Merge "[SMS] Define new SMS error code in HAL 1.6"
diff --git a/Android.bp b/Android.bp
index 9e1df13..00ba1e2 100644
--- a/Android.bp
+++ b/Android.bp
@@ -15,7 +15,6 @@
 cc_defaults {
     name: "VtsHalTargetTestDefaults",
     defaults: [
-        "vts_target_tests_defaults",
         "hidl_defaults",
     ],
 
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/IStreamOut.hal b/audio/7.0/IStreamOut.hal
index 38d750f..0951a9e 100644
--- a/audio/7.0/IStreamOut.hal
+++ b/audio/7.0/IStreamOut.hal
@@ -271,8 +271,6 @@
      * timestamp must correspond to N rather than N+M. The terms 'recent' and
      * 'small' are not defined. They reflect the quality of the implementation.
      *
-     * Optional method
-     *
      * @return retval operation completion status.
      * @return frames count of presented audio frames.
      * @return timeStamp associated clock time.
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/common/all-versions/default/service/service.cpp b/audio/common/all-versions/default/service/service.cpp
index 147d062..710ddce 100644
--- a/audio/common/all-versions/default/service/service.cpp
+++ b/audio/common/all-versions/default/service/service.cpp
@@ -87,7 +87,8 @@
         },
         {
             "Bluetooth Audio API",
-            "android.hardware.bluetooth.audio@2.0::IBluetoothAudioProvidersFactory"
+            "android.hardware.bluetooth.audio@2.1::IBluetoothAudioProvidersFactory",
+            "android.hardware.bluetooth.audio@2.0::IBluetoothAudioProvidersFactory",
         },
         // remove the old HIDL when Bluetooth Audio Hal V2 has offloading supported
         {
diff --git a/audio/core/all-versions/default/Conversions.cpp b/audio/core/all-versions/default/Conversions.cpp
index eddff55..0b6ad80 100644
--- a/audio/core/all-versions/default/Conversions.cpp
+++ b/audio/core/all-versions/default/Conversions.cpp
@@ -31,7 +31,7 @@
     // HAL assumes that the address is NUL-terminated.
     char halAddress[AUDIO_DEVICE_MAX_ADDRESS_LEN];
     memset(halAddress, 0, sizeof(halAddress));
-    uint32_t halDevice = static_cast<uint32_t>(address.device);
+    audio_devices_t halDevice = static_cast<audio_devices_t>(address.device);
     if (getAudioDeviceOutAllA2dpSet().count(halDevice) > 0 ||
         halDevice == AUDIO_DEVICE_IN_BLUETOOTH_A2DP) {
         snprintf(halAddress, sizeof(halAddress), "%02X:%02X:%02X:%02X:%02X:%02X",
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/audio/policy/1.0/vts/functional/Android.bp b/audio/policy/1.0/vts/functional/Android.bp
index a5ddee5..7b7cf0d 100644
--- a/audio/policy/1.0/vts/functional/Android.bp
+++ b/audio/policy/1.0/vts/functional/Android.bp
@@ -1,6 +1,5 @@
 cc_test {
     name: "VtsHalAudioPolicyV1_0TargetTest",
-    defaults: ["vts_target_tests_defaults"],
     srcs: [
         "ValidateEngineConfiguration.cpp",
     ],
diff --git a/authsecret/1.0/vts/functional/VtsHalAuthSecretV1_0TargetTest.cpp b/authsecret/1.0/vts/functional/VtsHalAuthSecretV1_0TargetTest.cpp
index 687c70c..c09b265 100644
--- a/authsecret/1.0/vts/functional/VtsHalAuthSecretV1_0TargetTest.cpp
+++ b/authsecret/1.0/vts/functional/VtsHalAuthSecretV1_0TargetTest.cpp
@@ -34,11 +34,19 @@
         authsecret = IAuthSecret::getService(GetParam());
         ASSERT_NE(authsecret, nullptr);
 
+        // Notify LSS to generate PIN code '1234' and corresponding secret.
+        (void)system("cmd lock_settings set-pin 1234");
+
         // All tests must enroll the correct secret first as this cannot be changed
         // without a factory reset and the order of tests could change.
         authsecret->primaryUserCredential(CORRECT_SECRET);
     }
 
+    static void TearDownTestSuite() {
+        // clean up PIN code after testing
+        (void)system("cmd lock_settings clear --old 1234");
+    }
+
     sp<IAuthSecret> authsecret;
     hidl_vec<uint8_t> CORRECT_SECRET{61, 93, 124, 240, 5, 0, 7, 201, 9, 129, 11, 12, 0, 14, 0, 16};
     hidl_vec<uint8_t> WRONG_SECRET{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
diff --git a/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp b/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp
index 638ecd5..8de9304 100644
--- a/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp
+++ b/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp
@@ -72,6 +72,8 @@
 using ::android::hardware::automotive::evs::V1_0::DisplayDesc;
 using ::android::hardware::automotive::evs::V1_0::DisplayState;
 using ::android::hardware::graphics::common::V1_0::PixelFormat;
+using ::android::frameworks::automotive::display::V1_0::HwDisplayConfig;
+using ::android::frameworks::automotive::display::V1_0::HwDisplayState;
 using IEvsCamera_1_0 = ::android::hardware::automotive::evs::V1_0::IEvsCamera;
 using IEvsCamera_1_1 = ::android::hardware::automotive::evs::V1_1::IEvsCamera;
 using IEvsDisplay_1_0 = ::android::hardware::automotive::evs::V1_0::IEvsDisplay;
@@ -605,7 +607,10 @@
     LOG(INFO) << "Display " << targetDisplayId << " is alreay in use.";
 
     // Get the display descriptor
-    pDisplay->getDisplayInfo_1_1([](const auto& config, const auto& state) {
+    pDisplay->getDisplayInfo_1_1([](const HwDisplayConfig& config, const HwDisplayState& state) {
+        ASSERT_GT(config.size(), 0);
+        ASSERT_GT(state.size(), 0);
+
         android::DisplayConfig* pConfig = (android::DisplayConfig*)config.data();
         const auto width = pConfig->resolution.getWidth();
         const auto height = pConfig->resolution.getHeight();
diff --git a/automotive/vehicle/2.0/default/Android.bp b/automotive/vehicle/2.0/default/Android.bp
index 9a0d89d..590adc5 100644
--- a/automotive/vehicle/2.0/default/Android.bp
+++ b/automotive/vehicle/2.0/default/Android.bp
@@ -137,7 +137,6 @@
     local_include_dirs: ["common/include/vhal_v2_0"],
     export_include_dirs: ["impl"],
     srcs: [
-        "impl/vhal_v2_0/EmulatedUserHal.cpp",
         "impl/vhal_v2_0/GeneratorHub.cpp",
         "impl/vhal_v2_0/JsonFakeValueGenerator.cpp",
         "impl/vhal_v2_0/LinearFakeValueGenerator.cpp",
diff --git a/automotive/vehicle/2.0/default/VehicleService.cpp b/automotive/vehicle/2.0/default/VehicleService.cpp
index 62a4f20..7e8deb6 100644
--- a/automotive/vehicle/2.0/default/VehicleService.cpp
+++ b/automotive/vehicle/2.0/default/VehicleService.cpp
@@ -31,7 +31,7 @@
 
 int main(int /* argc */, char* /* argv */ []) {
     auto store = std::make_unique<VehiclePropertyStore>();
-    auto connector = impl::makeEmulatedPassthroughConnector();
+    auto connector = std::make_unique<impl::EmulatedVehicleConnector>();
     auto userHal = connector->getEmulatedUserHal();
     auto hal = std::make_unique<impl::EmulatedVehicleHal>(store.get(), connector.get(), userHal);
     auto emulator = std::make_unique<impl::VehicleEmulator>(hal.get());
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
index e3b559e..80a1831 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
@@ -1095,6 +1095,30 @@
         {
                 .config =
                         {
+                                .prop = toInt(VehicleProperty::POWER_POLICY_REQ),
+                                .access = VehiclePropertyAccess::READ,
+                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                        },
+        },
+        {
+                .config =
+                        {
+                                .prop = toInt(VehicleProperty::POWER_POLICY_GROUP_REQ),
+                                .access = VehiclePropertyAccess::READ,
+                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                        },
+        },
+        {
+                .config =
+                        {
+                                .prop = toInt(VehicleProperty::CURRENT_POWER_POLICY),
+                                .access = VehiclePropertyAccess::READ_WRITE,
+                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                        },
+        },
+        {
+                .config =
+                        {
                                 .prop = toInt(VehicleProperty::WATCHDOG_ALIVE),
                                 .access = VehiclePropertyAccess::WRITE,
                                 .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.cpp
index 7f9362f..ed3f4a2 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.cpp
@@ -35,13 +35,33 @@
 
 namespace impl {
 
-class EmulatedPassthroughConnector : public PassthroughConnector {
-  public:
-    bool onDump(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
-};
+EmulatedUserHal* EmulatedVehicleConnector::getEmulatedUserHal() {
+    return &mEmulatedUserHal;
+}
 
-bool EmulatedPassthroughConnector::onDump(const hidl_handle& handle,
-                                          const hidl_vec<hidl_string>& options) {
+StatusCode EmulatedVehicleConnector::onSetProperty(const VehiclePropValue& value,
+                                                   bool updateStatus) {
+    if (mEmulatedUserHal.isSupported(value.prop)) {
+        LOG(INFO) << "onSetProperty(): property " << value.prop << " will be handled by UserHal";
+
+        const auto& ret = mEmulatedUserHal.onSetProperty(value);
+        if (!ret.ok()) {
+            LOG(ERROR) << "onSetProperty(): HAL returned error: " << ret.error().message();
+            return StatusCode(ret.error().code());
+        }
+        auto updatedValue = ret.value().get();
+        if (updatedValue != nullptr) {
+            LOG(INFO) << "onSetProperty(): updating property returned by HAL: "
+                      << toString(*updatedValue);
+            onPropertyValueFromCar(*updatedValue, updateStatus);
+        }
+        return StatusCode::OK;
+    }
+    return this->VehicleHalServer::onSetProperty(value, updateStatus);
+}
+
+bool EmulatedVehicleConnector::onDump(const hidl_handle& handle,
+                                      const hidl_vec<hidl_string>& options) {
     int fd = handle->data[0];
 
     if (options.size() > 0) {
@@ -68,10 +88,6 @@
     return true;
 }
 
-PassthroughConnectorPtr makeEmulatedPassthroughConnector() {
-    return std::make_unique<EmulatedPassthroughConnector>();
-}
-
 }  // namespace impl
 
 }  // namespace V2_0
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.h
index 57cbb8b..4c6c661 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.h
@@ -19,6 +19,7 @@
 
 #include <vhal_v2_0/VehicleConnector.h>
 
+#include "EmulatedUserHal.h"
 #include "VehicleHalClient.h"
 #include "VehicleHalServer.h"
 
@@ -30,10 +31,20 @@
 
 namespace impl {
 
-using PassthroughConnector = IPassThroughConnector<VehicleHalClient, VehicleHalServer>;
-using PassthroughConnectorPtr = std::unique_ptr<PassthroughConnector>;
+class EmulatedVehicleConnector : public IPassThroughConnector<VehicleHalClient, VehicleHalServer> {
+  public:
+    EmulatedVehicleConnector() {}
 
-PassthroughConnectorPtr makeEmulatedPassthroughConnector();
+    EmulatedUserHal* getEmulatedUserHal();
+
+    // Methods from VehicleHalServer
+    StatusCode onSetProperty(const VehiclePropValue& value, bool updateStatus) override;
+
+    bool onDump(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
+
+  private:
+    EmulatedUserHal mEmulatedUserHal;
+};
 
 }  // namespace impl
 
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.cpp
index 36f2534..0ee1835 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.cpp
@@ -41,10 +41,6 @@
     return mValuePool;
 }
 
-EmulatedUserHal* VehicleHalServer::getEmulatedUserHal() {
-    return &mEmulatedUserHal;
-}
-
 void VehicleHalServer::setValuePool(VehiclePropValuePool* valuePool) {
     if (!valuePool) {
         LOG(WARNING) << __func__ << ": Setting value pool to nullptr!";
@@ -185,22 +181,6 @@
 }
 
 StatusCode VehicleHalServer::onSetProperty(const VehiclePropValue& value, bool updateStatus) {
-    if (mEmulatedUserHal.isSupported(value.prop)) {
-        LOG(INFO) << "onSetProperty(): property " << value.prop << " will be handled by UserHal";
-
-        const auto& ret = mEmulatedUserHal.onSetProperty(value);
-        if (!ret.ok()) {
-            LOG(ERROR) << "onSetProperty(): HAL returned error: " << ret.error().message();
-            return StatusCode(ret.error().code());
-        }
-        auto updatedValue = ret.value().get();
-        if (updatedValue != nullptr) {
-            LOG(INFO) << "onSetProperty(): updating property returned by HAL: "
-                      << toString(*updatedValue);
-            onPropertyValueFromCar(*updatedValue, updateStatus);
-        }
-        return StatusCode::OK;
-    }
     LOG(DEBUG) << "onSetProperty(" << value.prop << ")";
 
     // Some properties need to be treated non-trivially
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.h
index fca78bc..117eadb 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.h
@@ -19,7 +19,6 @@
 #include <vhal_v2_0/VehicleObjectPool.h>
 #include <vhal_v2_0/VehicleServer.h>
 
-#include "EmulatedUserHal.h"
 #include "GeneratorHub.h"
 
 namespace android::hardware::automotive::vehicle::V2_0::impl {
@@ -38,8 +37,6 @@
     // Set the Property Value Pool used in this server
     void setValuePool(VehiclePropValuePool* valuePool);
 
-    EmulatedUserHal* getEmulatedUserHal();
-
   private:
     using VehiclePropValuePtr = recyclable_ptr<VehiclePropValue>;
 
@@ -56,11 +53,6 @@
     VehiclePropValuePtr createHwInputKeyProp(VehicleHwKeyInputAction action, int32_t keyCode,
                                              int32_t targetDisplay);
 
-    // data members
-
-  protected:
-    EmulatedUserHal mEmulatedUserHal;
-
   private:
     GeneratorHub mGeneratorHub{
             std::bind(&VehicleHalServer::onFakeValueGenerated, this, std::placeholders::_1)};
diff --git a/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal
index 11fe70e..931fee4 100644
--- a/automotive/vehicle/2.0/types.hal
+++ b/automotive/vehicle/2.0/types.hal
@@ -2921,6 +2921,65 @@
         | VehicleArea:GLOBAL),
 
     /**
+     * Defines a request to apply power policy.
+     *
+     * VHAL sets this property to change car power policy. Car power policy service subscribes to
+     * this property and actually changes the power policy.
+     * The request is made by setting the VehiclePropValue with the ID of a power policy which is
+     * defined at /vendor/etc/power_policy.xml. If the given ID is not defined, car power policy
+     * service ignores the request and the current power policy is maintained.
+     *
+     *   string: "sample_policy_id" // power policy ID
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     */
+    POWER_POLICY_REQ = (
+        0x0F21
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:STRING
+        | VehicleArea:GLOBAL),
+
+    /**
+     * Defines a request to set the power polic group used to decide a default power policy per
+     * power status transition.
+     *
+     * VHAL sets this property with the ID of a power policy group in order to set the default power
+     * policy applied at power status transition. Power policy groups are defined at
+     * /vendor/etc/power_policy.xml. If the given ID is not defined, car power policy service
+     * ignores the request.
+     * Car power policy service subscribes to this property and sets the power policy group.
+     * The actual application of power policy takes place when the system power status changes and
+     * there is a valid mapped power policy for the new power status.
+     *
+     *   string: "sample_policy_group_id" // power policy group ID
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     */
+    POWER_POLICY_GROUP_REQ = (
+        0x0F22
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:STRING
+        | VehicleArea:GLOBAL),
+
+    /**
+     * Notifies the current power policy to VHAL layer.
+     *
+     * Car power policy service sets this property when the current power policy is changed.
+     *
+     *   string: "sample_policy_id" // power policy ID
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    CURRENT_POWER_POLICY = (
+        0x0F23
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:STRING
+        | VehicleArea:GLOBAL),
+
+    /**
      * Defines an event that car watchdog updates to tell it's alive.
      *
      * Car watchdog sets this property to system uptime in milliseconds at every 3 second.
@@ -2938,8 +2997,8 @@
     /**
      * Defines a process terminated by car watchdog and the reason of termination.
      *
-     * int32Values[0]: 1         // ProcessTerminationReason showing why a process is terminated.
-     * string: "/system/bin/log" // Process execution command.
+     *   int32Values[0]: 1         // ProcessTerminationReason showing why a process is terminated.
+     *   string: "/system/bin/log" // Process execution command.
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:WRITE
diff --git a/biometrics/face/aidl/Android.bp b/biometrics/face/aidl/Android.bp
new file mode 100644
index 0000000..4f8b71d
--- /dev/null
+++ b/biometrics/face/aidl/Android.bp
@@ -0,0 +1,22 @@
+aidl_interface {
+    name: "android.hardware.biometrics.face",
+    vendor_available: true,
+    srcs: [
+        "android/hardware/biometrics/face/**/*.aidl",
+    ],
+    imports: [
+        "android.hardware.biometrics.common",
+        "android.hardware.common",
+        "android.hardware.keymaster",
+    ],
+    stability: "vintf",
+    backend: {
+        java: {
+            enabled: false,
+            platform_apis: false,
+        },
+        cpp: {
+            enabled: false,
+        },
+    },
+}
diff --git a/powerstats/aidl/aidl_api/android.hardware.powerstats/current/android/hardware/powerstats/RailInfo.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/AcquiredInfo.aidl
similarity index 65%
rename from powerstats/aidl/aidl_api/android.hardware.powerstats/current/android/hardware/powerstats/RailInfo.aidl
rename to biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/AcquiredInfo.aidl
index 413ea0d..011b711 100644
--- a/powerstats/aidl/aidl_api/android.hardware.powerstats/current/android/hardware/powerstats/RailInfo.aidl
+++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/AcquiredInfo.aidl
@@ -15,11 +15,30 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.powerstats;
-@VintfStability
-parcelable RailInfo {
-  int railIndex;
-  String railName;
-  String subsysName;
-  int samplingRateHz;
+package android.hardware.biometrics.face;
+@Backing(type="byte") @VintfStability
+enum AcquiredInfo {
+  GOOD = 0,
+  INSUFFICIENT = 1,
+  TOO_BRIGHT = 2,
+  TOO_DARK = 3,
+  TOO_CLOSE = 4,
+  TOO_FAR = 5,
+  FACE_TOO_HIGH = 6,
+  FACE_TOO_LOW = 7,
+  FACE_TOO_RIGHT = 8,
+  FACE_TOO_LEFT = 9,
+  POOR_GAZE = 10,
+  NOT_DETECTED = 11,
+  TOO_MUCH_MOTION = 12,
+  RECALIBRATE = 13,
+  TOO_DIFFERENT = 14,
+  TOO_SIMILAR = 15,
+  PAN_TOO_EXTREME = 16,
+  TILT_TOO_EXTREME = 17,
+  ROLL_TOO_EXTREME = 18,
+  FACE_OBSCURED = 19,
+  START = 20,
+  SENSOR_DIRTY = 21,
+  VENDOR = 22,
 }
diff --git a/common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/MQDescriptor.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/Error.aidl
similarity index 81%
copy from common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/MQDescriptor.aidl
copy to biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/Error.aidl
index c9fe1d7..15fcbf9 100644
--- a/common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/MQDescriptor.aidl
+++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/Error.aidl
@@ -15,11 +15,14 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.common;
-@VintfStability
-parcelable MQDescriptor {
-  android.hardware.common.GrantorDescriptor[] grantors;
-  ParcelFileDescriptor fileDescriptor;
-  int quantum;
-  int flags;
+package android.hardware.biometrics.face;
+@Backing(type="byte") @VintfStability
+enum Error {
+  HW_UNAVAILABLE = 1,
+  UNABLE_TO_PROCESS = 2,
+  TIMEOUT = 3,
+  NO_SPACE = 4,
+  CANCELED = 5,
+  UNABLE_TO_REMOVE = 6,
+  VENDOR = 8,
 }
diff --git a/common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/UnsynchronizedWrite.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/FaceSensorType.aidl
similarity index 88%
copy from common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/UnsynchronizedWrite.aidl
copy to biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/FaceSensorType.aidl
index e390d20..943129e 100644
--- a/common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/UnsynchronizedWrite.aidl
+++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/FaceSensorType.aidl
@@ -15,8 +15,9 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.common;
-@VintfStability
-enum UnsynchronizedWrite {
-  EMPTY = 0,
+package android.hardware.biometrics.face;
+@Backing(type="byte") @VintfStability
+enum FaceSensorType {
+  RGB = 0,
+  IR = 1,
 }
diff --git a/common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/MQDescriptor.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/IFace.aidl
similarity index 78%
copy from common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/MQDescriptor.aidl
copy to biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/IFace.aidl
index c9fe1d7..518fb14 100644
--- a/common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/MQDescriptor.aidl
+++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/IFace.aidl
@@ -15,11 +15,9 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.common;
+package android.hardware.biometrics.face;
 @VintfStability
-parcelable MQDescriptor {
-  android.hardware.common.GrantorDescriptor[] grantors;
-  ParcelFileDescriptor fileDescriptor;
-  int quantum;
-  int flags;
+interface IFace {
+  android.hardware.biometrics.face.SensorProps[] getSensorProps();
+  android.hardware.biometrics.face.ISession createSession(in int sensorId, in int userId, in android.hardware.biometrics.face.ISessionCallback cb);
 }
diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/ISession.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/ISession.aidl
new file mode 100644
index 0000000..c9b443d
--- /dev/null
+++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/ISession.aidl
@@ -0,0 +1,31 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.biometrics.face;
+@VintfStability
+interface ISession {
+  void generateChallenge(in int cookie, in int sensorId, in int userId, in int timeoutSec);
+  void revokeChallenge(in int cookie, in int sensorId, in int userId, in long challenge);
+  android.hardware.biometrics.common.ICancellationSignal enroll(in int cookie, in android.hardware.keymaster.HardwareAuthToken hat, in android.hardware.common.NativeHandle previewSurface);
+  android.hardware.biometrics.common.ICancellationSignal authenticate(in int cookie, in long operationId);
+  android.hardware.biometrics.common.ICancellationSignal detectInteraction(in int cookie);
+  void enumerateEnrollments(in int cookie);
+  void removeEnrollments(in int cookie, in int[] enrollmentIds);
+  void getAuthenticatorId(in int cookie);
+  void invalidateAuthenticatorId(in int cookie);
+  void resetLockout(in int cookie, in android.hardware.keymaster.HardwareAuthToken hat);
+}
diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/ISessionCallback.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/ISessionCallback.aidl
new file mode 100644
index 0000000..477ba5a
--- /dev/null
+++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/ISessionCallback.aidl
@@ -0,0 +1,37 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.biometrics.face;
+@VintfStability
+interface ISessionCallback {
+  void onStateChanged(in int cookie, in android.hardware.biometrics.face.SessionState state);
+  void onChallengeGenerated(in int sensorId, in int userId, in long challenge);
+  void onChallengeRevoked(in int sensorId, in int userId, in long challenge);
+  void onAcquired(in android.hardware.biometrics.face.AcquiredInfo info, in int vendorCode);
+  void onError(in android.hardware.biometrics.face.Error error, in int vendorCode);
+  void onEnrollmentProgress(in int enrollmentId, int remaining);
+  void onAuthenticationSucceeded(in int enrollmentId, in android.hardware.keymaster.HardwareAuthToken hat);
+  void onAuthenticationFailed();
+  void onLockoutTimed(in long durationMillis);
+  void onLockoutPermanent();
+  void onLockoutCleared();
+  void onInteractionDetected();
+  void onEnrollmentsEnumerated(in int[] enrollmentIds);
+  void onEnrollmentsRemoved(in int[] enrollmentIds);
+  void onAuthenticatorIdRetrieved(in long authenticatorId);
+  void onAuthenticatorIdInvalidated();
+}
diff --git a/common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/MQDescriptor.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/SensorProps.aidl
similarity index 82%
copy from common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/MQDescriptor.aidl
copy to biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/SensorProps.aidl
index c9fe1d7..9f977f5 100644
--- a/common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/MQDescriptor.aidl
+++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/SensorProps.aidl
@@ -15,11 +15,10 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.common;
+package android.hardware.biometrics.face;
 @VintfStability
-parcelable MQDescriptor {
-  android.hardware.common.GrantorDescriptor[] grantors;
-  ParcelFileDescriptor fileDescriptor;
-  int quantum;
-  int flags;
+parcelable SensorProps {
+  android.hardware.biometrics.common.CommonProps commonProps;
+  android.hardware.biometrics.face.FaceSensorType sensorType;
+  boolean halControlsPreview;
 }
diff --git a/common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/MQDescriptor.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/SessionState.aidl
similarity index 71%
copy from common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/MQDescriptor.aidl
copy to biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/SessionState.aidl
index c9fe1d7..8e5139b 100644
--- a/common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/MQDescriptor.aidl
+++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/SessionState.aidl
@@ -15,11 +15,19 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.common;
-@VintfStability
-parcelable MQDescriptor {
-  android.hardware.common.GrantorDescriptor[] grantors;
-  ParcelFileDescriptor fileDescriptor;
-  int quantum;
-  int flags;
+package android.hardware.biometrics.face;
+@Backing(type="byte") @VintfStability
+enum SessionState {
+  IDLING = 0,
+  TERMINATED = 1,
+  GENERATING_CHALLENGE = 2,
+  REVOKING_CHALLENGE = 3,
+  ENROLLING = 4,
+  AUTHENTICATING = 5,
+  DETECTING_INTERACTION = 6,
+  ENUMERATING_ENROLLMENTS = 7,
+  REMOVING_ENROLLMENTS = 8,
+  GETTING_AUTHENTICATOR_ID = 9,
+  INVALIDATING_AUTHENTICATOR_ID = 10,
+  RESETTING_LOCKOUT = 11,
 }
diff --git a/biometrics/face/aidl/android/hardware/biometrics/face/AcquiredInfo.aidl b/biometrics/face/aidl/android/hardware/biometrics/face/AcquiredInfo.aidl
new file mode 100644
index 0000000..fffb418
--- /dev/null
+++ b/biometrics/face/aidl/android/hardware/biometrics/face/AcquiredInfo.aidl
@@ -0,0 +1,219 @@
+/*
+ * 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.
+ */
+
+package android.hardware.biometrics.face;
+
+@VintfStability
+@Backing(type="byte")
+enum AcquiredInfo {
+
+    /**
+     * The acquired face data was good, no further user interaction is necessary.
+     */
+    GOOD = 0,
+
+    /**
+     * The acquired face data was too noisy or did not have sufficient detail.
+     * This is a catch-all for all acquisition errors not captured by the other
+     * constants.
+     */
+    INSUFFICIENT = 1,
+
+    /**
+     * Because there was too much ambient light, the captured face data was too
+     * bright. It's reasonable to return this after multiple
+     * AcquiredInfo.INSUFFICIENT.
+     *
+     * The user is expected to take action to retry the operation in better
+     * lighting conditions when this is returned.
+     */
+    TOO_BRIGHT = 2,
+
+    /**
+     * Because there was not enough illumination, the captured face data was too
+     * dark. It's reasonable to return this after multiple
+     * AcquiredInfo.INSUFFICIENT.
+     *
+     * The user is expected to take action to retry the operation in better
+     * lighting conditions when this is returned.
+     */
+    TOO_DARK = 3,
+
+    /**
+     * The detected face is too close to the sensor, and the image cannot be
+     * processed.
+     *
+     * The user is expected to be informed to move further from the sensor when
+     * this is returned.
+     */
+    TOO_CLOSE = 4,
+
+    /**
+     * The detected face is too small, as the user might be too far away from
+     * the sensor.
+     *
+     * The user is expected to be informed to move closer to the sensor when
+     * this is returned.
+     */
+    TOO_FAR = 5,
+
+    /**
+     * Only the upper part of the face was detected. The sensor's field of view
+     * is too high.
+     *
+     * The user should be informed to move up with respect to the sensor when
+     * this is returned.
+     */
+    FACE_TOO_HIGH = 6,
+
+    /**
+     * Only the lower part of the face was detected. The sensor's field of view
+     * is too low.
+     *
+     * The user should be informed to move down with respect to the sensor when
+     * this is returned.
+     */
+    FACE_TOO_LOW = 7,
+
+    /**
+     * Only the right part of the face was detected. The sensor's field of view
+     * is too far right.
+     *
+     * The user should be informed to move to the right with respect to the
+     * sensor when this is returned.
+     */
+    FACE_TOO_RIGHT = 8,
+
+    /**
+     * Only the left part of the face was detected. The sensor's field of view
+     * is too far left.
+     *
+     * The user should be informed to move to the left with respect to the
+     * sensor when this is returned.
+     */
+    FACE_TOO_LEFT = 9,
+
+    /**
+     * The user's eyes have strayed away from the sensor. If this message is
+     * sent, the user should be informed to look at the device. If the user
+     * can't be found in the frame, one of the other acquisition messages
+     * must be sent, e.g. NOT_DETECTED.
+     */
+    POOR_GAZE = 10,
+
+    /**
+     * No face was detected within the sensor's field of view.
+     *
+     * The user should be informed to point the sensor to a face when this is
+     * returned.
+     */
+    NOT_DETECTED = 11,
+
+    /**
+     * Too much motion was detected.
+     *
+     * The user should be informed to keep their face steady relative to the
+     * sensor.
+     */
+    TOO_MUCH_MOTION = 12,
+
+    /**
+     * The sensor needs to be re-calibrated. This is an unexpected condition,
+     * and must only be sent if a serious, uncorrectable, and unrecoverable
+     * calibration issue is detected which requires user intervention, e.g.
+     * re-enrolling. The expected response to this message is to direct the
+     * user to re-enroll.
+     */
+    RECALIBRATE = 13,
+
+    /**
+     * The face is too different from a previous acquisition. This condition
+     * only applies to enrollment. This can happen if the user passes the
+     * device to someone else in the middle of enrollment.
+     */
+    TOO_DIFFERENT = 14,
+
+    /**
+     * The face is too similar to a previous acquisition. This condition only
+     * applies to enrollment. The user should change their pose.
+     */
+    TOO_SIMILAR = 15,
+
+    /**
+     * The magnitude of the pan angle of the user’s face with respect to the sensor’s
+     * capture plane is too high.
+     *
+     * The pan angle is defined as the angle swept out by the user’s face turning
+     * their neck left and right. The pan angle would be zero if the user faced the
+     * camera directly.
+     *
+     * The user should be informed to look more directly at the camera.
+     */
+    PAN_TOO_EXTREME = 16,
+
+    /**
+     * The magnitude of the tilt angle of the user’s face with respect to the sensor’s
+     * capture plane is too high.
+     *
+     * The tilt angle is defined as the angle swept out by the user’s face looking up
+     * and down. The tilt angle would be zero if the user faced the camera directly.
+     *
+     * The user should be informed to look more directly at the camera.
+     */
+    TILT_TOO_EXTREME = 17,
+
+    /**
+     * The magnitude of the roll angle of the user’s face with respect to the sensor’s
+     * capture plane is too high.
+     *
+     * The roll angle is defined as the angle swept out by the user’s face tilting their head
+     * towards their shoulders to the left and right. The roll angle would be zero if the user's
+     * head is vertically aligned with the camera.
+     *
+     * The user should be informed to look more directly at the camera.
+     */
+    ROLL_TOO_EXTREME = 18,
+
+   /**
+     * The user’s face has been obscured by some object.
+     *
+     * The user should be informed to remove any objects from the line of sight from
+     * the sensor to the user’s face.
+     */
+    FACE_OBSCURED = 19,
+
+    /**
+     * This message represents the earliest message sent at the beginning of the authentication
+     * pipeline. It is expected to be used to measure latency. For example, in a camera-based
+     * authentication system it's expected to be sent prior to camera initialization. Note this
+     * should be sent whenever authentication is restarted (see IBiometricsFace#userActivity).
+     * The framework will measure latency based on the time between the last START message and the
+     * onAuthenticated callback.
+     */
+    START = 20,
+
+    /**
+     * The sensor is dirty. The user should be informed to clean the sensor.
+     */
+    SENSOR_DIRTY = 21,
+
+    /**
+     * Vendor-specific acquisition message. See ISessionCallback#onAcquired vendorCode
+     * documentation.
+    */
+    VENDOR = 22
+}
+
diff --git a/biometrics/face/aidl/android/hardware/biometrics/face/Error.aidl b/biometrics/face/aidl/android/hardware/biometrics/face/Error.aidl
new file mode 100644
index 0000000..1d02456
--- /dev/null
+++ b/biometrics/face/aidl/android/hardware/biometrics/face/Error.aidl
@@ -0,0 +1,92 @@
+/*
+ * 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.
+ */
+
+package android.hardware.biometrics.face;
+
+@VintfStability
+@Backing(type="byte")
+enum Error {
+    /**
+     * Reserved for testing and to keep subsequent numbering consistent with
+     * older interfaces.
+     *
+     * NO_ERROR = 0,
+     */
+
+    /**
+     * A hardware error has occurred that cannot be resolved. Try again later.
+     */
+    HW_UNAVAILABLE = 1,
+
+    /**
+     * The current enroll or authenticate operation could not be completed,
+     * e.g. the sensor was unable to process the current image or the HAT was
+     * invalid.
+     */
+    UNABLE_TO_PROCESS = 2,
+
+    /**
+     * The current operation took too long to complete. This is intended to
+     * prevent programs from blocking the face HAL indefinitely. The timeout is
+     * framework and sensor-specific, but is generally on the order of 30
+     * seconds.
+     *
+     * The timeout is a device-specific time meant to optimize power. For
+     * example after 30 seconds of searching for a face it can be use to
+     * indicate that the implementation is no longer looking and the framework
+     * should restart the operation on the next user interaction.
+     */
+    TIMEOUT = 3,
+
+    /**
+     * The current operation could not be completed because there is not enough
+     * storage space remaining to do so.
+     */
+    NO_SPACE = 4,
+
+    /**
+     * The current operation has been cancelled. This may happen if a new
+     * request (authenticate, remove, enumerate, enroll) is initiated while
+     * an on-going operation is in progress, or if cancel() was called.
+     */
+    CANCELED = 5,
+
+    /**
+     * The current remove operation could not be completed; the face template
+     * provided could not be removed.
+     */
+    UNABLE_TO_REMOVE = 6,
+
+    /**
+     * Reserved to maintain backwards compatibility. See
+     * ISessionCallback#onLockoutTimed instead.
+     *
+     * LOCKOUT = 7,
+     */
+
+    /**
+     * Used to enable a vendor-specific error message.
+     */
+    VENDOR = 8,
+
+    /**
+     * Reserved to maintain backwards compatibility. See
+     * ISessionCallback#onLockoutPermanent instead.
+     *
+     * LOCKOUT_PERMANENT = 9
+     */
+}
+
diff --git a/tests/safeunion/1.0/IOtherInterface.hal b/biometrics/face/aidl/android/hardware/biometrics/face/FaceSensorType.aidl
similarity index 73%
copy from tests/safeunion/1.0/IOtherInterface.hal
copy to biometrics/face/aidl/android/hardware/biometrics/face/FaceSensorType.aidl
index cdaf847..766f732 100644
--- a/tests/safeunion/1.0/IOtherInterface.hal
+++ b/biometrics/face/aidl/android/hardware/biometrics/face/FaceSensorType.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 The Android Open Source Project
+ * 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.
@@ -14,8 +14,11 @@
  * limitations under the License.
  */
 
-package android.hardware.tests.safeunion@1.0;
+package android.hardware.biometrics.face;
 
-interface IOtherInterface {
-    concatTwoStrings(string a, string b) generates (string result);
-};
+@VintfStability
+@Backing(type="byte")
+enum FaceSensorType {
+    RGB,
+    IR
+}
diff --git a/biometrics/face/aidl/android/hardware/biometrics/face/IFace.aidl b/biometrics/face/aidl/android/hardware/biometrics/face/IFace.aidl
new file mode 100644
index 0000000..e9a66e2
--- /dev/null
+++ b/biometrics/face/aidl/android/hardware/biometrics/face/IFace.aidl
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+package android.hardware.biometrics.face;
+
+import android.hardware.biometrics.face.ISession;
+import android.hardware.biometrics.face.ISessionCallback;
+import android.hardware.biometrics.face.SensorProps;
+
+@VintfStability
+interface IFace {
+    /**
+     * getSensorProps:
+     *
+     * @return A list of properties for all face sensors available to the HAL.
+     */
+    SensorProps[] getSensorProps();
+
+    /**
+     * createSession:
+     *
+     * Creates a session that can be used by the framework to perform operations such as
+     * enroll, authenticate, etc. for the given sensorId and userId.
+     *
+     * Implementations must store user-specific state or metadata in /data/vendor_de/<user>/facedata
+     * as specified by the SELinux policy. The directory /data/vendor_de is managed by vold (see
+     * vold_prepare_subdirs.cpp). Implementations may store additional user-specific data, such as
+     * embeddings or templates in StrongBox.
+     *
+     * @param sensorId The sensorId with which this session is being created.
+     * @param userId The userId with which this session is being created.
+     * @param cb A callback to notify the framework about the session's results and events.
+     * @return A new session.
+     */
+    ISession createSession(in int sensorId, in int userId, in ISessionCallback cb);
+
+}
diff --git a/biometrics/face/aidl/android/hardware/biometrics/face/ISession.aidl b/biometrics/face/aidl/android/hardware/biometrics/face/ISession.aidl
new file mode 100644
index 0000000..5145b1e
--- /dev/null
+++ b/biometrics/face/aidl/android/hardware/biometrics/face/ISession.aidl
@@ -0,0 +1,369 @@
+/*
+ * 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.
+ */
+
+package android.hardware.biometrics.face;
+
+import android.hardware.biometrics.common.ICancellationSignal;
+import android.hardware.keymaster.HardwareAuthToken;
+import android.hardware.common.NativeHandle;
+
+/**
+ * A session is a collection of immutable state (sensorId, userId), mutable state (SessionState),
+ * methods available for the framework to call, and a callback (ISessionCallback) to notify the
+ * framework about the events and results. A session is used to establish communication between
+ * the framework and the HAL.
+ */
+@VintfStability
+interface ISession {
+   /**
+     * generateChallenge:
+     *
+     * Begins a secure transaction request. Note that the challenge by itself is not useful. It only
+     * becomes useful when wrapped in a verifiable message such as a HardwareAuthToken.
+     *
+     * Canonical example:
+     *   1) User requests an operation, such as face enrollment.
+     *   2) Face enrollment cannot happen until the user confirms their lockscreen credential
+     *      (PIN/Pattern/Password).
+     *   3) However, the biometric subsystem does not want just "any" proof of credential
+     *      confirmation. It needs proof that the user explicitly authenticated credential in order
+     *      to allow addition of biometric enrollments.
+     * To secure this path, the following path is taken:
+     *   1) Upon user requesting face enroll, the framework requests
+     *      IFace#generateChallenge
+     *   2) Framework sends the challenge to the credential subsystem, and upon credential
+     *      confirmation, a HAT is created, containing the challenge in the "challenge" field.
+     *   3) Framework sends the HAT to the HAL, e.g. ISession#enroll.
+     *   4) Implementation verifies the authenticity and integrity of the HAT.
+     *   5) Implementation now has confidence that the user entered their credential to allow
+     *      biometric enrollment.
+     *
+     * Note that the interface allows multiple in-flight challenges. For example, invoking
+     * generateChallenge(0, 0, timeoutSec) twice does not invalidate the first challenge. The
+     * challenge is invalidated only when:
+     *   1) The provided timeout expires, or
+     *   2) IFace#revokeChallenge is invoked
+     *
+     * For example, the following is a possible table of valid challenges:
+     * ----------------------------------------------
+     * | SensorId | UserId | ValidUntil | Challenge |
+     * |----------|--------|------------|-----------|
+     * | 0        | 0      | <Time1>    | <Random1> |
+     * | 0        | 0      | <Time2>    | <Random2> |
+     * | 1        | 0      | <Time3>    | <Random3> |
+     * | 0        | 10     | <Time4>    | <Random4> |
+     * ----------------------------------------------
+     *
+     * @param cookie A unique number identifying this operation
+     * @param sensorId Sensor to associate the challenge with
+     * @param userId User to associate the challenge with
+     * @param timeoutSec Duration for which the challenge is valid for
+     */
+    void generateChallenge(in int cookie, in int sensorId, in int userId, in int timeoutSec);
+
+    /**
+     * revokeChallenge:
+     *
+     * Revokes a challenge that was previously generated. Note that if an invalid combination of
+     * parameters is requested, the implementation must still notify the framework using the
+     * provided callback.
+     *
+     * @param cookie A unique number identifying this operation
+     * @param sensorId Sensor that the revocation should apply to.
+     * @param userId User that the revocation should apply to.
+     * @param challenge Challenge that should be revoked.
+     */
+    void revokeChallenge(in int cookie, in int sensorId, in int userId, in long challenge);
+
+    /**
+     * enroll:
+     *
+     * A request to add a face enrollment.
+     *
+     * Once the HAL is able to start processing the enrollment request, it must notify the framework
+     * via ISessionCallback#onStateChanged with SessionState::ENROLLING.
+     *
+     * At any point during enrollment, if a non-recoverable error occurs, the HAL must notify the
+     * framework via ISessionCallback#onError with the applicable enrollment-specific error, and
+     * then send ISessionCallback#onStateChanged(cookie, SessionState::IDLING) if no subsequent
+     * operation is in the queue.
+     *
+     * Before capturing face data, the implementation must first verify the authenticity and
+     * integrity of the provided HardwareAuthToken. In addition, it must check that the challenge
+     * within the provided HardwareAuthToken is valid. See IFace#generateChallenge. If any of
+     * the above checks fail, the framework must be notified via ISessionCallback#onError and the
+     * HAL must notify the framework when it returns to the idle state. See
+     * Error::UNABLE_TO_PROCESS.
+     *
+     * During enrollment, the implementation may notify the framework via
+     * ISessionCallback#onAcquired with messages that may be used to guide the user. This callback
+     * can be invoked multiple times if necessary. Similarly, the framework may be notified of
+     * enrollment progress changes via ISessionCallback#onEnrollmentProgress. Once the framework is
+     * notified that there are 0 "remaining" steps, the framework may cache the "enrollmentId". See
+     * ISessionCallback#onEnrollmentProgress for more info. The HAL must notify the framework once
+     * it returns to the idle state.
+     *
+     * When a finger is successfully added and before the framework is notified of remaining=0, the
+     * implementation MUST update and associate this (sensorId, userId) pair with a new new
+     * entropy-encoded random identifier. See ISession#getAuthenticatorId for more information.
+     *
+     * @param cookie An identifier used to track subsystem operations related to this call path. The
+     *               client must guarantee that it is unique per ISession.
+     * @param previewSurface A surface provided by the framework if SensorProps#halControlsPreview is
+     *                       set to true. The HAL must send the preview frames to previewSurface if
+     *                       it's not null.
+     * @param hat See above documentation.
+     * @return ICancellationSignal An object that can be used by the framework to cancel this
+     * operation.
+     */
+    ICancellationSignal enroll(in int cookie, in HardwareAuthToken hat, in NativeHandle previewSurface);
+
+    /**
+     * authenticate:
+     *
+     * A request to start looking for faces to authenticate.
+     *
+     * Once the HAL is able to start processing the authentication request, it must notify framework
+     * via ISessionCallback#onStateChanged with SessionState::AUTHENTICATING.
+     *
+     * At any point during authentication, if a non-recoverable error occurs, the HAL must notify
+     * the framework via ISessionCallback#onError with the applicable authentication-specific error,
+     * and then send ISessionCallback#onStateChanged(cookie, SessionState::IDLING) if no
+     * subsequent operation is in the queue.
+     *
+     * During authentication, the implementation may notify the framework via
+     * ISessionCallback#onAcquired with messages that may be used to guide the user. This callback
+     * can be invoked multiple times if necessary.
+     *
+     * The HAL must notify the framework of accepts/rejects via ISessionCallback#onAuthentication*.
+     *
+     * The authentication lifecycle ends when either
+     *   1) A face is accepted, and ISessionCallback#onAuthenticationSucceeded is invoked, or
+     *   2) Any non-recoverable error occurs (such as lockout). See the full list of
+     *      authentication-specific errors in the Error enum.
+     *
+     * Note that upon successful authentication, the lockout counter for this (sensorId, userId)
+     * pair must be cleared.
+     *
+     * Note that upon successful authentication, ONLY sensors configured as SensorStrength::STRONG
+     * are allowed to create and send a HardwareAuthToken to the framework. See the Android CDD for
+     * more details. For SensorStrength::STRONG sensors, the HardwareAuthToken's "challenge" field
+     * must be set with the operationId passed in during #authenticate. If the sensor is NOT
+     * SensorStrength::STRONG, the HardwareAuthToken MUST be null.
+     *
+     * @param cookie An identifier used to track subsystem operations related to this call path. The
+     *               client must guarantee that it is unique per ISession.
+     * @param operationId For sensors configured as SensorStrength::STRONG, this must be used ONLY
+     *                    upon successful authentication and wrapped in the HardwareAuthToken's
+     *                    "challenge" field and sent to the framework via
+     *                    ISessionCallback#onAuthenticated. The operationId is an opaque identifier
+     *                    created from a separate secure subsystem such as, but not limited to
+     *                    KeyStore/KeyMaster. The HardwareAuthToken can then be used as an
+     *                    attestation for the provided operation. For example, this is used
+     *                    to unlock biometric-bound auth-per-use keys (see
+     *                    setUserAuthenticationParameters in KeyGenParameterSpec.Builder and
+     *                    KeyProtection.Builder.
+     * @return ICancellationSignal An object that can be used by the framework to cancel this
+     * operation.
+     */
+    ICancellationSignal authenticate(in int cookie, in long operationId);
+
+    /**
+     * detectInteraction:
+     *
+     * A request to start looking for faces without performing matching.
+     *
+     * Once the HAL is able to start processing this request, it must notify the framework via
+     * ISessionCallback#onStateChanged with SessionState::DETECTING_INTERACTION.
+     *
+     * The framework will use this method in cases where determing user presence is required, but
+     * identifying/authentication is not. For example, when the device is encrypted (first boot) or
+     * in lockdown mode.
+     *
+     * At any point during detectInteraction, if a non-recoverable error occurs, the HAL must notify
+     * the framework via ISessionCallback#onError with the applicable error, and then send
+     * ISessionCallback#onStateChanged(cookie, SessionState::IDLING) if no subsequent operation is
+     * in the queue.
+     *
+     * The implementation must only check for a face-like image was detected (e.g. to
+     * minimize interactions due to non-face objects), and the lockout counter must not
+     * be modified.
+     *
+     * Upon detecting any face, the implementation must invoke
+     * ISessionCallback#onInteractionDetected.
+     *
+     * The lifecycle of this operation ends when either
+     * 1) Any face is detected and the framework is notified via
+     *    ISessionCallback#onInteractiondetected
+     * 2) The operation was cancelled by the framework (see ICancellationSignal)
+     * 3) The HAL ends the operation, for example when a subsequent operation pre-empts this one.
+     *
+     * Note that if the operation is canceled, the implementation must notify the framework via
+     * ISessionCallback#onError with Error::CANCELED.
+     *
+     * @param cookie An identifier used to track subsystem operations related to this call path.
+     *               The framework will guarantee that it is unique per ISession.
+     * @return ICancellationSignal An object that can be used by the framework to cancel this
+     * operation.
+     */
+    ICancellationSignal detectInteraction(in int cookie);
+
+    /*
+     * enumerateEnrollments:
+     *
+     * A request to enumerate (list) the enrollments for this (sensorId, userId) pair. The
+     * framework typically uses this to ensure that its cache is in sync with the HAL.
+     *
+     * Once the HAL is able to start processing this request, it must notify the framework via
+     * ISessionCallback#onStateChanged with SessionState::ENUMERATING_ENROLLMENTS.
+     *
+     * The implementation must then notify the framework with a list of enrollments applicable
+     * for the current session via ISessionCallback#onEnrollmentsEnumerated.
+     *
+     * @param cookie An identifier used to track subsystem operations related to this call path.
+     *               The framework will guarantee that it is unique per ISession.
+     */
+    void enumerateEnrollments(in int cookie);
+
+    /**
+     * removeEnrollments:
+     *
+     * A request to remove the enrollments for this (sensorId, userId) pair.
+     *
+     * Once the HAL is able to start processing this request, it must notify the framework via
+     * ISessionCallback#onStateChanged with SessionState::REMOVING_ENROLLMENTS.
+     *
+     * After removing the enrollmentIds from everywhere necessary (filesystem, secure subsystems,
+     * etc), the implementation must notify the framework via ISessionCallback#onEnrollmentsRemoved.
+     *
+     * @param cookie An identifier used to track subsystem operations related to this call path.
+     *               The framework will guarantee that it is unique per ISession.
+     */
+    void removeEnrollments(in int cookie, in int[] enrollmentIds);
+
+    /**
+     * getAuthenticatorId:
+     *
+     * MUST return 0 via ISessionCallback#onAuthenticatorIdRetrieved for sensors that are configured
+     * as SensorStrength::WEAK or SensorStrength::CONVENIENCE.
+     *
+     * The following only applies to sensors that are configured as SensorStrength::STRONG.
+     *
+     * The authenticatorId is a (sensorId, user)-specific identifier which can be used during key
+     * generation and key import to to associate a key (in KeyStore / KeyMaster) with the current
+     * set of enrolled faces. For example, the following public Android APIs allow for keys
+     * to be invalidated when the user adds a new enrollment after the key was created:
+     * KeyGenParameterSpec.Builder.setInvalidatedByBiometricEnrollment and
+     * KeyProtection.Builder.setInvalidatedByBiometricEnrollment.
+     *
+     * In addition, upon successful face authentication, the signed HAT that is returned to
+     * the framework via ISessionCallback#onAuthenticated must contain this identifier in the
+     * authenticatorId field.
+     *
+     * Returns an entropy-encoded random identifier associated with the current set of enrollments
+     * via ISessionCallback#onAuthenticatorIdRetrieved. The authenticatorId
+     *   1) MUST change whenever a new face is enrolled
+     *   2) MUST return 0 if no faces are enrolled
+     *   3) MUST not change if a face is deleted.
+     *   4) MUST be an entropy-encoded random number
+     *
+     * @param cookie An identifier used to track subsystem operations related to this call path. The
+     *               client must guarantee that it is unique per ISession.
+     */
+    void getAuthenticatorId(in int cookie);
+
+    /**
+     * invalidateAuthenticatorId:
+     *
+     * This method only applies to sensors that are configured as SensorStrength::STRONG. If invoked
+     * by the framework for sensor of other strengths, the HAL should immediately invoke
+     * ISessionCallback#onAuthenticatorIdInvalidated.
+     *
+     * The following only applies to sensors that are configured as SensorStrength::STRONG.
+     *
+     * When invoked by the framework, the implementation must perform the following sequence of
+     * events:
+     *   1) Verify the authenticity and integrity of the provided HAT. If this check fails, the HAL
+     *      must invoke ISessionCallback#onError with Error::UNABLE_TO_PROCESS and return to
+     *      SessionState::IDLING if no subsequent work is in the queue.
+     *   2) Verify that the timestamp provided within the HAT is relatively recent (e.g. on the
+     *      order of minutes, not hours). If this check fails, the HAL must invoke
+     *      ISessionCallback#onError with Error::UNABLE_TO_PROCESS and return to
+     *      SessionState::IDLING if no subsequent work is in the queue.
+     *   3) Update the authenticatorId with a new entropy-encoded random number
+     *   4) Persist the new authenticatorId to non-ephemeral storage
+     *   5) Notify the framework that the above is completed, via
+     *      ISessionCallback#onAuthenticatorInvalidated
+     *
+     * A practical use case of invalidation would be when the user adds a new enrollment to a sensor
+     * managed by a different HAL instance. The public android.security.keystore APIs bind keys to
+     * "all biometrics" rather than "face-only" or "face-only" (see #getAuthenticatorId
+     * for more details). As such, the framework would coordinate invalidation across multiple
+     * biometric HALs as necessary.
+     *
+     * @param cookie An identifier used to track subsystem operations related to this call path. The
+     *               client must guarantee that it is unique per ISession.
+     */
+    void invalidateAuthenticatorId(in int cookie);
+
+    /**
+     * resetLockout:
+     *
+     * Requests the implementation to clear the lockout counter. Upon receiving this request, the
+     * implementation must perform the following:
+     *   1) Verify the authenticity and integrity of the provided HAT
+     *   2) Verify that the timestamp provided within the HAT is relatively recent (e.g. on the
+     *      order of minutes, not hours).
+     * If either of the checks fail, the HAL must invoke ISessionCallback#onError with
+     * Error::UNABLE_TO_PROCESS and return to SessionState::IDLING if no subsequent work is in the
+     * queue.
+     *
+     * Upon successful verification, the HAL must clear the lockout counter and notify the framework
+     * via ISessionCallback#onLockoutCleared.
+     *
+     * Note that lockout is user AND sensor specific. In other words, there is a separate lockout
+     * state for each (user, sensor) pair. For example, the following is a valid state on a
+     * multi-sensor device:
+     * ------------------------------------------------------------------
+     * | SensorId | UserId | FailedAttempts | LockedOut | LockedUntil   |
+     * |----------|--------|----------------|-----------|---------------|
+     * | 0        | 0      | 1              | false     | x             |
+     * | 1        | 0      | 5              | true      | <future_time> |
+     * | 0        | 10     | 0              | false     | x             |
+     * | 1        | 10     | 0              | false     | x             |
+     * ------------------------------------------------------------------
+     *
+     * Lockout may be cleared in the following ways:
+     *   1) ISession#resetLockout
+     *   2) After a period of time, according to a rate-limiter.
+     *
+     * Note that the "FailedAttempts" counter must be cleared upon successful face
+     * authentication. For example, if SensorId=0 UserId=0 FailedAttempts=1, and a successful
+     * face authentication occurs, the counter for that (SensorId, UserId) pair must be reset
+     * to 0.
+     *
+     * In addition, lockout states MUST persist after device reboots, HAL crashes, etc.
+     *
+     * See the Android CDD section 7.3.10 for the full set of lockout and rate-limiting
+     * requirements.
+     *
+     * @param cookie An identifier used to track subsystem operations related to this call path. The
+     *               client must guarantee that it is unique per ISession.
+     * @param hat HardwareAuthToken See above documentation.
+     */
+    void resetLockout(in int cookie, in HardwareAuthToken hat);
+}
+
diff --git a/biometrics/face/aidl/android/hardware/biometrics/face/ISessionCallback.aidl b/biometrics/face/aidl/android/hardware/biometrics/face/ISessionCallback.aidl
new file mode 100644
index 0000000..2608d5f
--- /dev/null
+++ b/biometrics/face/aidl/android/hardware/biometrics/face/ISessionCallback.aidl
@@ -0,0 +1,200 @@
+/*
+ * 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.
+ */
+
+package android.hardware.biometrics.face;
+
+import android.hardware.biometrics.face.AcquiredInfo;
+import android.hardware.biometrics.face.Error;
+import android.hardware.biometrics.face.SessionState;
+import android.hardware.keymaster.HardwareAuthToken;
+
+@VintfStability
+interface ISessionCallback {
+    /**
+     * Used to notify the framework of session state changes. See ISession for more information.
+     */
+    void onStateChanged(in int cookie, in SessionState state);
+
+    /**
+     * Notifies the framework when a challenge is successfully generated.
+     */
+    void onChallengeGenerated(in int sensorId, in int userId, in long challenge);
+
+    /**
+     * Notifies the framework when a challenge has been revoked.
+     */
+    void onChallengeRevoked(in int sensorId, in int userId, in long challenge);
+
+    /**
+     * This method must only be used to notify the framework during the following states:
+     *   1) SessionState::ENROLLING
+     *   2) SessionState::AUTHENTICATING
+     *   3) SessionState::DETECTING_INTERACTION
+     *
+     * These messages may be used to provide user guidance multiple times if necessary per
+     * operation.
+     *
+     * @param info See the AcquiredInfo enum.
+     * @param vendorCode Only valid if info == AcquiredInfo::VENDOR. The vendorCode must be used to
+     *                   index into the configuration
+     *                   com.android.internal.R.array.face_acquired_vendor that's installed
+     *                   on the vendor partition.
+     */
+    void onAcquired(in AcquiredInfo info, in int vendorCode);
+
+    /**
+     * This method must only be used to notify the framework during the following states:
+     *   1) SessionState::ENROLLING
+     *   2) SessionState::AUTHENTICATING
+     *   3) SessionState::DETECTING_INTERACTION
+     *   4) SessionState::INVALIDATING_AUTHENTICATOR_ID
+     *   5) SessionState::RESETTING_LOCKOUT
+     *
+     * These messages may be used to notify the framework or user that a non-recoverable error
+     * has occurred. The operation is finished, and the HAL must proceed with the next operation
+     * or return to SessionState::IDLING if the queue is empty.
+     *
+     * Note that cancellation (see common::ICancellationSignal) and preemption most be followed with
+     * an Error::CANCELED message.
+     *
+     * @param error See the Error enum.
+     * @param vendorCode Only valid if error == Error::VENDOR. The vendorCode must be used to index
+     *                   into the configuration
+     *                   com.android.internal.R.face_error_vendor that's installed on the
+     *                   vendor partition.
+     */
+    void onError(in Error error, in int vendorCode);
+
+    /**
+     * This method must only be used to notify the framework during the following state:
+     *   1) SessionState::ENROLLING
+     *
+     * @param enrollmentId Unique stable identifier for the enrollment that's being added by this
+     *                     ISession#enroll invocation.
+     * @param remaining Remaining number of steps before enrollment is complete.
+     */
+    void onEnrollmentProgress(in int enrollmentId, int remaining);
+
+    /**
+     * This method must only be used to notify the framework during SessionState::AUTHENTICATING.
+     *
+     * Used to notify the framework upon successful authentication. Note that the authentication
+     * lifecycle ends when either 1) a face is accepted, or 2) an error occurred. The
+     * authentication lifecycle does NOT end when a face is rejected.
+     *
+     * @param enrollmentId Face that was accepted.
+     * @param hat If the sensor is configured as SensorStrength::STRONG, a non-null attestation that
+     *            a face was accepted. The HardwareAuthToken's "challenge" field must be set
+     *            with the operationId passed in during ISession#authenticate. If the sensor is NOT
+     *            SensorStrength::STRONG, the HardwareAuthToken MUST be null.
+     */
+    void onAuthenticationSucceeded(in int enrollmentId, in HardwareAuthToken hat);
+
+    /**
+     * This method must only be used to notify the framework during SessionState::AUTHENTICATING.
+     *
+     * Used to notify the framework upon rejected attempts. Note that the authentication
+     * lifecycle ends when either 1) a face is accepted, or 2) an occurred. The
+     * authentication lifecycle does NOT end when a face is rejected.
+     */
+    void onAuthenticationFailed();
+
+    /**
+     * This method must only be used to notify the framework during SessionState::AUTHENTICATING.
+     *
+     * Authentication is locked out due to too many unsuccessful attempts. This is a rate-limiting
+     * lockout, and authentication can be restarted after a period of time. See
+     * ISession#resetLockout.
+     *
+     * @param sensorId Sensor for which the user is locked out.
+     * @param userId User for which the sensor is locked out.
+     * @param durationMillis Remaining duration of the lockout.
+     */
+    void onLockoutTimed(in long durationMillis);
+
+    /**
+     * This method must only be used to notify the framework during SessionState::AUTHENTICATING.
+     *
+     * Authentication is disabled until the user unlocks with their device credential
+     * (PIN/Pattern/Password). See ISession#resetLockout.
+     *
+     * @param sensorId Sensor for which the user is locked out.
+     * @param userId User for which the sensor is locked out.
+     */
+    void onLockoutPermanent();
+
+    /**
+     * Notifies the framework that lockout has been cleared for this (sensorId, userId) pair.
+     *
+     * Note that this method can be used to notify the framework during any state.
+     *
+     * Lockout can be cleared in the following scenarios:
+     * 1) A timed lockout has ended (e.g. durationMillis specified in previous #onLockoutTimed
+     *    has expired.
+     * 2) See ISession#resetLockout.
+     *
+     * @param sensorId Sensor for which the user's lockout is cleared.
+     * @param userId User for the sensor's lockout is cleared.
+     */
+    void onLockoutCleared();
+
+    /**
+     * This method must only be used to notify the framework during
+     * SessionState::DETECTING_INTERACTION
+     *
+     * Notifies the framework that user interaction occurred. See ISession#detectInteraction.
+     */
+    void onInteractionDetected();
+
+    /**
+     * This method must only be used to notify the framework during
+     * SessionState::ENUMERATING_ENROLLMENTS.
+     *
+     * Notifies the framework of the current enrollments. See ISession#enumerateEnrollments.
+     *
+     * @param enrollmentIds A list of enrollments for the session's (userId, sensorId) pair.
+     */
+    void onEnrollmentsEnumerated(in int[] enrollmentIds);
+
+    /**
+     * This method must only be used to notify the framework during
+     * SessionState::REMOVING_ENROLLMENTS.
+     *
+     * Notifies the framework that the specified enrollments are removed.
+     *
+     * @param enrollmentIds The enrollments that were removed.
+     */
+    void onEnrollmentsRemoved(in int[] enrollmentIds);
+
+    /**
+     * This method must only be used to notify the framework during
+     * SessionState::GETTING_AUTHENTICATOR_ID.
+     *
+     * Notifies the framework with the authenticatorId corresponding to this session's
+     * (userId, sensorId) pair.
+     *
+     * @param authenticatorId See the above documentation.
+     */
+    void onAuthenticatorIdRetrieved(in long authenticatorId);
+
+    /**
+     * This method must only be used to notify the framework during
+     * SessionState::INVALIDATING_AUTHENTICATOR_ID.
+     *
+     * See ISession#invalidateAuthenticatorId for more information.
+     */
+    void onAuthenticatorIdInvalidated();
+}
diff --git a/biometrics/face/aidl/android/hardware/biometrics/face/SensorProps.aidl b/biometrics/face/aidl/android/hardware/biometrics/face/SensorProps.aidl
new file mode 100644
index 0000000..53cc44e
--- /dev/null
+++ b/biometrics/face/aidl/android/hardware/biometrics/face/SensorProps.aidl
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+
+package android.hardware.biometrics.face;
+
+import android.hardware.biometrics.common.CommonProps;
+import android.hardware.biometrics.face.FaceSensorType;
+
+@VintfStability
+parcelable SensorProps {
+    /**
+     * Statically configured properties that apply to this face sensor.
+     */
+    CommonProps commonProps;
+
+    /**
+     * A statically configured sensor type representing this face sensor.
+     */
+    FaceSensorType sensorType;
+
+    /**
+     * Whether or not the HAL is responsible for showing the face enrollment preview to the user.
+     * Devices with multiple front camera sensors can set this to false and rely on the framework to
+     * show the preview with one of the unused cameras. Devices with a single front sensor must set
+     * this to true and configure their send their camera stream to the preview surface provided by
+     * the framework.
+     */
+    boolean halControlsPreview;
+}
+
diff --git a/biometrics/face/aidl/android/hardware/biometrics/face/SessionState.aidl b/biometrics/face/aidl/android/hardware/biometrics/face/SessionState.aidl
new file mode 100644
index 0000000..1878f7c
--- /dev/null
+++ b/biometrics/face/aidl/android/hardware/biometrics/face/SessionState.aidl
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+
+package android.hardware.biometrics.face;
+
+@VintfStability
+@Backing(type="byte")
+enum SessionState {
+    /**
+     * The HAL is not processing any session requests.
+     */
+    IDLING,
+
+    /**
+     * The session has been terminated by the HAL.
+     */
+    TERMINATED,
+
+    /**
+     * The HAL is processing the ISession#generateChallenge request.
+     */
+    GENERATING_CHALLENGE,
+
+    /**
+     * The HAL is processing the ISession#revokeChallenge request.
+     */
+    REVOKING_CHALLENGE,
+
+    /**
+     * The HAL is processing the ISession#enroll request.
+     */
+    ENROLLING,
+
+    /**
+     * The HAL is processing the ISession#authenticate request.
+     */
+    AUTHENTICATING,
+
+    /**
+     * The HAL is processing the ISession#detectInteraction request.
+     */
+    DETECTING_INTERACTION,
+
+    /**
+     * The HAL is processing the ISession#enumerateEnrollments request.
+     */
+    ENUMERATING_ENROLLMENTS,
+
+    /**
+     * The HAL is processing the ISession#removeEnrollments request.
+     */
+    REMOVING_ENROLLMENTS,
+
+    /**
+     * The HAL is processing the ISession#getAuthenticatorId request.
+     */
+    GETTING_AUTHENTICATOR_ID,
+
+    /**
+     * The HAL is processing the ISession#invalidateAuthenticatorId request.
+     */
+    INVALIDATING_AUTHENTICATOR_ID,
+
+    /**
+     * The HAL is processing the ISession#resetLockout request.
+     */
+    RESETTING_LOCKOUT
+}
+
diff --git a/biometrics/face/aidl/default/Android.bp b/biometrics/face/aidl/default/Android.bp
new file mode 100644
index 0000000..51a8ef4
--- /dev/null
+++ b/biometrics/face/aidl/default/Android.bp
@@ -0,0 +1,18 @@
+cc_binary {
+    name: "android.hardware.biometrics.face-service.example",
+    relative_install_path: "hw",
+    init_rc: ["face-default.rc"],
+    vintf_fragments: ["face-default.xml"],
+    vendor: true,
+    shared_libs: [
+        "libbase",
+        "libbinder_ndk",
+        "android.hardware.biometrics.face-ndk_platform",
+        "android.hardware.biometrics.common-unstable-ndk_platform",
+    ],
+    srcs: [
+        "main.cpp",
+        "Face.cpp",
+        "Session.cpp",
+    ],
+}
diff --git a/biometrics/face/aidl/default/Face.cpp b/biometrics/face/aidl/default/Face.cpp
new file mode 100644
index 0000000..1526245
--- /dev/null
+++ b/biometrics/face/aidl/default/Face.cpp
@@ -0,0 +1,61 @@
+/*
+ * 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 "Face.h"
+#include "Session.h"
+
+namespace aidl::android::hardware::biometrics::face {
+
+const int kSensorId = 0;
+const common::SensorStrength kSensorStrength = common::SensorStrength::WEAK;
+const int kMaxEnrollmentsPerUser = 5;
+const FaceSensorType kSensorType = FaceSensorType::RGB;
+const bool kHalControlsPreview = true;
+const std::string kHwDeviceName = "faceSensor";
+const std::string kHardwareVersion = "vendor/model/revision";
+const std::string kFirmwareVersion = "1.01";
+const std::string kSerialNumber = "00000001";
+
+ndk::ScopedAStatus Face::getSensorProps(std::vector<SensorProps>* return_val) {
+    common::HardwareInfo hardware_info;
+    hardware_info.deviceName = kHwDeviceName;
+    hardware_info.hardwareVersion = kHardwareVersion;
+    hardware_info.firmwareVersion = kFirmwareVersion;
+    hardware_info.serialNumber = kSerialNumber;
+
+    common::CommonProps commonProps;
+    commonProps.sensorId = kSensorId;
+    commonProps.sensorStrength = kSensorStrength;
+    commonProps.maxEnrollmentsPerUser = kMaxEnrollmentsPerUser;
+    commonProps.hardwareInfo = {std::move(hardware_info)};
+
+    SensorProps props;
+    props.commonProps = std::move(commonProps);
+    props.sensorType = kSensorType;
+    props.halControlsPreview = kHalControlsPreview;
+
+    *return_val = {std::move(props)};
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Face::createSession(int32_t /*sensorId*/, int32_t /*userId*/,
+                                       const std::shared_ptr<ISessionCallback>& cb,
+                                       std::shared_ptr<ISession>* return_val) {
+    *return_val = SharedRefBase::make<Session>(cb);
+    return ndk::ScopedAStatus::ok();
+}
+
+}  // namespace aidl::android::hardware::biometrics::face
diff --git a/biometrics/face/aidl/default/Face.h b/biometrics/face/aidl/default/Face.h
new file mode 100644
index 0000000..786b4f8
--- /dev/null
+++ b/biometrics/face/aidl/default/Face.h
@@ -0,0 +1,32 @@
+/*
+ * 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 <aidl/android/hardware/biometrics/face/BnFace.h>
+
+namespace aidl::android::hardware::biometrics::face {
+
+class Face : public BnFace {
+  public:
+    ndk::ScopedAStatus getSensorProps(std::vector<SensorProps>* _aidl_return) override;
+
+    ndk::ScopedAStatus createSession(int32_t sensorId, int32_t userId,
+                                     const std::shared_ptr<ISessionCallback>& cb,
+                                     std::shared_ptr<ISession>* _aidl_return) override;
+};
+
+}  // namespace aidl::android::hardware::biometrics::face
diff --git a/biometrics/face/aidl/default/Session.cpp b/biometrics/face/aidl/default/Session.cpp
new file mode 100644
index 0000000..bb895b7
--- /dev/null
+++ b/biometrics/face/aidl/default/Session.cpp
@@ -0,0 +1,82 @@
+/*
+ * 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 <aidl/android/hardware/biometrics/common/BnCancellationSignal.h>
+
+#include "Session.h"
+
+namespace aidl::android::hardware::biometrics::face {
+
+class CancellationSignal : public common::BnCancellationSignal {
+  public:
+    ndk::ScopedAStatus cancel() override { return ndk::ScopedAStatus::ok(); }
+};
+
+Session::Session(std::shared_ptr<ISessionCallback> cb) : cb_(std::move(cb)) {}
+
+ndk::ScopedAStatus Session::generateChallenge(int32_t /*cookie*/, int32_t /*sensorId*/,
+                                              int32_t /*userId*/, int32_t /*timeoutSec*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Session::revokeChallenge(int32_t /*cookie*/, int32_t /*sensorId*/,
+                                            int32_t /*userId*/, int64_t /*challenge*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Session::enroll(int32_t /*cookie*/, const keymaster::HardwareAuthToken& /*hat*/,
+                                   const NativeHandle& /*previewSurface*/,
+                                   std::shared_ptr<biometrics::common::ICancellationSignal>*
+                                   /*returnVal*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Session::authenticate(int32_t /*cookie*/, int64_t /*keystoreOperationId*/,
+                                         std::shared_ptr<common::ICancellationSignal>* return_val) {
+    if (cb_) {
+        cb_->onStateChanged(0, SessionState::AUTHENTICATING);
+    }
+    *return_val = SharedRefBase::make<CancellationSignal>();
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Session::detectInteraction(
+        int32_t /*cookie*/, std::shared_ptr<common::ICancellationSignal>* /*return_val*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Session::enumerateEnrollments(int32_t /*cookie*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Session::removeEnrollments(int32_t /*cookie*/,
+                                              const std::vector<int32_t>& /*enrollmentIds*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Session::getAuthenticatorId(int32_t /*cookie*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Session::invalidateAuthenticatorId(int32_t /*cookie*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Session::resetLockout(int32_t /*cookie*/,
+                                         const keymaster::HardwareAuthToken& /*hat*/) {
+    return ndk::ScopedAStatus::ok();
+}
+}  // namespace aidl::android::hardware::biometrics::face
diff --git a/biometrics/face/aidl/default/Session.h b/biometrics/face/aidl/default/Session.h
new file mode 100644
index 0000000..a91ad81
--- /dev/null
+++ b/biometrics/face/aidl/default/Session.h
@@ -0,0 +1,67 @@
+/*
+ * 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 <aidl/android/hardware/biometrics/face/BnSession.h>
+#include <aidl/android/hardware/biometrics/face/ISessionCallback.h>
+
+namespace aidl::android::hardware::biometrics::face {
+
+namespace common = aidl::android::hardware::biometrics::common;
+namespace keymaster = aidl::android::hardware::keymaster;
+
+using aidl::android::hardware::common::NativeHandle;
+
+class Session : public BnSession {
+  public:
+    explicit Session(std::shared_ptr<ISessionCallback> cb);
+
+    ndk::ScopedAStatus generateChallenge(int32_t cookie, int32_t sensorId, int32_t userId,
+                                         int32_t timeoutSec) override;
+
+    ndk::ScopedAStatus revokeChallenge(int32_t cookie, int32_t sensorId, int32_t userId,
+                                       int64_t challenge) override;
+
+    ndk::ScopedAStatus enroll(
+            int32_t cookie, const keymaster::HardwareAuthToken& hat,
+            const NativeHandle& previewSurface,
+            std::shared_ptr<biometrics::common::ICancellationSignal>* returnVal) override;
+
+    ndk::ScopedAStatus authenticate(
+            int32_t cookie, int64_t keystoreOperationId,
+            std::shared_ptr<common::ICancellationSignal>* returnVal) override;
+
+    ndk::ScopedAStatus detectInteraction(
+            int32_t cookie, std::shared_ptr<common::ICancellationSignal>* returnVal) override;
+
+    ndk::ScopedAStatus enumerateEnrollments(int32_t cookie) override;
+
+    ndk::ScopedAStatus removeEnrollments(int32_t cookie,
+                                         const std::vector<int32_t>& enrollmentIds) override;
+
+    ndk::ScopedAStatus getAuthenticatorId(int32_t cookie) override;
+
+    ndk::ScopedAStatus invalidateAuthenticatorId(int32_t cookie) override;
+
+    ndk::ScopedAStatus resetLockout(int32_t cookie,
+                                    const keymaster::HardwareAuthToken& hat) override;
+
+  private:
+    std::shared_ptr<ISessionCallback> cb_;
+};
+
+}  // namespace aidl::android::hardware::biometrics::face
diff --git a/biometrics/face/aidl/default/face-default.rc b/biometrics/face/aidl/default/face-default.rc
new file mode 100644
index 0000000..f6499f0
--- /dev/null
+++ b/biometrics/face/aidl/default/face-default.rc
@@ -0,0 +1,5 @@
+service vendor.face-default /vendor/bin/hw/android.hardware.biometrics.face-service.example
+    class hal
+    user nobody
+    group nobody
+
diff --git a/biometrics/face/aidl/default/face-default.xml b/biometrics/face/aidl/default/face-default.xml
new file mode 100644
index 0000000..6915ad0
--- /dev/null
+++ b/biometrics/face/aidl/default/face-default.xml
@@ -0,0 +1,6 @@
+<manifest version="1.0" type="device">
+    <hal format="aidl">
+        <name>android.hardware.biometrics.face</name>
+        <fqname>IFace/default</fqname>
+    </hal>
+</manifest>
diff --git a/powerstats/aidl/default/main.cpp b/biometrics/face/aidl/default/main.cpp
similarity index 72%
copy from powerstats/aidl/default/main.cpp
copy to biometrics/face/aidl/default/main.cpp
index 1496805..80b153e 100644
--- a/powerstats/aidl/default/main.cpp
+++ b/biometrics/face/aidl/default/main.cpp
@@ -14,20 +14,21 @@
  * limitations under the License.
  */
 
-#include "PowerStats.h"
+#include "Face.h"
 
 #include <android-base/logging.h>
 #include <android/binder_manager.h>
 #include <android/binder_process.h>
 
-using aidl::android::hardware::powerstats::PowerStats;
+using aidl::android::hardware::biometrics::face::Face;
 
 int main() {
+    LOG(INFO) << "Face HAL started";
     ABinderProcess_setThreadPoolMaxThreadCount(0);
-    std::shared_ptr<PowerStats> p = ndk::SharedRefBase::make<PowerStats>();
+    std::shared_ptr<Face> hal = ndk::SharedRefBase::make<Face>();
 
-    const std::string instance = std::string() + PowerStats::descriptor + "/default";
-    binder_status_t status = AServiceManager_addService(p->asBinder().get(), instance.c_str());
+    const std::string instance = std::string(Face::descriptor) + "/default";
+    binder_status_t status = AServiceManager_addService(hal->asBinder().get(), instance.c_str());
     CHECK(status == STATUS_OK);
 
     ABinderProcess_joinThreadPool();
diff --git a/biometrics/face/aidl/vts/Android.bp b/biometrics/face/aidl/vts/Android.bp
new file mode 100644
index 0000000..427b878
--- /dev/null
+++ b/biometrics/face/aidl/vts/Android.bp
@@ -0,0 +1,16 @@
+cc_test {
+    name: "VtsHalBiometricsFaceTargetTest",
+    defaults: [
+        "VtsHalTargetTestDefaults",
+        "use_libaidlvintf_gtest_helper_static",
+    ],
+    srcs: ["VtsHalBiometricsFaceTargetTest.cpp"],
+    shared_libs: [
+        "libbinder_ndk",
+        "android.hardware.biometrics.face-ndk_platform",
+    ],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
+}
diff --git a/biometrics/face/aidl/vts/VtsHalBiometricsFaceTargetTest.cpp b/biometrics/face/aidl/vts/VtsHalBiometricsFaceTargetTest.cpp
new file mode 100644
index 0000000..c1ba66b
--- /dev/null
+++ b/biometrics/face/aidl/vts/VtsHalBiometricsFaceTargetTest.cpp
@@ -0,0 +1,157 @@
+/*
+ * 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 <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/biometrics/face/BnFace.h>
+#include <aidl/android/hardware/biometrics/face/BnSessionCallback.h>
+
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+#include <future>
+
+namespace aidl::android::hardware::biometrics::face {
+namespace {
+
+constexpr int kSensorId = 0;
+constexpr int kUserId = 0;
+constexpr auto kCallbackTimeout = std::chrono::seconds(1);
+
+enum class SessionCallbackMethodName {
+    kOnStateChanged,
+};
+
+struct SessionCallbackInvocation {
+    SessionCallbackMethodName method_name;
+    SessionState state;
+};
+
+class SessionCallback : public BnSessionCallback {
+  public:
+    explicit SessionCallback(std::promise<SessionCallbackInvocation> invocation_promise)
+        : invocation_promise_(std::move(invocation_promise)) {}
+    ndk::ScopedAStatus onStateChanged(int32_t /*cookie*/, SessionState state) override {
+        SessionCallbackInvocation invocation = {};
+        invocation.method_name = SessionCallbackMethodName::kOnStateChanged;
+        invocation.state = state;
+        invocation_promise_.set_value(invocation);
+        return ndk::ScopedAStatus::ok();
+    }
+
+    ndk::ScopedAStatus onChallengeGenerated(int32_t /*sensorId*/, int32_t /*userId*/,
+                                            int64_t /*challenge*/) override {
+        return ndk::ScopedAStatus::ok();
+    }
+
+    ndk::ScopedAStatus onChallengeRevoked(int32_t /*sensorId*/, int32_t /*userId*/,
+                                          int64_t /*challenge*/) override {
+        return ndk::ScopedAStatus::ok();
+    }
+
+    ndk::ScopedAStatus onAcquired(AcquiredInfo /*info*/, int32_t /*vendorCode*/) override {
+        return ndk::ScopedAStatus::ok();
+    }
+
+    ndk::ScopedAStatus onError(Error /*error*/, int32_t /*vendorCode*/) override {
+        return ndk::ScopedAStatus::ok();
+    }
+
+    ndk::ScopedAStatus onEnrollmentProgress(int32_t /*enrollmentId*/,
+                                            int32_t /*remaining*/) override {
+        return ndk::ScopedAStatus::ok();
+    }
+
+    ndk::ScopedAStatus onAuthenticationSucceeded(
+            int32_t /*enrollmentId*/, const keymaster::HardwareAuthToken& /*hat*/) override {
+        return ndk::ScopedAStatus::ok();
+    }
+
+    ndk::ScopedAStatus onAuthenticationFailed() override { return ndk::ScopedAStatus::ok(); }
+
+    ndk::ScopedAStatus onLockoutTimed(int64_t /*durationMillis*/) override {
+        return ndk::ScopedAStatus::ok();
+    }
+
+    ndk::ScopedAStatus onLockoutPermanent() override { return ndk::ScopedAStatus::ok(); }
+
+    ndk::ScopedAStatus onLockoutCleared() override { return ndk::ScopedAStatus::ok(); }
+
+    ndk::ScopedAStatus onInteractionDetected() override { return ndk::ScopedAStatus::ok(); }
+
+    ndk::ScopedAStatus onEnrollmentsEnumerated(
+            const std::vector<int32_t>& /*enrollmentIds*/) override {
+        return ndk::ScopedAStatus::ok();
+    }
+
+    ndk::ScopedAStatus onEnrollmentsRemoved(
+            const std::vector<int32_t>& /*enrollmentIds*/) override {
+        return ndk::ScopedAStatus::ok();
+    }
+
+    ndk::ScopedAStatus onAuthenticatorIdRetrieved(int64_t /*authenticatorId*/) override {
+        return ndk::ScopedAStatus::ok();
+    }
+
+    ndk::ScopedAStatus onAuthenticatorIdInvalidated() override { return ndk::ScopedAStatus::ok(); }
+
+  private:
+    std::promise<SessionCallbackInvocation> invocation_promise_;
+};
+
+class Face : public testing::TestWithParam<std::string> {
+  protected:
+    void SetUp() override {
+        AIBinder* binder = AServiceManager_waitForService(GetParam().c_str());
+        ASSERT_NE(binder, nullptr);
+        hal_ = IFace::fromBinder(ndk::SpAIBinder(binder));
+    }
+
+    std::shared_ptr<IFace> hal_;
+};
+
+TEST_P(Face, AuthenticateTest) {
+    std::promise<SessionCallbackInvocation> invocation_promise;
+    std::future<SessionCallbackInvocation> invocation_future = invocation_promise.get_future();
+    std::shared_ptr<SessionCallback> session_cb =
+            ndk::SharedRefBase::make<SessionCallback>(std::move(invocation_promise));
+
+    std::shared_ptr<ISession> session;
+    ASSERT_TRUE(hal_->createSession(kSensorId, kUserId, session_cb, &session).isOk());
+
+    std::shared_ptr<common::ICancellationSignal> cancel_cb;
+    ASSERT_TRUE(session->authenticate(0, 0, &cancel_cb).isOk());
+    ASSERT_EQ(invocation_future.wait_for(kCallbackTimeout), std::future_status::ready);
+
+    SessionCallbackInvocation invocation = invocation_future.get();
+    EXPECT_EQ(invocation.method_name, SessionCallbackMethodName::kOnStateChanged);
+    EXPECT_EQ(invocation.state, SessionState::AUTHENTICATING);
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Face);
+INSTANTIATE_TEST_SUITE_P(IFace, Face,
+                         testing::ValuesIn(::android::getAidlHalInstanceNames(IFace::descriptor)),
+                         ::android::PrintInstanceNameToString);
+
+}  // namespace
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    ABinderProcess_setThreadPoolMaxThreadCount(1);
+    ABinderProcess_startThreadPool();
+    return RUN_ALL_TESTS();
+}
+
+}  // namespace aidl::android::hardware::biometrics::face
diff --git a/bluetooth/audio/2.1/Android.bp b/bluetooth/audio/2.1/Android.bp
new file mode 100644
index 0000000..9af8add
--- /dev/null
+++ b/bluetooth/audio/2.1/Android.bp
@@ -0,0 +1,22 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.bluetooth.audio@2.1",
+    root: "android.hardware",
+    srcs: [
+        "types.hal",
+        "IBluetoothAudioProvider.hal",
+        "IBluetoothAudioProvidersFactory.hal",
+    ],
+    interfaces: [
+        "android.hardware.audio.common@5.0",
+        "android.hardware.bluetooth.audio@2.0",
+        "android.hidl.base@1.0",
+        "android.hidl.safe_union@1.0",
+    ],
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.bluetooth.updatable",
+    ],
+    gen_java: false,
+}
diff --git a/bluetooth/audio/2.1/IBluetoothAudioProvider.hal b/bluetooth/audio/2.1/IBluetoothAudioProvider.hal
new file mode 100644
index 0000000..c462b9e
--- /dev/null
+++ b/bluetooth/audio/2.1/IBluetoothAudioProvider.hal
@@ -0,0 +1,62 @@
+/*
+ * Copyright 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.
+ */
+
+package android.hardware.bluetooth.audio@2.1;
+
+import @2.0::IBluetoothAudioProvider;
+import @2.0::IBluetoothAudioPort;
+import @2.0::Status;
+
+/**
+ * HAL interface from the Bluetooth stack to the Audio HAL
+ *
+ * The Bluetooth stack calls methods in this interface to start and end audio
+ * sessions and sends callback events to the Audio HAL.
+ *
+ * Note: For HIDL APIs with a "generates" statement, the callback parameter used
+ * for return value must be invoked synchronously before the API call returns.
+ */
+interface IBluetoothAudioProvider extends @2.0::IBluetoothAudioProvider {
+
+    /**
+     * This method indicates that the Bluetooth stack is ready to stream audio.
+     * It registers an instance of IBluetoothAudioPort with and provides the
+     * current negotiated codec to the Audio HAL. After this method is called,
+     * the Audio HAL can invoke IBluetoothAudioPort.startStream().
+     *
+     * Note: endSession() must be called to unregister this IBluetoothAudioPort
+     *
+     * @param hostIf An instance of IBluetoothAudioPort for stream control
+     * @param audioConfig The audio configuration negotiated with the remote
+     *    device. The PCM parameters are set if software based encoding,
+     *    otherwise the correct codec configuration is used for hardware
+     *    encoding.
+     *
+     * @return status One of the following
+     *    SUCCESS if this IBluetoothAudioPort was successfully registered with
+     *        the Audio HAL
+     *    UNSUPPORTED_CODEC_CONFIGURATION if the Audio HAL cannot register this
+     *        IBluetoothAudioPort with the given codec configuration
+     *    FAILURE if the Audio HAL cannot register this IBluetoothAudioPort for
+     *        any other reason
+     * @return dataMQ The fast message queue for audio data from/to this
+     *    provider. Audio data will be in PCM format as specified by the
+     *    audioConfig.pcmConfig parameter. Invalid if streaming is offloaded
+     *    from/to hardware or on failure.
+     */
+    startSession_2_1(IBluetoothAudioPort hostIf, AudioConfiguration audioConfig)
+                generates (Status status, fmq_sync<uint8_t> dataMQ);
+};
diff --git a/bluetooth/audio/2.1/IBluetoothAudioProvidersFactory.hal b/bluetooth/audio/2.1/IBluetoothAudioProvidersFactory.hal
new file mode 100644
index 0000000..5593c7c
--- /dev/null
+++ b/bluetooth/audio/2.1/IBluetoothAudioProvidersFactory.hal
@@ -0,0 +1,73 @@
+/*
+ * Copyright 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.
+ */
+
+package android.hardware.bluetooth.audio@2.1;
+
+import IBluetoothAudioProvider;
+import @2.0::IBluetoothAudioProvidersFactory;
+import @2.0::Status;
+
+/**
+ * This factory allows a HAL implementation to be split into multiple
+ * independent providers.
+ *
+ * When the Bluetooth stack is ready to create an audio session, it must first
+ * obtain the IBluetoothAudioProvider for that session type by calling
+ * openProvider().
+ *
+ * Note: For HIDL APIs with a "generates" statement, the callback parameter used
+ * for return value must be invoked synchronously before the API call returns.
+ */
+interface IBluetoothAudioProvidersFactory extends @2.0::IBluetoothAudioProvidersFactory {
+
+    /**
+     * Opens an audio provider for a session type. To close the provider, it is
+     * necessary to release references to the returned provider object.
+     *
+     * @param sessionType The session type (e.g.
+     *    LE_AUDIO_SOFTWARE_ENCODING_DATAPATH).
+     *
+     * @return status One of the following
+     *    SUCCESS if the Audio HAL successfully opens the provider with the
+     *        given session type
+     *    FAILURE if the Audio HAL cannot open the provider
+     * @return provider The provider of the specified session type
+     */
+    openProvider_2_1(SessionType sessionType)
+        generates (Status status, IBluetoothAudioProvider provider);
+
+    /**
+     * Gets a list of audio capabilities for a session type.
+     *
+     * For software encoding, the PCM capabilities are returned.
+     * For hardware encoding, the supported codecs and their capabilities are
+     * returned.
+     *
+     * @param sessionType The session type (e.g.
+     *    A2DP_SOFTWARE_ENCODING_DATAPATH).
+     * @return audioCapabilities A list containing all the capabilities
+     *    supported by the sesson type. The capabilities is a list of
+     *    available options when configuring the codec for the session.
+     *    For software encoding it is the PCM data rate.
+     *    For hardware encoding it is the list of supported codecs and their
+     *    capabilities.
+     *    If a provider isn't supported, an empty list should be returned.
+     *    Note: Only one entry should exist per codec when using hardware
+     *    encoding.
+     */
+     getProviderCapabilities_2_1(SessionType sessionType)
+         generates (vec<AudioCapabilities> audioCapabilities);
+};
diff --git a/bluetooth/audio/2.1/default/A2dpOffloadAudioProvider.cpp b/bluetooth/audio/2.1/default/A2dpOffloadAudioProvider.cpp
new file mode 100644
index 0000000..b4a61b6
--- /dev/null
+++ b/bluetooth/audio/2.1/default/A2dpOffloadAudioProvider.cpp
@@ -0,0 +1,95 @@
+/*
+ * Copyright 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 "BTAudioProviderA2dpOffload"
+
+#include "A2dpOffloadAudioProvider.h"
+
+#include <android-base/logging.h>
+#include <fmq/MessageQueue.h>
+#include <hidl/MQDescriptor.h>
+
+#include "BluetoothAudioSessionReport.h"
+#include "BluetoothAudioSupportedCodecsDB.h"
+
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::bluetooth::audio::BluetoothAudioSessionReport;
+using ::android::hardware::kSynchronizedReadWrite;
+using ::android::hardware::MessageQueue;
+using ::android::hardware::Void;
+using ::android::hardware::bluetooth::audio::V2_0::AudioConfiguration;
+
+using DataMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
+
+A2dpOffloadAudioProvider::A2dpOffloadAudioProvider()
+    : BluetoothAudioProvider() {
+  session_type_ = SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH;
+}
+
+bool A2dpOffloadAudioProvider::isValid(const V2_0::SessionType& sessionType) {
+  return isValid(static_cast<SessionType>(sessionType));
+}
+
+bool A2dpOffloadAudioProvider::isValid(const SessionType& sessionType) {
+  return (sessionType == session_type_);
+}
+
+Return<void> A2dpOffloadAudioProvider::startSession(
+    const sp<IBluetoothAudioPort>& hostIf,
+    const AudioConfiguration& audioConfig, startSession_cb _hidl_cb) {
+  /**
+   * Initialize the audio platform if audioConfiguration is supported.
+   * Save the IBluetoothAudioPort interface, so that it can be used
+   * later to send stream control commands to the HAL client, based on
+   * interaction with Audio framework.
+   */
+  if (audioConfig.getDiscriminator() !=
+      AudioConfiguration::hidl_discriminator::codecConfig) {
+    LOG(WARNING) << __func__
+                 << " - Invalid Audio Configuration=" << toString(audioConfig);
+    _hidl_cb(BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION,
+             DataMQ::Descriptor());
+    return Void();
+  } else if (!android::bluetooth::audio::IsOffloadCodecConfigurationValid(
+                 session_type_, audioConfig.codecConfig())) {
+    _hidl_cb(BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION,
+             DataMQ::Descriptor());
+    return Void();
+  }
+
+  return BluetoothAudioProvider::startSession(hostIf, audioConfig, _hidl_cb);
+}
+
+Return<void> A2dpOffloadAudioProvider::onSessionReady(
+    startSession_cb _hidl_cb) {
+  BluetoothAudioSessionReport::OnSessionStarted(session_type_, stack_iface_,
+                                                nullptr, audio_config_);
+  _hidl_cb(BluetoothAudioStatus::SUCCESS, DataMQ::Descriptor());
+  return Void();
+}
+
+}  // namespace implementation
+}  // namespace V2_1
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
diff --git a/bluetooth/audio/2.1/default/A2dpOffloadAudioProvider.h b/bluetooth/audio/2.1/default/A2dpOffloadAudioProvider.h
new file mode 100644
index 0000000..13e0b9a
--- /dev/null
+++ b/bluetooth/audio/2.1/default/A2dpOffloadAudioProvider.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright 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 "BluetoothAudioProvider.h"
+
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+namespace V2_1 {
+namespace implementation {
+
+class A2dpOffloadAudioProvider : public BluetoothAudioProvider {
+ public:
+  A2dpOffloadAudioProvider();
+
+  bool isValid(const SessionType& sessionType) override;
+  bool isValid(const V2_0::SessionType& sessionType) override;
+
+  Return<void> startSession(const sp<V2_0::IBluetoothAudioPort>& hostIf,
+                            const V2_0::AudioConfiguration& audioConfig,
+                            startSession_cb _hidl_cb) override;
+
+ private:
+  Return<void> onSessionReady(startSession_cb _hidl_cb) override;
+};
+
+}  // namespace implementation
+}  // namespace V2_1
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
diff --git a/bluetooth/audio/2.1/default/A2dpSoftwareAudioProvider.cpp b/bluetooth/audio/2.1/default/A2dpSoftwareAudioProvider.cpp
new file mode 100644
index 0000000..a67c341
--- /dev/null
+++ b/bluetooth/audio/2.1/default/A2dpSoftwareAudioProvider.cpp
@@ -0,0 +1,113 @@
+/*
+ * Copyright 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 "BTAudioProviderA2dpSoftware"
+
+#include "A2dpSoftwareAudioProvider.h"
+
+#include <android-base/logging.h>
+
+#include "BluetoothAudioSessionReport.h"
+#include "BluetoothAudioSupportedCodecsDB.h"
+
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::bluetooth::audio::BluetoothAudioSessionReport;
+using ::android::hardware::Void;
+using ::android::hardware::bluetooth::audio::V2_0::AudioConfiguration;
+
+static constexpr uint32_t kPcmFrameSize = 4;  // 16 bits per sample / stereo
+static constexpr uint32_t kPcmFrameCount = 128;
+static constexpr uint32_t kRtpFrameSize = kPcmFrameSize * kPcmFrameCount;
+static constexpr uint32_t kRtpFrameCount = 7;  // max counts by 1 tick (20ms)
+static constexpr uint32_t kBufferSize = kRtpFrameSize * kRtpFrameCount;
+static constexpr uint32_t kBufferCount = 2;  // double buffer
+static constexpr uint32_t kDataMqSize = kBufferSize * kBufferCount;
+
+A2dpSoftwareAudioProvider::A2dpSoftwareAudioProvider()
+    : BluetoothAudioProvider(), mDataMQ(nullptr) {
+  LOG(INFO) << __func__ << " - size of audio buffer " << kDataMqSize
+            << " byte(s)";
+  std::unique_ptr<DataMQ> tempDataMQ(
+      new DataMQ(kDataMqSize, /* EventFlag */ true));
+  if (tempDataMQ && tempDataMQ->isValid()) {
+    mDataMQ = std::move(tempDataMQ);
+    session_type_ = SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH;
+  } else {
+    ALOGE_IF(!tempDataMQ, "failed to allocate data MQ");
+    ALOGE_IF(tempDataMQ && !tempDataMQ->isValid(), "data MQ is invalid");
+  }
+}
+
+bool A2dpSoftwareAudioProvider::isValid(const V2_0::SessionType& sessionType) {
+  return isValid(static_cast<SessionType>(sessionType));
+}
+
+bool A2dpSoftwareAudioProvider::isValid(const SessionType& sessionType) {
+  return (sessionType == session_type_ && mDataMQ && mDataMQ->isValid());
+}
+
+Return<void> A2dpSoftwareAudioProvider::startSession(
+    const sp<IBluetoothAudioPort>& hostIf,
+    const V2_0::AudioConfiguration& audioConfig, startSession_cb _hidl_cb) {
+  /**
+   * Initialize the audio platform if audioConfiguration is supported.
+   * Save the IBluetoothAudioPort interface, so that it can be used
+   * later to send stream control commands to the HAL client, based on
+   * interaction with Audio framework.
+   */
+  if (audioConfig.getDiscriminator() !=
+      AudioConfiguration::hidl_discriminator::pcmConfig) {
+    LOG(WARNING) << __func__
+                 << " - Invalid Audio Configuration=" << toString(audioConfig);
+    _hidl_cb(BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION,
+             DataMQ::Descriptor());
+    return Void();
+  } else if (!android::bluetooth::audio::IsSoftwarePcmConfigurationValid(
+                 audioConfig.pcmConfig())) {
+    LOG(WARNING) << __func__ << " - Unsupported PCM Configuration="
+                 << toString(audioConfig.pcmConfig());
+    _hidl_cb(BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION,
+             DataMQ::Descriptor());
+    return Void();
+  }
+
+  return BluetoothAudioProvider::startSession(hostIf, audioConfig, _hidl_cb);
+}
+
+Return<void> A2dpSoftwareAudioProvider::onSessionReady(
+    startSession_cb _hidl_cb) {
+  if (mDataMQ && mDataMQ->isValid()) {
+    BluetoothAudioSessionReport::OnSessionStarted(
+        session_type_, stack_iface_, mDataMQ->getDesc(), audio_config_);
+    _hidl_cb(BluetoothAudioStatus::SUCCESS, *mDataMQ->getDesc());
+  } else {
+    _hidl_cb(BluetoothAudioStatus::FAILURE, DataMQ::Descriptor());
+  }
+  return Void();
+}
+
+}  // namespace implementation
+}  // namespace V2_1
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
diff --git a/bluetooth/audio/2.1/default/A2dpSoftwareAudioProvider.h b/bluetooth/audio/2.1/default/A2dpSoftwareAudioProvider.h
new file mode 100644
index 0000000..20566d1
--- /dev/null
+++ b/bluetooth/audio/2.1/default/A2dpSoftwareAudioProvider.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright 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 <fmq/MessageQueue.h>
+#include <hidl/MQDescriptor.h>
+
+#include "BluetoothAudioProvider.h"
+
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::kSynchronizedReadWrite;
+using ::android::hardware::MessageQueue;
+
+using DataMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
+
+class A2dpSoftwareAudioProvider : public BluetoothAudioProvider {
+ public:
+  A2dpSoftwareAudioProvider();
+
+  bool isValid(const SessionType& sessionType) override;
+  bool isValid(const V2_0::SessionType& sessionType) override;
+
+  Return<void> startSession(const sp<IBluetoothAudioPort>& hostIf,
+                            const V2_0::AudioConfiguration& audioConfig,
+                            startSession_cb _hidl_cb) override;
+
+ private:
+  // audio data queue for software encoding
+  std::unique_ptr<DataMQ> mDataMQ;
+
+  Return<void> onSessionReady(startSession_cb _hidl_cb) override;
+};
+
+}  // namespace implementation
+}  // namespace V2_1
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
diff --git a/bluetooth/audio/2.1/default/Android.bp b/bluetooth/audio/2.1/default/Android.bp
new file mode 100644
index 0000000..5381fec
--- /dev/null
+++ b/bluetooth/audio/2.1/default/Android.bp
@@ -0,0 +1,48 @@
+cc_library_shared {
+    name: "android.hardware.bluetooth.audio@2.1-impl",
+    defaults: ["hidl_defaults"],
+    vendor: true,
+    relative_install_path: "hw",
+    srcs: [
+        "BluetoothAudioProvidersFactory.cpp",
+        "BluetoothAudioProvider.cpp",
+        "A2dpOffloadAudioProvider.cpp",
+        "A2dpSoftwareAudioProvider.cpp",
+        "HearingAidAudioProvider.cpp",
+        "LeAudioAudioProvider.cpp",
+    ],
+    header_libs: ["libhardware_headers"],
+    shared_libs: [
+        "android.hardware.bluetooth.audio@2.0",
+        "android.hardware.bluetooth.audio@2.1",
+        "libbase",
+        "libbluetooth_audio_session_2_1",
+        "libcutils",
+        "libfmq",
+        "libhidlbase",
+        "liblog",
+        "libutils",
+    ],
+}
+
+cc_library_shared {
+    name: "libbluetooth_audio_session_2_1",
+    defaults: ["hidl_defaults"],
+    vendor: true,
+    srcs: [
+        "session/BluetoothAudioSession.cpp",
+        "session/BluetoothAudioSupportedCodecsDB.cpp",
+    ],
+    export_include_dirs: ["session/"],
+    header_libs: ["libhardware_headers"],
+    shared_libs: [
+        "android.hardware.bluetooth.audio@2.0",
+        "android.hardware.bluetooth.audio@2.1",
+        "libbase",
+        "libcutils",
+        "libfmq",
+        "libhidlbase",
+        "liblog",
+        "libutils",
+    ],
+}
diff --git a/bluetooth/audio/2.1/default/BluetoothAudioProvider.cpp b/bluetooth/audio/2.1/default/BluetoothAudioProvider.cpp
new file mode 100644
index 0000000..0f349a4
--- /dev/null
+++ b/bluetooth/audio/2.1/default/BluetoothAudioProvider.cpp
@@ -0,0 +1,159 @@
+/*
+ * Copyright 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 "BTAudioProviderStub"
+
+#include "BluetoothAudioProvider.h"
+
+#include <android-base/logging.h>
+
+#include "BluetoothAudioSessionReport.h"
+#include "BluetoothAudioSupportedCodecsDB.h"
+
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::bluetooth::audio::BluetoothAudioSessionReport;
+using ::android::hardware::kSynchronizedReadWrite;
+using ::android::hardware::MessageQueue;
+using ::android::hardware::Void;
+
+using DataMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
+
+void BluetoothAudioDeathRecipient::serviceDied(
+    uint64_t cookie __unused,
+    const wp<::android::hidl::base::V1_0::IBase>& who __unused) {
+  LOG(ERROR) << "BluetoothAudioDeathRecipient::" << __func__
+             << " - BluetoothAudio Service died";
+  provider_->endSession();
+}
+
+BluetoothAudioProvider::BluetoothAudioProvider()
+    : death_recipient_(new BluetoothAudioDeathRecipient(this)),
+      session_type_(SessionType::UNKNOWN),
+      audio_config_({}) {}
+
+Return<void> BluetoothAudioProvider::startSession(
+    const sp<IBluetoothAudioPort>& hostIf,
+    const V2_0::AudioConfiguration& audioConfig, startSession_cb _hidl_cb) {
+  AudioConfiguration audioConfig_2_1;
+
+  audioConfig_2_1.codecConfig() = audioConfig.codecConfig();
+  audioConfig_2_1.pcmConfig() = {
+      .sampleRate = static_cast<SampleRate>(audioConfig.pcmConfig().sampleRate),
+      .channelMode = audioConfig.pcmConfig().channelMode,
+      .bitsPerSample = audioConfig.pcmConfig().bitsPerSample,
+      .dataIntervalUs = 0};
+
+  return startSession_2_1(hostIf, audioConfig_2_1, _hidl_cb);
+}
+
+Return<void> BluetoothAudioProvider::startSession_2_1(
+    const sp<IBluetoothAudioPort>& hostIf,
+    const AudioConfiguration& audioConfig, startSession_cb _hidl_cb) {
+  if (hostIf == nullptr) {
+    _hidl_cb(BluetoothAudioStatus::FAILURE, DataMQ::Descriptor());
+    return Void();
+  }
+
+  /**
+   * Initialize the audio platform if audioConfiguration is supported.
+   * Save the IBluetoothAudioPort interface, so that it can be used
+   * later to send stream control commands to the HAL client, based on
+   * interaction with Audio framework.
+   */
+  audio_config_ = audioConfig;
+  stack_iface_ = hostIf;
+  stack_iface_->linkToDeath(death_recipient_, 0);
+
+  LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
+            << ", AudioConfiguration=[" << toString(audio_config_) << "]";
+
+  onSessionReady(_hidl_cb);
+  return Void();
+}
+
+Return<void> BluetoothAudioProvider::streamStarted(
+    BluetoothAudioStatus status) {
+  LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
+            << ", status=" << toString(status);
+
+  /**
+   * Streaming on control path has started,
+   * HAL server should start the streaming on data path.
+   */
+  if (stack_iface_) {
+    BluetoothAudioSessionReport::ReportControlStatus(session_type_, true,
+                                                     status);
+  } else {
+    LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
+                 << ", status=" << toString(status) << " has NO session";
+  }
+
+  return Void();
+}
+
+Return<void> BluetoothAudioProvider::streamSuspended(
+    BluetoothAudioStatus status) {
+  LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
+            << ", status=" << toString(status);
+
+  /**
+   * Streaming on control path has suspend,
+   * HAL server should suspend the streaming on data path.
+   */
+  if (stack_iface_) {
+    BluetoothAudioSessionReport::ReportControlStatus(session_type_, false,
+                                                     status);
+  } else {
+    LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
+                 << ", status=" << toString(status) << " has NO session";
+  }
+
+  return Void();
+}
+
+Return<void> BluetoothAudioProvider::endSession() {
+  LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_);
+
+  if (stack_iface_) {
+    BluetoothAudioSessionReport::OnSessionEnded(session_type_);
+    stack_iface_->unlinkToDeath(death_recipient_);
+  } else {
+    LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
+              << " has NO session";
+  }
+
+  /**
+   * Clean up the audio platform as remote audio device is no
+   * longer active
+   */
+  stack_iface_ = nullptr;
+  audio_config_ = {};
+
+  return Void();
+}
+
+}  // namespace implementation
+}  // namespace V2_1
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
diff --git a/bluetooth/audio/2.1/default/BluetoothAudioProvider.h b/bluetooth/audio/2.1/default/BluetoothAudioProvider.h
new file mode 100644
index 0000000..a2e611f
--- /dev/null
+++ b/bluetooth/audio/2.1/default/BluetoothAudioProvider.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright 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/bluetooth/audio/2.1/IBluetoothAudioProvider.h>
+
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::sp;
+using ::android::hardware::bluetooth::audio::V2_0::IBluetoothAudioPort;
+
+using BluetoothAudioStatus =
+    ::android::hardware::bluetooth::audio::V2_0::Status;
+
+class BluetoothAudioDeathRecipient;
+
+class BluetoothAudioProvider : public IBluetoothAudioProvider {
+ public:
+  BluetoothAudioProvider();
+  ~BluetoothAudioProvider() = default;
+
+  virtual bool isValid(const SessionType& sessionType) = 0;
+  virtual bool isValid(const V2_0::SessionType& sessionType) = 0;
+
+  Return<void> startSession(const sp<IBluetoothAudioPort>& hostIf,
+                            const V2_0::AudioConfiguration& audioConfig,
+                            startSession_cb _hidl_cb) override;
+  Return<void> startSession_2_1(const sp<IBluetoothAudioPort>& hostIf,
+                                const AudioConfiguration& audioConfig,
+                                startSession_cb _hidl_cb) override;
+  Return<void> streamStarted(BluetoothAudioStatus status) override;
+  Return<void> streamSuspended(BluetoothAudioStatus status) override;
+  Return<void> endSession() override;
+
+ protected:
+  sp<BluetoothAudioDeathRecipient> death_recipient_;
+
+  SessionType session_type_;
+  AudioConfiguration audio_config_;
+  sp<V2_0::IBluetoothAudioPort> stack_iface_;
+
+  virtual Return<void> onSessionReady(startSession_cb _hidl_cb) = 0;
+};
+
+class BluetoothAudioDeathRecipient : public hidl_death_recipient {
+ public:
+  BluetoothAudioDeathRecipient(const sp<BluetoothAudioProvider> provider)
+      : provider_(provider) {}
+
+  virtual void serviceDied(
+      uint64_t cookie,
+      const wp<::android::hidl::base::V1_0::IBase>& who) override;
+
+ private:
+  sp<BluetoothAudioProvider> provider_;
+};
+
+}  // namespace implementation
+}  // namespace V2_1
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
diff --git a/bluetooth/audio/2.1/default/BluetoothAudioProvidersFactory.cpp b/bluetooth/audio/2.1/default/BluetoothAudioProvidersFactory.cpp
new file mode 100644
index 0000000..adf2717
--- /dev/null
+++ b/bluetooth/audio/2.1/default/BluetoothAudioProvidersFactory.cpp
@@ -0,0 +1,174 @@
+/*
+ * Copyright 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 "BTAudioProvidersFactory"
+
+#include "BluetoothAudioProvidersFactory.h"
+
+#include <android-base/logging.h>
+
+#include "BluetoothAudioSupportedCodecsDB.h"
+
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Void;
+using ::android::hardware::bluetooth::audio::V2_0::CodecCapabilities;
+
+A2dpSoftwareAudioProvider
+    BluetoothAudioProvidersFactory::a2dp_software_provider_instance_;
+A2dpOffloadAudioProvider
+    BluetoothAudioProvidersFactory::a2dp_offload_provider_instance_;
+HearingAidAudioProvider
+    BluetoothAudioProvidersFactory::hearing_aid_provider_instance_;
+LeAudioOutputAudioProvider
+    BluetoothAudioProvidersFactory::leaudio_output_provider_instance_;
+LeAudioInputAudioProvider
+    BluetoothAudioProvidersFactory::leaudio_input_provider_instance_;
+
+Return<void> BluetoothAudioProvidersFactory::openProvider(
+    const V2_0::SessionType sessionType, openProvider_cb _hidl_cb) {
+  LOG(INFO) << __func__ << " - SessionType=" << toString(sessionType);
+  BluetoothAudioStatus status = BluetoothAudioStatus::SUCCESS;
+  BluetoothAudioProvider* provider = nullptr;
+  switch (sessionType) {
+    case V2_0::SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH:
+      provider = &a2dp_software_provider_instance_;
+      break;
+    case V2_0::SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH:
+      provider = &a2dp_offload_provider_instance_;
+      break;
+    case V2_0::SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH:
+      provider = &hearing_aid_provider_instance_;
+      break;
+    default:
+      status = BluetoothAudioStatus::FAILURE;
+  }
+  if (provider == nullptr || !provider->isValid(sessionType)) {
+    provider = nullptr;
+    status = BluetoothAudioStatus::FAILURE;
+    LOG(ERROR) << __func__ << " - SessionType=" << toString(sessionType)
+               << ", status=" << toString(status);
+  }
+  _hidl_cb(status, provider);
+  return Void();
+}
+
+Return<void> BluetoothAudioProvidersFactory::openProvider_2_1(
+    const SessionType sessionType, openProvider_2_1_cb _hidl_cb) {
+  LOG(INFO) << __func__ << " - SessionType=" << toString(sessionType);
+  BluetoothAudioStatus status = BluetoothAudioStatus::SUCCESS;
+  BluetoothAudioProvider* provider = nullptr;
+  switch (sessionType) {
+    case SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH:
+      provider = &a2dp_software_provider_instance_;
+      break;
+    case SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH:
+      provider = &a2dp_offload_provider_instance_;
+      break;
+    case SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH:
+      provider = &hearing_aid_provider_instance_;
+      break;
+    case SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH:
+      provider = &leaudio_output_provider_instance_;
+      break;
+    case SessionType::LE_AUDIO_SOFTWARE_DECODED_DATAPATH:
+      provider = &leaudio_input_provider_instance_;
+      break;
+    default:
+      status = BluetoothAudioStatus::FAILURE;
+  }
+  if (provider == nullptr || !provider->isValid(sessionType)) {
+    provider = nullptr;
+    status = BluetoothAudioStatus::FAILURE;
+    LOG(ERROR) << __func__ << " - SessionType=" << toString(sessionType)
+               << ", status=" << toString(status);
+  }
+  _hidl_cb(status, provider);
+  return Void();
+}
+
+Return<void> BluetoothAudioProvidersFactory::getProviderCapabilities(
+    const V2_0::SessionType sessionType, getProviderCapabilities_cb _hidl_cb) {
+  hidl_vec<V2_0::AudioCapabilities> audio_capabilities =
+      hidl_vec<V2_0::AudioCapabilities>(0);
+  if (sessionType == V2_0::SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH) {
+    std::vector<CodecCapabilities> db_codec_capabilities =
+        android::bluetooth::audio::GetOffloadCodecCapabilities(sessionType);
+    if (db_codec_capabilities.size()) {
+      audio_capabilities.resize(db_codec_capabilities.size());
+      for (int i = 0; i < db_codec_capabilities.size(); ++i) {
+        audio_capabilities[i].codecCapabilities(db_codec_capabilities[i]);
+      }
+    }
+  } else if (sessionType != V2_0::SessionType::UNKNOWN) {
+    std::vector<::android::hardware::bluetooth::audio::V2_0::PcmParameters>
+        db_pcm_capabilities =
+            android::bluetooth::audio::GetSoftwarePcmCapabilities();
+    if (db_pcm_capabilities.size() == 1) {
+      audio_capabilities.resize(1);
+      audio_capabilities[0].pcmCapabilities(db_pcm_capabilities[0]);
+    }
+  }
+  LOG(INFO) << __func__ << " - SessionType=" << toString(sessionType)
+            << " supports " << audio_capabilities.size() << " codecs";
+  _hidl_cb(audio_capabilities);
+  return Void();
+}
+
+Return<void> BluetoothAudioProvidersFactory::getProviderCapabilities_2_1(
+    const SessionType sessionType, getProviderCapabilities_2_1_cb _hidl_cb) {
+  hidl_vec<AudioCapabilities> audio_capabilities =
+      hidl_vec<AudioCapabilities>(0);
+  if (sessionType == SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH) {
+    std::vector<CodecCapabilities> db_codec_capabilities =
+        android::bluetooth::audio::GetOffloadCodecCapabilities(sessionType);
+    if (db_codec_capabilities.size()) {
+      audio_capabilities.resize(db_codec_capabilities.size());
+      for (int i = 0; i < db_codec_capabilities.size(); ++i) {
+        audio_capabilities[i].codecCapabilities(db_codec_capabilities[i]);
+      }
+    }
+  } else if (sessionType != SessionType::UNKNOWN) {
+    std::vector<PcmParameters> db_pcm_capabilities =
+        android::bluetooth::audio::GetSoftwarePcmCapabilities_2_1();
+    if (db_pcm_capabilities.size() == 1) {
+      audio_capabilities.resize(1);
+      audio_capabilities[0].pcmCapabilities(db_pcm_capabilities[0]);
+    }
+  }
+  LOG(INFO) << __func__ << " - SessionType=" << toString(sessionType)
+            << " supports " << audio_capabilities.size() << " codecs";
+  _hidl_cb(audio_capabilities);
+  return Void();
+}
+
+IBluetoothAudioProvidersFactory* HIDL_FETCH_IBluetoothAudioProvidersFactory(
+    const char* /* name */) {
+  return new BluetoothAudioProvidersFactory();
+}
+
+}  // namespace implementation
+}  // namespace V2_1
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
diff --git a/bluetooth/audio/2.1/default/BluetoothAudioProvidersFactory.h b/bluetooth/audio/2.1/default/BluetoothAudioProvidersFactory.h
new file mode 100644
index 0000000..fd83694
--- /dev/null
+++ b/bluetooth/audio/2.1/default/BluetoothAudioProvidersFactory.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright 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/bluetooth/audio/2.1/IBluetoothAudioProvidersFactory.h>
+
+#include "A2dpOffloadAudioProvider.h"
+#include "A2dpSoftwareAudioProvider.h"
+#include "BluetoothAudioProvider.h"
+#include "HearingAidAudioProvider.h"
+#include "LeAudioAudioProvider.h"
+
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+namespace V2_1 {
+namespace implementation {
+
+class BluetoothAudioProvidersFactory : public IBluetoothAudioProvidersFactory {
+ public:
+  BluetoothAudioProvidersFactory() {}
+
+  Return<void> openProvider(const V2_0::SessionType sessionType,
+                            openProvider_cb _hidl_cb) override;
+
+  Return<void> getProviderCapabilities(
+      const V2_0::SessionType sessionType,
+      getProviderCapabilities_cb _hidl_cb) override;
+
+  Return<void> openProvider_2_1(const SessionType sessionType,
+                                openProvider_2_1_cb _hidl_cb) override;
+
+  Return<void> getProviderCapabilities_2_1(
+      const SessionType sessionType,
+      getProviderCapabilities_2_1_cb _hidl_cb) override;
+
+ private:
+  static A2dpSoftwareAudioProvider a2dp_software_provider_instance_;
+  static A2dpOffloadAudioProvider a2dp_offload_provider_instance_;
+  static HearingAidAudioProvider hearing_aid_provider_instance_;
+  static LeAudioOutputAudioProvider leaudio_output_provider_instance_;
+  static LeAudioInputAudioProvider leaudio_input_provider_instance_;
+};
+
+extern "C" IBluetoothAudioProvidersFactory*
+HIDL_FETCH_IBluetoothAudioProvidersFactory(const char* name);
+
+}  // namespace implementation
+}  // namespace V2_1
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
diff --git a/bluetooth/audio/2.1/default/HearingAidAudioProvider.cpp b/bluetooth/audio/2.1/default/HearingAidAudioProvider.cpp
new file mode 100644
index 0000000..aded7e1
--- /dev/null
+++ b/bluetooth/audio/2.1/default/HearingAidAudioProvider.cpp
@@ -0,0 +1,112 @@
+/*
+ * Copyright 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 "BTAudioProviderHearingAid"
+
+#include "HearingAidAudioProvider.h"
+
+#include <android-base/logging.h>
+
+#include "BluetoothAudioSessionReport.h"
+#include "BluetoothAudioSupportedCodecsDB.h"
+
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::bluetooth::audio::BluetoothAudioSessionReport;
+using ::android::hardware::Void;
+using ::android::hardware::bluetooth::audio::V2_0::AudioConfiguration;
+
+static constexpr uint32_t kPcmFrameSize = 4;  // 16 bits per sample / stereo
+static constexpr uint32_t kPcmFrameCount = 128;
+static constexpr uint32_t kRtpFrameSize = kPcmFrameSize * kPcmFrameCount;
+static constexpr uint32_t kRtpFrameCount = 7;  // max counts by 1 tick (20ms)
+static constexpr uint32_t kBufferSize = kRtpFrameSize * kRtpFrameCount;
+static constexpr uint32_t kBufferCount = 1;  // single buffer
+static constexpr uint32_t kDataMqSize = kBufferSize * kBufferCount;
+
+HearingAidAudioProvider::HearingAidAudioProvider()
+    : BluetoothAudioProvider(), mDataMQ(nullptr) {
+  LOG(INFO) << __func__ << " - size of audio buffer " << kDataMqSize
+            << " byte(s)";
+  std::unique_ptr<DataMQ> tempDataMQ(
+      new DataMQ(kDataMqSize, /* EventFlag */ true));
+  if (tempDataMQ && tempDataMQ->isValid()) {
+    mDataMQ = std::move(tempDataMQ);
+    session_type_ = SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH;
+  } else {
+    ALOGE_IF(!tempDataMQ, "failed to allocate data MQ");
+    ALOGE_IF(tempDataMQ && !tempDataMQ->isValid(), "data MQ is invalid");
+  }
+}
+
+bool HearingAidAudioProvider::isValid(const V2_0::SessionType& sessionType) {
+  return isValid(static_cast<SessionType>(sessionType));
+}
+
+bool HearingAidAudioProvider::isValid(const SessionType& sessionType) {
+  return (sessionType == session_type_ && mDataMQ && mDataMQ->isValid());
+}
+
+Return<void> HearingAidAudioProvider::startSession(
+    const sp<IBluetoothAudioPort>& hostIf,
+    const V2_0::AudioConfiguration& audioConfig, startSession_cb _hidl_cb) {
+  /**
+   * Initialize the audio platform if audioConfiguration is supported.
+   * Save the IBluetoothAudioPort interface, so that it can be used
+   * later to send stream control commands to the HAL client, based on
+   * interaction with Audio framework.
+   */
+  if (audioConfig.getDiscriminator() !=
+      AudioConfiguration::hidl_discriminator::pcmConfig) {
+    LOG(WARNING) << __func__
+                 << " - Invalid Audio Configuration=" << toString(audioConfig);
+    _hidl_cb(BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION,
+             DataMQ::Descriptor());
+    return Void();
+  } else if (!android::bluetooth::audio::IsSoftwarePcmConfigurationValid(
+                 audioConfig.pcmConfig())) {
+    LOG(WARNING) << __func__ << " - Unsupported PCM Configuration="
+                 << toString(audioConfig.pcmConfig());
+    _hidl_cb(BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION,
+             DataMQ::Descriptor());
+    return Void();
+  }
+
+  return BluetoothAudioProvider::startSession(hostIf, audioConfig, _hidl_cb);
+}
+
+Return<void> HearingAidAudioProvider::onSessionReady(startSession_cb _hidl_cb) {
+  if (mDataMQ && mDataMQ->isValid()) {
+    BluetoothAudioSessionReport::OnSessionStarted(
+        session_type_, stack_iface_, mDataMQ->getDesc(), audio_config_);
+    _hidl_cb(BluetoothAudioStatus::SUCCESS, *mDataMQ->getDesc());
+  } else {
+    _hidl_cb(BluetoothAudioStatus::FAILURE, DataMQ::Descriptor());
+  }
+  return Void();
+}
+
+}  // namespace implementation
+}  // namespace V2_1
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
diff --git a/bluetooth/audio/2.1/default/HearingAidAudioProvider.h b/bluetooth/audio/2.1/default/HearingAidAudioProvider.h
new file mode 100644
index 0000000..c949257
--- /dev/null
+++ b/bluetooth/audio/2.1/default/HearingAidAudioProvider.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright 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 <fmq/MessageQueue.h>
+#include <hidl/MQDescriptor.h>
+
+#include "BluetoothAudioProvider.h"
+
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::kSynchronizedReadWrite;
+using ::android::hardware::MessageQueue;
+
+using DataMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
+
+class HearingAidAudioProvider : public BluetoothAudioProvider {
+ public:
+  HearingAidAudioProvider();
+
+  bool isValid(const SessionType& sessionType) override;
+  bool isValid(const V2_0::SessionType& sessionType) override;
+
+  Return<void> startSession(const sp<IBluetoothAudioPort>& hostIf,
+                            const V2_0::AudioConfiguration& audioConfig,
+                            startSession_cb _hidl_cb) override;
+
+ private:
+  // audio data queue for software encoding
+  std::unique_ptr<DataMQ> mDataMQ;
+
+  Return<void> onSessionReady(startSession_cb _hidl_cb) override;
+};
+
+}  // namespace implementation
+}  // namespace V2_1
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
diff --git a/bluetooth/audio/2.1/default/LeAudioAudioProvider.cpp b/bluetooth/audio/2.1/default/LeAudioAudioProvider.cpp
new file mode 100644
index 0000000..1fa2dce
--- /dev/null
+++ b/bluetooth/audio/2.1/default/LeAudioAudioProvider.cpp
@@ -0,0 +1,201 @@
+/*
+ * Copyright 2020 HIMSA II K/S - www.himsa.com. Represented by EHIMA -
+ * www.ehima.com
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "BTAudioProviderLeAudio"
+
+#include "LeAudioAudioProvider.h"
+
+#include <android-base/logging.h>
+
+#include "BluetoothAudioSessionReport.h"
+#include "BluetoothAudioSupportedCodecsDB.h"
+
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::bluetooth::audio::BluetoothAudioSessionReport;
+using ::android::hardware::Void;
+using ::android::hardware::bluetooth::audio::V2_0::BitsPerSample;
+using ::android::hardware::bluetooth::audio::V2_0::ChannelMode;
+using ::android::hardware::bluetooth::audio::V2_1::SampleRate;
+
+static constexpr uint32_t kBufferOutCount = 2;  // two frame buffer
+static constexpr uint32_t kBufferInCount = 2;   // two frame buffer
+
+LeAudioOutputAudioProvider::LeAudioOutputAudioProvider()
+    : LeAudioAudioProvider() {
+  session_type_ = SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH;
+}
+
+LeAudioInputAudioProvider::LeAudioInputAudioProvider()
+    : LeAudioAudioProvider() {
+  session_type_ = SessionType::LE_AUDIO_SOFTWARE_DECODED_DATAPATH;
+}
+
+LeAudioAudioProvider::LeAudioAudioProvider()
+    : BluetoothAudioProvider(), mDataMQ(nullptr) {}
+
+bool LeAudioAudioProvider::isValid(const V2_0::SessionType& sessionType) {
+  LOG(ERROR) << __func__ << ", invalid session type for Le Audio provider: "
+             << toString(sessionType);
+
+  return false;
+}
+
+bool LeAudioAudioProvider::isValid(const SessionType& sessionType) {
+  return (sessionType == session_type_);
+}
+
+Return<void> LeAudioAudioProvider::startSession_2_1(
+    const sp<V2_0::IBluetoothAudioPort>& hostIf,
+    const AudioConfiguration& audioConfig, startSession_cb _hidl_cb) {
+  /**
+   * Initialize the audio platform if audioConfiguration is supported.
+   * Save the IBluetoothAudioPort interface, so that it can be used
+   * later to send stream control commands to the HAL client, based on
+   * interaction with Audio framework.
+   */
+  if (audioConfig.getDiscriminator() !=
+      AudioConfiguration::hidl_discriminator::pcmConfig) {
+    LOG(WARNING) << __func__
+                 << " - Invalid Audio Configuration=" << toString(audioConfig);
+    _hidl_cb(BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION,
+             DataMQ::Descriptor());
+    return Void();
+  } else if (!android::bluetooth::audio::IsSoftwarePcmConfigurationValid_2_1(
+                 audioConfig.pcmConfig())) {
+    LOG(WARNING) << __func__ << " - Unsupported PCM Configuration="
+                 << toString(audioConfig.pcmConfig());
+    _hidl_cb(BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION,
+             DataMQ::Descriptor());
+    return Void();
+  }
+
+  uint32_t kDataMqSize = 0;
+  switch (audioConfig.pcmConfig().sampleRate) {
+    case SampleRate::RATE_16000:
+      kDataMqSize = 16000;
+      break;
+    case SampleRate::RATE_24000:
+      kDataMqSize = 24000;
+      break;
+    case SampleRate::RATE_44100:
+      kDataMqSize = 44100;
+      break;
+    case SampleRate::RATE_48000:
+      kDataMqSize = 48000;
+      break;
+    case SampleRate::RATE_88200:
+      kDataMqSize = 88200;
+      break;
+    case SampleRate::RATE_96000:
+      kDataMqSize = 96000;
+      break;
+    case SampleRate::RATE_176400:
+      kDataMqSize = 176400;
+      break;
+    case SampleRate::RATE_192000:
+      kDataMqSize = 192000;
+      break;
+    default:
+      /* This should never happen it would be caught while validating
+       * parameters.
+       */
+      break;
+  }
+
+  /* Number of samples per millisecond */
+  kDataMqSize = ceil(kDataMqSize / 1000);
+
+  switch (audioConfig.pcmConfig().channelMode) {
+    case ChannelMode::MONO:
+      break;
+    case ChannelMode::STEREO:
+      kDataMqSize *= 2;
+      break;
+    default:
+      /* This should never happen it would be caught while validating
+       * parameters.
+       */
+      break;
+  }
+
+  switch (audioConfig.pcmConfig().bitsPerSample) {
+    case BitsPerSample::BITS_16:
+      kDataMqSize *= 2;
+      break;
+    case BitsPerSample::BITS_24:
+      kDataMqSize *= 3;
+      break;
+    case BitsPerSample::BITS_32:
+      kDataMqSize *= 4;
+      break;
+    default:
+      /* This should never happen it would be caught while validating
+       * parameters.
+       */
+      break;
+  }
+
+  if (session_type_ == SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH)
+    kDataMqSize *= kBufferOutCount;
+  else if (session_type_ == SessionType::LE_AUDIO_SOFTWARE_DECODED_DATAPATH)
+    kDataMqSize *= kBufferInCount;
+  else
+    LOG(WARNING) << __func__ << ", default single buffer used";
+
+  kDataMqSize *= audioConfig.pcmConfig().dataIntervalUs / 1000;
+
+  LOG(INFO) << __func__ << " - size of audio buffer " << kDataMqSize
+            << " byte(s)";
+
+  std::unique_ptr<DataMQ> tempDataMQ(
+      new DataMQ(kDataMqSize, /* EventFlag */ true));
+  if (tempDataMQ && tempDataMQ->isValid()) {
+    mDataMQ = std::move(tempDataMQ);
+  } else {
+    ALOGE_IF(!tempDataMQ, "failed to allocate data MQ");
+    ALOGE_IF(tempDataMQ && !tempDataMQ->isValid(), "data MQ is invalid");
+    _hidl_cb(BluetoothAudioStatus::FAILURE, DataMQ::Descriptor());
+    return Void();
+  }
+
+  return BluetoothAudioProvider::startSession_2_1(hostIf, audioConfig,
+                                                  _hidl_cb);
+}
+
+Return<void> LeAudioAudioProvider::onSessionReady(startSession_cb _hidl_cb) {
+  if (mDataMQ && mDataMQ->isValid()) {
+    BluetoothAudioSessionReport::OnSessionStarted(
+        session_type_, stack_iface_, mDataMQ->getDesc(), audio_config_);
+    _hidl_cb(BluetoothAudioStatus::SUCCESS, *mDataMQ->getDesc());
+  } else {
+    _hidl_cb(BluetoothAudioStatus::FAILURE, DataMQ::Descriptor());
+  }
+  return Void();
+}
+
+}  // namespace implementation
+}  // namespace V2_1
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
diff --git a/bluetooth/audio/2.1/default/LeAudioAudioProvider.h b/bluetooth/audio/2.1/default/LeAudioAudioProvider.h
new file mode 100644
index 0000000..09b2b54
--- /dev/null
+++ b/bluetooth/audio/2.1/default/LeAudioAudioProvider.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2020 HIMSA II K/S - www.himsa.com. Represented by EHIMA -
+ * www.ehima.com
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/bluetooth/audio/2.1/types.h>
+#include <fmq/MessageQueue.h>
+#include <hidl/MQDescriptor.h>
+
+#include "BluetoothAudioProvider.h"
+
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::kSynchronizedReadWrite;
+using ::android::hardware::MessageQueue;
+
+using DataMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
+
+class LeAudioAudioProvider : public BluetoothAudioProvider {
+ public:
+  LeAudioAudioProvider();
+
+  bool isValid(const SessionType& sessionType) override;
+  bool isValid(const V2_0::SessionType& sessionType) override;
+
+  Return<void> startSession_2_1(const sp<V2_0::IBluetoothAudioPort>& hostIf,
+                                const AudioConfiguration& audioConfig,
+                                startSession_cb _hidl_cb) override;
+
+ private:
+  /** queue for software encodec/decoded audio data */
+  std::unique_ptr<DataMQ> mDataMQ;
+
+  Return<void> onSessionReady(startSession_cb _hidl_cb) override;
+};
+
+class LeAudioOutputAudioProvider : public LeAudioAudioProvider {
+ public:
+  LeAudioOutputAudioProvider();
+};
+
+class LeAudioInputAudioProvider : public LeAudioAudioProvider {
+ public:
+  LeAudioInputAudioProvider();
+};
+
+}  // namespace implementation
+}  // namespace V2_1
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
diff --git a/bluetooth/audio/2.1/default/session/BluetoothAudioSession.cpp b/bluetooth/audio/2.1/default/session/BluetoothAudioSession.cpp
new file mode 100644
index 0000000..ea2c54a
--- /dev/null
+++ b/bluetooth/audio/2.1/default/session/BluetoothAudioSession.cpp
@@ -0,0 +1,467 @@
+/*
+ * Copyright 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 "BTAudioProviderSession"
+
+#include "BluetoothAudioSession.h"
+
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
+
+namespace android {
+namespace bluetooth {
+namespace audio {
+
+using ::android::hardware::audio::common::V5_0::AudioContentType;
+using ::android::hardware::audio::common::V5_0::AudioUsage;
+using ::android::hardware::audio::common::V5_0::PlaybackTrackMetadata;
+using ::android::hardware::audio::common::V5_0::SourceMetadata;
+using ::android::hardware::bluetooth::audio::V2_0::CodecType;
+using ::android::hardware::bluetooth::audio::V2_0::TimeSpec;
+
+const CodecConfiguration BluetoothAudioSession::kInvalidCodecConfiguration = {
+    .codecType = CodecType::UNKNOWN,
+    .encodedAudioBitrate = 0x00000000,
+    .peerMtu = 0xffff,
+    .isScmstEnabled = false,
+    .config = {}};
+AudioConfiguration BluetoothAudioSession::invalidSoftwareAudioConfiguration =
+    {};
+AudioConfiguration BluetoothAudioSession::invalidOffloadAudioConfiguration = {};
+
+static constexpr int kFmqSendTimeoutMs = 1000;  // 1000 ms timeout for sending
+static constexpr int kFmqReceiveTimeoutMs =
+    1000;                               // 1000 ms timeout for receiving
+static constexpr int kWritePollMs = 1;  // polled non-blocking interval
+static constexpr int kReadPollMs = 1;   // polled non-blocking interval
+
+static inline timespec timespec_convert_from_hal(const TimeSpec& TS) {
+  return {.tv_sec = static_cast<long>(TS.tvSec),
+          .tv_nsec = static_cast<long>(TS.tvNSec)};
+}
+
+BluetoothAudioSession::BluetoothAudioSession(const SessionType& session_type)
+    : session_type_(session_type), stack_iface_(nullptr), mDataMQ(nullptr) {
+  invalidSoftwareAudioConfiguration.pcmConfig(kInvalidPcmParameters);
+  invalidOffloadAudioConfiguration.codecConfig(kInvalidCodecConfiguration);
+}
+
+// The report function is used to report that the Bluetooth stack has started
+// this session without any failure, and will invoke session_changed_cb_ to
+// notify those registered bluetooth_audio outputs
+void BluetoothAudioSession::OnSessionStarted(
+    const sp<IBluetoothAudioPort> stack_iface, const DataMQ::Descriptor* dataMQ,
+    const AudioConfiguration& audio_config) {
+  std::lock_guard<std::recursive_mutex> guard(mutex_);
+  if (stack_iface == nullptr) {
+    LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_)
+               << ", IBluetoothAudioPort Invalid";
+  } else if (!UpdateAudioConfig(audio_config)) {
+    LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_)
+               << ", AudioConfiguration=" << toString(audio_config)
+               << " Invalid";
+  } else if (!UpdateDataPath(dataMQ)) {
+    LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_)
+               << " DataMQ Invalid";
+    audio_config_ =
+        (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH
+             ? kInvalidOffloadAudioConfiguration
+             : kInvalidSoftwareAudioConfiguration);
+  } else {
+    stack_iface_ = stack_iface;
+    LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
+              << ", AudioConfiguration=" << toString(audio_config);
+    ReportSessionStatus();
+  }
+}
+
+// The report function is used to report that the Bluetooth stack has ended the
+// session, and will invoke session_changed_cb_ to notify registered
+// bluetooth_audio outputs
+void BluetoothAudioSession::OnSessionEnded() {
+  std::lock_guard<std::recursive_mutex> guard(mutex_);
+  bool toggled = IsSessionReady();
+  LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_);
+  audio_config_ = (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH
+                       ? kInvalidOffloadAudioConfiguration
+                       : kInvalidSoftwareAudioConfiguration);
+  stack_iface_ = nullptr;
+  UpdateDataPath(nullptr);
+  if (toggled) {
+    ReportSessionStatus();
+  }
+}
+
+// invoking the registered session_changed_cb_
+void BluetoothAudioSession::ReportSessionStatus() {
+  // This is locked already by OnSessionStarted / OnSessionEnded
+  if (observers_.empty()) {
+    LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
+              << " has NO port state observer";
+    return;
+  }
+  for (auto& observer : observers_) {
+    uint16_t cookie = observer.first;
+    std::shared_ptr<struct PortStatusCallbacks> cb = observer.second;
+    LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
+              << " notify to bluetooth_audio=0x"
+              << android::base::StringPrintf("%04x", cookie);
+    cb->session_changed_cb_(cookie);
+  }
+}
+
+// The report function is used to report that the Bluetooth stack has notified
+// the result of startStream or suspendStream, and will invoke
+// control_result_cb_ to notify registered bluetooth_audio outputs
+void BluetoothAudioSession::ReportControlStatus(
+    bool start_resp, const BluetoothAudioStatus& status) {
+  std::lock_guard<std::recursive_mutex> guard(mutex_);
+  if (observers_.empty()) {
+    LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
+                 << " has NO port state observer";
+    return;
+  }
+  for (auto& observer : observers_) {
+    uint16_t cookie = observer.first;
+    std::shared_ptr<struct PortStatusCallbacks> cb = observer.second;
+    LOG(INFO) << __func__ << " - status=" << toString(status)
+              << " for SessionType=" << toString(session_type_)
+              << ", bluetooth_audio=0x"
+              << android::base::StringPrintf("%04x", cookie)
+              << (start_resp ? " started" : " suspended");
+    cb->control_result_cb_(cookie, start_resp, status);
+  }
+}
+
+// The function helps to check if this session is ready or not
+// @return: true if the Bluetooth stack has started the specified session
+bool BluetoothAudioSession::IsSessionReady() {
+  std::lock_guard<std::recursive_mutex> guard(mutex_);
+  bool dataMQ_valid =
+      (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH ||
+       (mDataMQ != nullptr && mDataMQ->isValid()));
+  return stack_iface_ != nullptr && dataMQ_valid;
+}
+
+bool BluetoothAudioSession::UpdateDataPath(const DataMQ::Descriptor* dataMQ) {
+  if (dataMQ == nullptr) {
+    // usecase of reset by nullptr
+    mDataMQ = nullptr;
+    return true;
+  }
+  std::unique_ptr<DataMQ> tempDataMQ;
+  tempDataMQ.reset(new DataMQ(*dataMQ));
+  if (!tempDataMQ || !tempDataMQ->isValid()) {
+    mDataMQ = nullptr;
+    return false;
+  }
+  mDataMQ = std::move(tempDataMQ);
+  return true;
+}
+
+bool BluetoothAudioSession::UpdateAudioConfig(
+    const AudioConfiguration& audio_config) {
+  bool is_software_session =
+      (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
+       session_type_ == SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH ||
+       session_type_ == SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH ||
+       session_type_ == SessionType::LE_AUDIO_SOFTWARE_DECODED_DATAPATH);
+  bool is_offload_session =
+      (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
+  auto audio_config_discriminator = audio_config.getDiscriminator();
+  bool is_software_audio_config =
+      (is_software_session &&
+       audio_config_discriminator ==
+           AudioConfiguration::hidl_discriminator::pcmConfig);
+  bool is_offload_audio_config =
+      (is_offload_session &&
+       audio_config_discriminator ==
+           AudioConfiguration::hidl_discriminator::codecConfig);
+  if (!is_software_audio_config && !is_offload_audio_config) {
+    return false;
+  }
+  audio_config_ = audio_config;
+  return true;
+}
+
+// The control function helps the bluetooth_audio module to register
+// PortStatusCallbacks
+// @return: cookie - the assigned number to this bluetooth_audio output
+uint16_t BluetoothAudioSession::RegisterStatusCback(
+    const PortStatusCallbacks& cbacks) {
+  std::lock_guard<std::recursive_mutex> guard(mutex_);
+  uint16_t cookie = ObserversCookieGetInitValue(session_type_);
+  uint16_t cookie_upper_bound = ObserversCookieGetUpperBound(session_type_);
+
+  while (cookie < cookie_upper_bound) {
+    if (observers_.find(cookie) == observers_.end()) {
+      break;
+    }
+    ++cookie;
+  }
+  if (cookie >= cookie_upper_bound) {
+    LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_)
+               << " has " << observers_.size()
+               << " observers already (No Resource)";
+    return kObserversCookieUndefined;
+  }
+  std::shared_ptr<struct PortStatusCallbacks> cb =
+      std::make_shared<struct PortStatusCallbacks>();
+  *cb = cbacks;
+  observers_[cookie] = cb;
+  return cookie;
+}
+
+// The control function helps the bluetooth_audio module to unregister
+// PortStatusCallbacks
+// @param: cookie - indicates which bluetooth_audio output is
+void BluetoothAudioSession::UnregisterStatusCback(uint16_t cookie) {
+  std::lock_guard<std::recursive_mutex> guard(mutex_);
+  if (observers_.erase(cookie) != 1) {
+    LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
+                 << " no such provider=0x"
+                 << android::base::StringPrintf("%04x", cookie);
+  }
+}
+
+// The control function is for the bluetooth_audio module to get the current
+// AudioConfiguration
+const AudioConfiguration& BluetoothAudioSession::GetAudioConfig() {
+  std::lock_guard<std::recursive_mutex> guard(mutex_);
+  if (IsSessionReady()) {
+    return audio_config_;
+  } else if (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH) {
+    return kInvalidOffloadAudioConfiguration;
+  } else {
+    return kInvalidSoftwareAudioConfiguration;
+  }
+}
+
+// Those control functions are for the bluetooth_audio module to start, suspend,
+// stop stream, to check position, and to update metadata.
+bool BluetoothAudioSession::StartStream() {
+  std::lock_guard<std::recursive_mutex> guard(mutex_);
+  if (!IsSessionReady()) {
+    LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
+               << " has NO session";
+    return false;
+  }
+  auto hal_retval = stack_iface_->startStream();
+  if (!hal_retval.isOk()) {
+    LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
+                 << toString(session_type_) << " failed";
+    return false;
+  }
+  return true;
+}
+
+bool BluetoothAudioSession::SuspendStream() {
+  std::lock_guard<std::recursive_mutex> guard(mutex_);
+  if (!IsSessionReady()) {
+    LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
+               << " has NO session";
+    return false;
+  }
+  auto hal_retval = stack_iface_->suspendStream();
+  if (!hal_retval.isOk()) {
+    LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
+                 << toString(session_type_) << " failed";
+    return false;
+  }
+  return true;
+}
+
+void BluetoothAudioSession::StopStream() {
+  std::lock_guard<std::recursive_mutex> guard(mutex_);
+  if (!IsSessionReady()) {
+    return;
+  }
+  auto hal_retval = stack_iface_->stopStream();
+  if (!hal_retval.isOk()) {
+    LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
+                 << toString(session_type_) << " failed";
+  }
+}
+
+bool BluetoothAudioSession::GetPresentationPosition(
+    uint64_t* remote_delay_report_ns, uint64_t* total_bytes_readed,
+    timespec* data_position) {
+  std::lock_guard<std::recursive_mutex> guard(mutex_);
+  if (!IsSessionReady()) {
+    LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
+               << " has NO session";
+    return false;
+  }
+  bool retval = false;
+  auto hal_retval = stack_iface_->getPresentationPosition(
+      [&retval, &remote_delay_report_ns, &total_bytes_readed, &data_position](
+          BluetoothAudioStatus status,
+          const uint64_t& remoteDeviceAudioDelayNanos,
+          uint64_t transmittedOctets,
+          const TimeSpec& transmittedOctetsTimeStamp) {
+        if (status == BluetoothAudioStatus::SUCCESS) {
+          if (remote_delay_report_ns)
+            *remote_delay_report_ns = remoteDeviceAudioDelayNanos;
+          if (total_bytes_readed) *total_bytes_readed = transmittedOctets;
+          if (data_position)
+            *data_position =
+                timespec_convert_from_hal(transmittedOctetsTimeStamp);
+          retval = true;
+        }
+      });
+  if (!hal_retval.isOk()) {
+    LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
+                 << toString(session_type_) << " failed";
+    return false;
+  }
+  return retval;
+}
+
+void BluetoothAudioSession::UpdateTracksMetadata(
+    const struct source_metadata* source_metadata) {
+  std::lock_guard<std::recursive_mutex> guard(mutex_);
+  if (!IsSessionReady()) {
+    LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
+               << " has NO session";
+    return;
+  }
+
+  ssize_t track_count = source_metadata->track_count;
+  LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) << ", "
+            << track_count << " track(s)";
+  if (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
+      session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH) {
+    return;
+  }
+
+  struct playback_track_metadata* track = source_metadata->tracks;
+  SourceMetadata sourceMetadata;
+  PlaybackTrackMetadata* halMetadata;
+
+  sourceMetadata.tracks.resize(track_count);
+  halMetadata = sourceMetadata.tracks.data();
+  while (track_count && track) {
+    halMetadata->usage = static_cast<AudioUsage>(track->usage);
+    halMetadata->contentType =
+        static_cast<AudioContentType>(track->content_type);
+    halMetadata->gain = track->gain;
+    LOG(VERBOSE) << __func__ << " - SessionType=" << toString(session_type_)
+                 << ", usage=" << toString(halMetadata->usage)
+                 << ", content=" << toString(halMetadata->contentType)
+                 << ", gain=" << halMetadata->gain;
+    --track_count;
+    ++track;
+    ++halMetadata;
+  }
+  auto hal_retval = stack_iface_->updateMetadata(sourceMetadata);
+  if (!hal_retval.isOk()) {
+    LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
+                 << toString(session_type_) << " failed";
+  }
+}
+
+// The control function writes stream to FMQ
+size_t BluetoothAudioSession::OutWritePcmData(const void* buffer,
+                                              size_t bytes) {
+  if (buffer == nullptr || !bytes) return 0;
+  size_t totalWritten = 0;
+  int ms_timeout = kFmqSendTimeoutMs;
+  do {
+    std::unique_lock<std::recursive_mutex> lock(mutex_);
+    if (!IsSessionReady()) break;
+    size_t availableToWrite = mDataMQ->availableToWrite();
+    if (availableToWrite) {
+      if (availableToWrite > (bytes - totalWritten)) {
+        availableToWrite = bytes - totalWritten;
+      }
+
+      if (!mDataMQ->write(static_cast<const uint8_t*>(buffer) + totalWritten,
+                          availableToWrite)) {
+        ALOGE("FMQ datapath writing %zu/%zu failed", totalWritten, bytes);
+        return totalWritten;
+      }
+      totalWritten += availableToWrite;
+    } else if (ms_timeout >= kWritePollMs) {
+      lock.unlock();
+      usleep(kWritePollMs * 1000);
+      ms_timeout -= kWritePollMs;
+    } else {
+      ALOGD("out data %zu/%zu overflow %d ms", totalWritten, bytes,
+            (kFmqSendTimeoutMs - ms_timeout));
+      return totalWritten;
+    }
+  } while (totalWritten < bytes);
+  return totalWritten;
+}
+
+// The control function reads stream from FMQ
+size_t BluetoothAudioSession::InReadPcmData(void* buffer, size_t bytes) {
+  if (buffer == nullptr || !bytes) return 0;
+  size_t totalRead = 0;
+  int ms_timeout = kFmqReceiveTimeoutMs;
+  do {
+    std::unique_lock<std::recursive_mutex> lock(mutex_);
+    if (!IsSessionReady()) break;
+    size_t availableToRead = mDataMQ->availableToRead();
+    if (availableToRead) {
+      if (availableToRead > (bytes - totalRead)) {
+        availableToRead = bytes - totalRead;
+      }
+      if (!mDataMQ->read(static_cast<uint8_t*>(buffer) + totalRead,
+                         availableToRead)) {
+        ALOGE("FMQ datapath reading %zu/%zu failed", totalRead, bytes);
+        return totalRead;
+      }
+      totalRead += availableToRead;
+    } else if (ms_timeout >= kReadPollMs) {
+      lock.unlock();
+      usleep(kReadPollMs * 1000);
+      ms_timeout -= kReadPollMs;
+      continue;
+    } else {
+      ALOGD("in data %zu/%zu overflow %d ms", totalRead, bytes,
+            (kFmqReceiveTimeoutMs - ms_timeout));
+      return totalRead;
+    }
+  } while (totalRead < bytes);
+  return totalRead;
+}
+
+std::unique_ptr<BluetoothAudioSessionInstance>
+    BluetoothAudioSessionInstance::instance_ptr =
+        std::unique_ptr<BluetoothAudioSessionInstance>(
+            new BluetoothAudioSessionInstance());
+
+// API to fetch the session
+std::shared_ptr<BluetoothAudioSession>
+BluetoothAudioSessionInstance::GetSessionInstance(
+    const SessionType& session_type) {
+  std::lock_guard<std::mutex> guard(instance_ptr->mutex_);
+  if (!instance_ptr->sessions_map_.empty()) {
+    auto entry = instance_ptr->sessions_map_.find(session_type);
+    if (entry != instance_ptr->sessions_map_.end()) {
+      return entry->second;
+    }
+  }
+  std::shared_ptr<BluetoothAudioSession> session_ptr =
+      std::make_shared<BluetoothAudioSession>(session_type);
+  instance_ptr->sessions_map_[session_type] = session_ptr;
+  return session_ptr;
+}
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace android
diff --git a/bluetooth/audio/2.1/default/session/BluetoothAudioSession.h b/bluetooth/audio/2.1/default/session/BluetoothAudioSession.h
new file mode 100644
index 0000000..7bc12e6
--- /dev/null
+++ b/bluetooth/audio/2.1/default/session/BluetoothAudioSession.h
@@ -0,0 +1,190 @@
+/*
+ * Copyright 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 <mutex>
+#include <unordered_map>
+
+#include <android/hardware/bluetooth/audio/2.0/IBluetoothAudioPort.h>
+#include <android/hardware/bluetooth/audio/2.1/types.h>
+#include <fmq/MessageQueue.h>
+#include <hardware/audio.h>
+#include <hidl/MQDescriptor.h>
+
+namespace android {
+namespace bluetooth {
+namespace audio {
+
+using ::android::sp;
+using ::android::hardware::kSynchronizedReadWrite;
+using ::android::hardware::MessageQueue;
+using ::android::hardware::bluetooth::audio::V2_0::BitsPerSample;
+using ::android::hardware::bluetooth::audio::V2_0::ChannelMode;
+using ::android::hardware::bluetooth::audio::V2_0::CodecConfiguration;
+using ::android::hardware::bluetooth::audio::V2_0::IBluetoothAudioPort;
+using ::android::hardware::bluetooth::audio::V2_1::AudioConfiguration;
+using ::android::hardware::bluetooth::audio::V2_1::PcmParameters;
+using ::android::hardware::bluetooth::audio::V2_1::SampleRate;
+using ::android::hardware::bluetooth::audio::V2_1::SessionType;
+
+using BluetoothAudioStatus =
+    ::android::hardware::bluetooth::audio::V2_0::Status;
+
+using DataMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
+
+static constexpr uint16_t kObserversCookieSize = 0x0010;  // 0x0000 ~ 0x000f
+constexpr uint16_t kObserversCookieUndefined =
+    (static_cast<uint16_t>(SessionType::UNKNOWN) << 8 & 0xff00);
+inline SessionType ObserversCookieGetSessionType(uint16_t cookie) {
+  return static_cast<SessionType>(cookie >> 8 & 0x00ff);
+}
+inline uint16_t ObserversCookieGetInitValue(SessionType session_type) {
+  return (static_cast<uint16_t>(session_type) << 8 & 0xff00);
+}
+inline uint16_t ObserversCookieGetUpperBound(SessionType session_type) {
+  return (static_cast<uint16_t>(session_type) << 8 & 0xff00) +
+         kObserversCookieSize;
+}
+
+// This presents the callbacks of started / suspended and session changed,
+// and the bluetooth_audio module uses to receive the status notification
+struct PortStatusCallbacks {
+  // control_result_cb_ - when the Bluetooth stack reports results of
+  // streamStarted or streamSuspended, the BluetoothAudioProvider will invoke
+  // this callback to report to the bluetooth_audio module.
+  // @param: cookie - indicates which bluetooth_audio output should handle
+  // @param: start_resp - this report is for startStream or not
+  // @param: status - the result of startStream
+  std::function<void(uint16_t cookie, bool start_resp,
+                     const BluetoothAudioStatus& status)>
+      control_result_cb_;
+  // session_changed_cb_ - when the Bluetooth stack start / end session, the
+  // BluetoothAudioProvider will invoke this callback to notify to the
+  // bluetooth_audio module.
+  // @param: cookie - indicates which bluetooth_audio output should handle
+  std::function<void(uint16_t cookie)> session_changed_cb_;
+};
+
+class BluetoothAudioSession {
+ private:
+  // using recursive_mutex to allow hwbinder to re-enter again.
+  std::recursive_mutex mutex_;
+  SessionType session_type_;
+
+  // audio control path to use for both software and offloading
+  sp<IBluetoothAudioPort> stack_iface_;
+  // Audio path (FMQ) for software encoding/decoded data
+  std::unique_ptr<DataMQ> mDataMQ;
+  // audio data configuration for both software and offloading
+  AudioConfiguration audio_config_;
+
+  static AudioConfiguration invalidSoftwareAudioConfiguration;
+  static AudioConfiguration invalidOffloadAudioConfiguration;
+
+  // saving those registered bluetooth_audio's callbacks
+  std::unordered_map<uint16_t, std::shared_ptr<struct PortStatusCallbacks>>
+      observers_;
+
+  bool UpdateDataPath(const DataMQ::Descriptor* dataMQ);
+  bool UpdateAudioConfig(const AudioConfiguration& audio_config);
+  // invoking the registered session_changed_cb_
+  void ReportSessionStatus();
+
+ public:
+  BluetoothAudioSession(const SessionType& session_type);
+
+  // The function helps to check if this session is ready or not
+  // @return: true if the Bluetooth stack has started the specified session
+  bool IsSessionReady();
+
+  // The report function is used to report that the Bluetooth stack has started
+  // this session without any failure, and will invoke session_changed_cb_ to
+  // notify those registered bluetooth_audio outputs
+  void OnSessionStarted(const sp<IBluetoothAudioPort> stack_iface,
+                        const DataMQ::Descriptor* dataMQ,
+                        const AudioConfiguration& audio_config);
+
+  // The report function is used to report that the Bluetooth stack has ended
+  // the session, and will invoke session_changed_cb_ to notify registered
+  // bluetooth_audio outputs
+  void OnSessionEnded();
+
+  // The report function is used to report that the Bluetooth stack has notified
+  // the result of startStream or suspendStream, and will invoke
+  // control_result_cb_ to notify registered bluetooth_audio outputs
+  void ReportControlStatus(bool start_resp, const BluetoothAudioStatus& status);
+
+  // The control function helps the bluetooth_audio module to register
+  // PortStatusCallbacks
+  // @return: cookie - the assigned number to this bluetooth_audio output
+  uint16_t RegisterStatusCback(const PortStatusCallbacks& cbacks);
+
+  // The control function helps the bluetooth_audio module to unregister
+  // PortStatusCallbacks
+  // @param: cookie - indicates which bluetooth_audio output is
+  void UnregisterStatusCback(uint16_t cookie);
+
+  // The control function is for the bluetooth_audio module to get the current
+  // AudioConfiguration
+  const AudioConfiguration& GetAudioConfig();
+
+  // Those control functions are for the bluetooth_audio module to start,
+  // suspend, stop stream, to check position, and to update metadata.
+  bool StartStream();
+  bool SuspendStream();
+  void StopStream();
+  bool GetPresentationPosition(uint64_t* remote_delay_report_ns,
+                               uint64_t* total_bytes_readed,
+                               timespec* data_position);
+  void UpdateTracksMetadata(const struct source_metadata* source_metadata);
+
+  // The control function writes stream to FMQ
+  size_t OutWritePcmData(const void* buffer, size_t bytes);
+  // The control function read stream from FMQ
+  size_t InReadPcmData(void* buffer, size_t bytes);
+
+  static constexpr PcmParameters kInvalidPcmParameters = {
+      .sampleRate = SampleRate::RATE_UNKNOWN,
+      .channelMode = ChannelMode::UNKNOWN,
+      .bitsPerSample = BitsPerSample::BITS_UNKNOWN,
+      .dataIntervalUs = 0,
+  };
+  // can't be constexpr because of non-literal type
+  static const CodecConfiguration kInvalidCodecConfiguration;
+
+  static constexpr AudioConfiguration& kInvalidSoftwareAudioConfiguration =
+      invalidSoftwareAudioConfiguration;
+  static constexpr AudioConfiguration& kInvalidOffloadAudioConfiguration =
+      invalidOffloadAudioConfiguration;
+};
+
+class BluetoothAudioSessionInstance {
+ public:
+  // The API is to fetch the specified session
+  static std::shared_ptr<BluetoothAudioSession> GetSessionInstance(
+      const SessionType& session_type);
+
+ private:
+  static std::unique_ptr<BluetoothAudioSessionInstance> instance_ptr;
+  std::mutex mutex_;
+  std::unordered_map<SessionType, std::shared_ptr<BluetoothAudioSession>>
+      sessions_map_;
+};
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace android
diff --git a/bluetooth/audio/2.1/default/session/BluetoothAudioSessionControl.h b/bluetooth/audio/2.1/default/session/BluetoothAudioSessionControl.h
new file mode 100644
index 0000000..017a611
--- /dev/null
+++ b/bluetooth/audio/2.1/default/session/BluetoothAudioSessionControl.h
@@ -0,0 +1,154 @@
+/*
+ * Copyright 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 "BluetoothAudioSession.h"
+
+namespace android {
+namespace bluetooth {
+namespace audio {
+
+class BluetoothAudioSessionControl {
+ public:
+  // The control API helps to check if session is ready or not
+  // @return: true if the Bluetooth stack has started th specified session
+  static bool IsSessionReady(const SessionType& session_type) {
+    std::shared_ptr<BluetoothAudioSession> session_ptr =
+        BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      return session_ptr->IsSessionReady();
+    }
+    return false;
+  }
+
+  // The control API helps the bluetooth_audio module to register
+  // PortStatusCallbacks
+  // @return: cookie - the assigned number to this bluetooth_audio output
+  static uint16_t RegisterControlResultCback(
+      const SessionType& session_type, const PortStatusCallbacks& cbacks) {
+    std::shared_ptr<BluetoothAudioSession> session_ptr =
+        BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      return session_ptr->RegisterStatusCback(cbacks);
+    }
+    return kObserversCookieUndefined;
+  }
+
+  // The control API helps the bluetooth_audio module to unregister
+  // PortStatusCallbacks
+  // @param: cookie - indicates which bluetooth_audio output is
+  static void UnregisterControlResultCback(const SessionType& session_type,
+                                           uint16_t cookie) {
+    std::shared_ptr<BluetoothAudioSession> session_ptr =
+        BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      session_ptr->UnregisterStatusCback(cookie);
+    }
+  }
+
+  // The control API for the bluetooth_audio module to get current
+  // AudioConfiguration
+  static const AudioConfiguration& GetAudioConfig(
+      const SessionType& session_type) {
+    std::shared_ptr<BluetoothAudioSession> session_ptr =
+        BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      return session_ptr->GetAudioConfig();
+    } else if (session_type == SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH) {
+      return BluetoothAudioSession::kInvalidOffloadAudioConfiguration;
+    } else {
+      return BluetoothAudioSession::kInvalidSoftwareAudioConfiguration;
+    }
+  }
+
+  // Those control APIs for the bluetooth_audio module to start / suspend / stop
+  // stream, to check position, and to update metadata.
+  static bool StartStream(const SessionType& session_type) {
+    std::shared_ptr<BluetoothAudioSession> session_ptr =
+        BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      return session_ptr->StartStream();
+    }
+    return false;
+  }
+
+  static bool SuspendStream(const SessionType& session_type) {
+    std::shared_ptr<BluetoothAudioSession> session_ptr =
+        BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      return session_ptr->SuspendStream();
+    }
+    return false;
+  }
+
+  static void StopStream(const SessionType& session_type) {
+    std::shared_ptr<BluetoothAudioSession> session_ptr =
+        BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      session_ptr->StopStream();
+    }
+  }
+
+  static bool GetPresentationPosition(const SessionType& session_type,
+                                      uint64_t* remote_delay_report_ns,
+                                      uint64_t* total_bytes_readed,
+                                      timespec* data_position) {
+    std::shared_ptr<BluetoothAudioSession> session_ptr =
+        BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      return session_ptr->GetPresentationPosition(
+          remote_delay_report_ns, total_bytes_readed, data_position);
+    }
+    return false;
+  }
+
+  static void UpdateTracksMetadata(
+      const SessionType& session_type,
+      const struct source_metadata* source_metadata) {
+    std::shared_ptr<BluetoothAudioSession> session_ptr =
+        BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      session_ptr->UpdateTracksMetadata(source_metadata);
+    }
+  }
+
+  // The control API writes stream to FMQ
+  static size_t OutWritePcmData(const SessionType& session_type,
+                                const void* buffer, size_t bytes) {
+    std::shared_ptr<BluetoothAudioSession> session_ptr =
+        BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      return session_ptr->OutWritePcmData(buffer, bytes);
+    }
+    return 0;
+  }
+
+  // The control API reads stream from FMQ
+  static size_t InReadPcmData(const SessionType& session_type, void* buffer,
+                              size_t bytes) {
+    std::shared_ptr<BluetoothAudioSession> session_ptr =
+        BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      return session_ptr->InReadPcmData(buffer, bytes);
+    }
+    return 0;
+  }
+};
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace android
diff --git a/bluetooth/audio/2.1/default/session/BluetoothAudioSessionReport.h b/bluetooth/audio/2.1/default/session/BluetoothAudioSessionReport.h
new file mode 100644
index 0000000..267bf8f
--- /dev/null
+++ b/bluetooth/audio/2.1/default/session/BluetoothAudioSessionReport.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 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 "BluetoothAudioSession.h"
+
+namespace android {
+namespace bluetooth {
+namespace audio {
+
+class BluetoothAudioSessionReport {
+ public:
+  // The API reports the Bluetooth stack has started the session, and will
+  // inform registered bluetooth_audio session
+  static void OnSessionStarted(const SessionType& session_type,
+                               const sp<IBluetoothAudioPort> host_iface,
+                               const DataMQ::Descriptor* dataMQ,
+                               const AudioConfiguration& audio_config) {
+    std::shared_ptr<BluetoothAudioSession> session_ptr =
+        BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      session_ptr->OnSessionStarted(host_iface, dataMQ, audio_config);
+    }
+  }
+  // The API reports the Bluetooth stack has ended the session, and will
+  // inform registered bluetooth_audio outputs
+  static void OnSessionEnded(const SessionType& session_type) {
+    std::shared_ptr<BluetoothAudioSession> session_ptr =
+        BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      session_ptr->OnSessionEnded();
+    }
+  }
+  // The API reports the Bluetooth stack has replied the result of startStream
+  // or suspendStream, and will inform registered bluetooth_audio outputs
+  static void ReportControlStatus(const SessionType& session_type,
+                                  const bool& start_resp,
+                                  const BluetoothAudioStatus& status) {
+    std::shared_ptr<BluetoothAudioSession> session_ptr =
+        BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      session_ptr->ReportControlStatus(start_resp, status);
+    }
+  }
+};
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace android
diff --git a/bluetooth/audio/2.1/default/session/BluetoothAudioSupportedCodecsDB.cpp b/bluetooth/audio/2.1/default/session/BluetoothAudioSupportedCodecsDB.cpp
new file mode 100644
index 0000000..d15db49
--- /dev/null
+++ b/bluetooth/audio/2.1/default/session/BluetoothAudioSupportedCodecsDB.cpp
@@ -0,0 +1,487 @@
+/*
+ * Copyright 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 "BTAudioProviderSessionCodecsDB"
+
+#include "BluetoothAudioSupportedCodecsDB.h"
+
+#include <android-base/logging.h>
+
+namespace android {
+namespace bluetooth {
+namespace audio {
+
+using ::android::hardware::bluetooth::audio::V2_0::AacObjectType;
+using ::android::hardware::bluetooth::audio::V2_0::AacParameters;
+using ::android::hardware::bluetooth::audio::V2_0::AacVariableBitRate;
+using ::android::hardware::bluetooth::audio::V2_0::AptxParameters;
+using ::android::hardware::bluetooth::audio::V2_0::BitsPerSample;
+using ::android::hardware::bluetooth::audio::V2_0::ChannelMode;
+using ::android::hardware::bluetooth::audio::V2_0::CodecType;
+using ::android::hardware::bluetooth::audio::V2_0::LdacChannelMode;
+using ::android::hardware::bluetooth::audio::V2_0::LdacParameters;
+using ::android::hardware::bluetooth::audio::V2_0::LdacQualityIndex;
+using ::android::hardware::bluetooth::audio::V2_0::SbcAllocMethod;
+using ::android::hardware::bluetooth::audio::V2_0::SbcBlockLength;
+using ::android::hardware::bluetooth::audio::V2_0::SbcChannelMode;
+using ::android::hardware::bluetooth::audio::V2_0::SbcNumSubbands;
+using ::android::hardware::bluetooth::audio::V2_0::SbcParameters;
+using ::android::hardware::bluetooth::audio::V2_1::SampleRate;
+
+// Default Supported PCM Parameters
+static const ::android::hardware::bluetooth::audio::V2_0::PcmParameters
+    kDefaultSoftwarePcmCapabilities = {
+        .sampleRate = static_cast<
+            android::hardware::bluetooth::audio::V2_0::SampleRate>(
+            android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_44100 |
+            android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_48000 |
+            android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_88200 |
+            android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_96000 |
+            android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_16000),
+        .channelMode =
+            static_cast<ChannelMode>(ChannelMode::MONO | ChannelMode::STEREO),
+        .bitsPerSample = static_cast<BitsPerSample>(BitsPerSample::BITS_16 |
+                                                    BitsPerSample::BITS_24 |
+                                                    BitsPerSample::BITS_32)};
+
+static const PcmParameters kDefaultSoftwarePcmCapabilities_2_1 = {
+    .sampleRate = static_cast<SampleRate>(
+        SampleRate::RATE_48000 | SampleRate::RATE_44100 |
+        SampleRate::RATE_32000 | SampleRate::RATE_24000 |
+        SampleRate::RATE_16000 | SampleRate::RATE_8000),
+    .channelMode =
+        static_cast<ChannelMode>(ChannelMode::MONO | ChannelMode::STEREO),
+    .bitsPerSample = static_cast<BitsPerSample>(BitsPerSample::BITS_16)};
+
+// Default Supported Codecs
+// SBC: mSampleRate:(44100), mBitsPerSample:(16), mChannelMode:(MONO|STEREO)
+//      all blocks | subbands 8 | Loudness
+static const SbcParameters kDefaultOffloadSbcCapability = {
+    .sampleRate =
+        android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_44100,
+    .channelMode = static_cast<SbcChannelMode>(SbcChannelMode::MONO |
+                                               SbcChannelMode::JOINT_STEREO),
+    .blockLength = static_cast<SbcBlockLength>(
+        SbcBlockLength::BLOCKS_4 | SbcBlockLength::BLOCKS_8 |
+        SbcBlockLength::BLOCKS_12 | SbcBlockLength::BLOCKS_16),
+    .numSubbands = SbcNumSubbands::SUBBAND_8,
+    .allocMethod = SbcAllocMethod::ALLOC_MD_L,
+    .bitsPerSample = BitsPerSample::BITS_16,
+    .minBitpool = 2,
+    .maxBitpool = 53};
+
+// AAC: mSampleRate:(44100), mBitsPerSample:(16), mChannelMode:(STEREO)
+static const AacParameters kDefaultOffloadAacCapability = {
+    .objectType = AacObjectType::MPEG2_LC,
+    .sampleRate =
+        android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_44100,
+    .channelMode = ChannelMode::STEREO,
+    .variableBitRateEnabled = AacVariableBitRate::ENABLED,
+    .bitsPerSample = BitsPerSample::BITS_16};
+
+// LDAC: mSampleRate:(44100|48000|88200|96000), mBitsPerSample:(16|24|32),
+//       mChannelMode:(DUAL|STEREO)
+static const LdacParameters kDefaultOffloadLdacCapability = {
+    .sampleRate =
+        static_cast<android::hardware::bluetooth::audio::V2_0::SampleRate>(
+            android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_44100 |
+            android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_48000 |
+            android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_88200 |
+            android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_96000),
+    .channelMode = static_cast<LdacChannelMode>(LdacChannelMode::DUAL |
+                                                LdacChannelMode::STEREO),
+    .qualityIndex = LdacQualityIndex::QUALITY_HIGH,
+    .bitsPerSample = static_cast<BitsPerSample>(BitsPerSample::BITS_16 |
+                                                BitsPerSample::BITS_24 |
+                                                BitsPerSample::BITS_32)};
+
+// aptX: mSampleRate:(44100|48000), mBitsPerSample:(16), mChannelMode:(STEREO)
+static const AptxParameters kDefaultOffloadAptxCapability = {
+    .sampleRate =
+        static_cast<android::hardware::bluetooth::audio::V2_0::SampleRate>(
+            android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_44100 |
+            android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_48000),
+    .channelMode = ChannelMode::STEREO,
+    .bitsPerSample = BitsPerSample::BITS_16,
+};
+
+// aptX HD: mSampleRate:(44100|48000), mBitsPerSample:(24),
+//          mChannelMode:(STEREO)
+static const AptxParameters kDefaultOffloadAptxHdCapability = {
+    .sampleRate =
+        static_cast<android::hardware::bluetooth::audio::V2_0::SampleRate>(
+            android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_44100 |
+            android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_48000),
+    .channelMode = ChannelMode::STEREO,
+    .bitsPerSample = BitsPerSample::BITS_24,
+};
+
+const std::vector<CodecCapabilities> kDefaultOffloadA2dpCodecCapabilities = {
+    {.codecType = CodecType::SBC, .capabilities = {}},
+    {.codecType = CodecType::AAC, .capabilities = {}},
+    {.codecType = CodecType::LDAC, .capabilities = {}},
+    {.codecType = CodecType::APTX, .capabilities = {}},
+    {.codecType = CodecType::APTX_HD, .capabilities = {}}};
+
+static bool IsSingleBit(uint32_t bitmasks, uint32_t bitfield) {
+  bool single = false;
+  uint32_t test_bit = 0x00000001;
+  while (test_bit <= bitmasks && test_bit <= bitfield) {
+    if (bitfield & test_bit && bitmasks & test_bit) {
+      if (single) return false;
+      single = true;
+    }
+    if (test_bit == 0x80000000) break;
+    test_bit <<= 1;
+  }
+  return single;
+}
+
+static bool IsOffloadSbcConfigurationValid(
+    const CodecConfiguration::CodecSpecific& codec_specific);
+static bool IsOffloadAacConfigurationValid(
+    const CodecConfiguration::CodecSpecific& codec_specific);
+static bool IsOffloadLdacConfigurationValid(
+    const CodecConfiguration::CodecSpecific& codec_specific);
+static bool IsOffloadAptxConfigurationValid(
+    const CodecConfiguration::CodecSpecific& codec_specific);
+static bool IsOffloadAptxHdConfigurationValid(
+    const CodecConfiguration::CodecSpecific& codec_specific);
+
+static bool IsOffloadSbcConfigurationValid(
+    const CodecConfiguration::CodecSpecific& codec_specific) {
+  if (codec_specific.getDiscriminator() !=
+      CodecConfiguration::CodecSpecific::hidl_discriminator::sbcConfig) {
+    LOG(WARNING) << __func__
+                 << ": Invalid CodecSpecific=" << toString(codec_specific);
+    return false;
+  }
+  const SbcParameters sbc_data = codec_specific.sbcConfig();
+  if (!IsSingleBit(static_cast<uint32_t>(sbc_data.sampleRate), 0xff) ||
+      !IsSingleBit(static_cast<uint32_t>(sbc_data.channelMode), 0x0f) ||
+      !IsSingleBit(static_cast<uint32_t>(sbc_data.blockLength), 0xf0) ||
+      !IsSingleBit(static_cast<uint32_t>(sbc_data.numSubbands), 0x0c) ||
+      !IsSingleBit(static_cast<uint32_t>(sbc_data.allocMethod), 0x03) ||
+      !IsSingleBit(static_cast<uint32_t>(sbc_data.bitsPerSample), 0x07) ||
+      sbc_data.minBitpool > sbc_data.maxBitpool) {
+    LOG(WARNING) << __func__
+                 << ": Invalid CodecSpecific=" << toString(codec_specific);
+    return false;
+  } else if ((sbc_data.sampleRate & kDefaultOffloadSbcCapability.sampleRate) &&
+             (sbc_data.channelMode &
+              kDefaultOffloadSbcCapability.channelMode) &&
+             (sbc_data.blockLength &
+              kDefaultOffloadSbcCapability.blockLength) &&
+             (sbc_data.numSubbands &
+              kDefaultOffloadSbcCapability.numSubbands) &&
+             (sbc_data.allocMethod &
+              kDefaultOffloadSbcCapability.allocMethod) &&
+             (sbc_data.bitsPerSample &
+              kDefaultOffloadSbcCapability.bitsPerSample) &&
+             (kDefaultOffloadSbcCapability.minBitpool <= sbc_data.minBitpool &&
+              sbc_data.maxBitpool <= kDefaultOffloadSbcCapability.maxBitpool)) {
+    return true;
+  }
+  LOG(WARNING) << __func__
+               << ": Unsupported CodecSpecific=" << toString(codec_specific);
+  return false;
+}
+
+static bool IsOffloadAacConfigurationValid(
+    const CodecConfiguration::CodecSpecific& codec_specific) {
+  if (codec_specific.getDiscriminator() !=
+      CodecConfiguration::CodecSpecific::hidl_discriminator::aacConfig) {
+    LOG(WARNING) << __func__
+                 << ": Invalid CodecSpecific=" << toString(codec_specific);
+    return false;
+  }
+  const AacParameters aac_data = codec_specific.aacConfig();
+  if (!IsSingleBit(static_cast<uint32_t>(aac_data.objectType), 0xf0) ||
+      !IsSingleBit(static_cast<uint32_t>(aac_data.sampleRate), 0xff) ||
+      !IsSingleBit(static_cast<uint32_t>(aac_data.channelMode), 0x03) ||
+      !IsSingleBit(static_cast<uint32_t>(aac_data.bitsPerSample), 0x07)) {
+    LOG(WARNING) << __func__
+                 << ": Invalid CodecSpecific=" << toString(codec_specific);
+    return false;
+  } else if ((aac_data.objectType & kDefaultOffloadAacCapability.objectType) &&
+             (aac_data.sampleRate & kDefaultOffloadAacCapability.sampleRate) &&
+             (aac_data.channelMode &
+              kDefaultOffloadAacCapability.channelMode) &&
+             (aac_data.variableBitRateEnabled == AacVariableBitRate::DISABLED ||
+              kDefaultOffloadAacCapability.variableBitRateEnabled ==
+                  AacVariableBitRate::ENABLED) &&
+             (aac_data.bitsPerSample &
+              kDefaultOffloadAacCapability.bitsPerSample)) {
+    return true;
+  }
+  LOG(WARNING) << __func__
+               << ": Unsupported CodecSpecific=" << toString(codec_specific);
+  return false;
+}
+
+static bool IsOffloadLdacConfigurationValid(
+    const CodecConfiguration::CodecSpecific& codec_specific) {
+  if (codec_specific.getDiscriminator() !=
+      CodecConfiguration::CodecSpecific::hidl_discriminator::ldacConfig) {
+    LOG(WARNING) << __func__
+                 << ": Invalid CodecSpecific=" << toString(codec_specific);
+    return false;
+  }
+  const LdacParameters ldac_data = codec_specific.ldacConfig();
+  if (!IsSingleBit(static_cast<uint32_t>(ldac_data.sampleRate), 0xff) ||
+      !IsSingleBit(static_cast<uint32_t>(ldac_data.channelMode), 0x07) ||
+      (ldac_data.qualityIndex > LdacQualityIndex::QUALITY_LOW &&
+       ldac_data.qualityIndex != LdacQualityIndex::QUALITY_ABR) ||
+      !IsSingleBit(static_cast<uint32_t>(ldac_data.bitsPerSample), 0x07)) {
+    LOG(WARNING) << __func__
+                 << ": Invalid CodecSpecific=" << toString(codec_specific);
+    return false;
+  } else if ((ldac_data.sampleRate &
+              kDefaultOffloadLdacCapability.sampleRate) &&
+             (ldac_data.channelMode &
+              kDefaultOffloadLdacCapability.channelMode) &&
+             (ldac_data.bitsPerSample &
+              kDefaultOffloadLdacCapability.bitsPerSample)) {
+    return true;
+  }
+  LOG(WARNING) << __func__
+               << ": Unsupported CodecSpecific=" << toString(codec_specific);
+  return false;
+}
+
+static bool IsOffloadAptxConfigurationValid(
+    const CodecConfiguration::CodecSpecific& codec_specific) {
+  if (codec_specific.getDiscriminator() !=
+      CodecConfiguration::CodecSpecific::hidl_discriminator::aptxConfig) {
+    LOG(WARNING) << __func__
+                 << ": Invalid CodecSpecific=" << toString(codec_specific);
+    return false;
+  }
+  const AptxParameters aptx_data = codec_specific.aptxConfig();
+  if (!IsSingleBit(static_cast<uint32_t>(aptx_data.sampleRate), 0xff) ||
+      !IsSingleBit(static_cast<uint32_t>(aptx_data.channelMode), 0x03) ||
+      !IsSingleBit(static_cast<uint32_t>(aptx_data.bitsPerSample), 0x07)) {
+    LOG(WARNING) << __func__
+                 << ": Invalid CodecSpecific=" << toString(codec_specific);
+    return false;
+  } else if ((aptx_data.sampleRate &
+              kDefaultOffloadAptxCapability.sampleRate) &&
+             (aptx_data.channelMode &
+              kDefaultOffloadAptxCapability.channelMode) &&
+             (aptx_data.bitsPerSample &
+              kDefaultOffloadAptxCapability.bitsPerSample)) {
+    return true;
+  }
+  LOG(WARNING) << __func__
+               << ": Unsupported CodecSpecific=" << toString(codec_specific);
+  return false;
+}
+
+static bool IsOffloadAptxHdConfigurationValid(
+    const CodecConfiguration::CodecSpecific& codec_specific) {
+  if (codec_specific.getDiscriminator() !=
+      CodecConfiguration::CodecSpecific::hidl_discriminator::aptxConfig) {
+    LOG(WARNING) << __func__
+                 << ": Invalid CodecSpecific=" << toString(codec_specific);
+    return false;
+  }
+  const AptxParameters aptx_data = codec_specific.aptxConfig();
+  if (!IsSingleBit(static_cast<uint32_t>(aptx_data.sampleRate), 0xff) ||
+      !IsSingleBit(static_cast<uint32_t>(aptx_data.channelMode), 0x03) ||
+      !IsSingleBit(static_cast<uint32_t>(aptx_data.bitsPerSample), 0x07)) {
+    LOG(WARNING) << __func__
+                 << ": Invalid CodecSpecific=" << toString(codec_specific);
+    return false;
+  } else if ((aptx_data.sampleRate &
+              kDefaultOffloadAptxHdCapability.sampleRate) &&
+             (aptx_data.channelMode &
+              kDefaultOffloadAptxHdCapability.channelMode) &&
+             (aptx_data.bitsPerSample &
+              kDefaultOffloadAptxHdCapability.bitsPerSample)) {
+    return true;
+  }
+  LOG(WARNING) << __func__
+               << ": Unsupported CodecSpecific=" << toString(codec_specific);
+  return false;
+}
+
+std::vector<::android::hardware::bluetooth::audio::V2_0::PcmParameters>
+GetSoftwarePcmCapabilities() {
+  return std::vector<
+      ::android::hardware::bluetooth::audio::V2_0::PcmParameters>(
+      1, kDefaultSoftwarePcmCapabilities);
+}
+
+std::vector<PcmParameters> GetSoftwarePcmCapabilities_2_1() {
+  return std::vector<PcmParameters>(1, kDefaultSoftwarePcmCapabilities_2_1);
+}
+
+std::vector<CodecCapabilities> GetOffloadCodecCapabilities(
+    const ::android::hardware::bluetooth::audio::V2_0::SessionType&
+        session_type) {
+  return GetOffloadCodecCapabilities(static_cast<SessionType>(session_type));
+}
+
+std::vector<CodecCapabilities> GetOffloadCodecCapabilities(
+    const SessionType& session_type) {
+  if (session_type != SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH) {
+    return std::vector<CodecCapabilities>(0);
+  }
+  std::vector<CodecCapabilities> offload_a2dp_codec_capabilities =
+      kDefaultOffloadA2dpCodecCapabilities;
+  for (auto& codec_capability : offload_a2dp_codec_capabilities) {
+    switch (codec_capability.codecType) {
+      case CodecType::SBC:
+        codec_capability.capabilities.sbcCapabilities(
+            kDefaultOffloadSbcCapability);
+        break;
+      case CodecType::AAC:
+        codec_capability.capabilities.aacCapabilities(
+            kDefaultOffloadAacCapability);
+        break;
+      case CodecType::LDAC:
+        codec_capability.capabilities.ldacCapabilities(
+            kDefaultOffloadLdacCapability);
+        break;
+      case CodecType::APTX:
+        codec_capability.capabilities.aptxCapabilities(
+            kDefaultOffloadAptxCapability);
+        break;
+      case CodecType::APTX_HD:
+        codec_capability.capabilities.aptxCapabilities(
+            kDefaultOffloadAptxHdCapability);
+        break;
+      case CodecType::UNKNOWN:
+        codec_capability = {};
+        break;
+    }
+  }
+  return offload_a2dp_codec_capabilities;
+}
+
+bool IsSoftwarePcmConfigurationValid(
+    const ::android::hardware::bluetooth::audio::V2_0::PcmParameters&
+        pcm_config) {
+  if ((pcm_config.sampleRate !=
+           android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_44100 &&
+       pcm_config.sampleRate !=
+           android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_48000 &&
+       pcm_config.sampleRate !=
+           android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_88200 &&
+       pcm_config.sampleRate !=
+           android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_96000 &&
+       pcm_config.sampleRate !=
+           android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_16000 &&
+       pcm_config.sampleRate !=
+           android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_24000) ||
+      (pcm_config.bitsPerSample != BitsPerSample::BITS_16 &&
+       pcm_config.bitsPerSample != BitsPerSample::BITS_24 &&
+       pcm_config.bitsPerSample != BitsPerSample::BITS_32) ||
+      (pcm_config.channelMode != ChannelMode::MONO &&
+       pcm_config.channelMode != ChannelMode::STEREO)) {
+    LOG(WARNING) << __func__
+                 << ": Invalid PCM Configuration=" << toString(pcm_config);
+    return false;
+  } else if (pcm_config.sampleRate &
+                 kDefaultSoftwarePcmCapabilities.sampleRate &&
+             pcm_config.bitsPerSample &
+                 kDefaultSoftwarePcmCapabilities.bitsPerSample &&
+             pcm_config.channelMode &
+                 kDefaultSoftwarePcmCapabilities.channelMode) {
+    return true;
+  }
+  LOG(WARNING) << __func__
+               << ": Unsupported PCM Configuration=" << toString(pcm_config);
+  return false;
+}
+
+bool IsSoftwarePcmConfigurationValid_2_1(const PcmParameters& pcm_config) {
+  if ((pcm_config.sampleRate != SampleRate::RATE_44100 &&
+       pcm_config.sampleRate != SampleRate::RATE_48000 &&
+       pcm_config.sampleRate != SampleRate::RATE_88200 &&
+       pcm_config.sampleRate != SampleRate::RATE_96000 &&
+       pcm_config.sampleRate != SampleRate::RATE_16000 &&
+       pcm_config.sampleRate != SampleRate::RATE_24000) ||
+      (pcm_config.bitsPerSample != BitsPerSample::BITS_16 &&
+       pcm_config.bitsPerSample != BitsPerSample::BITS_24 &&
+       pcm_config.bitsPerSample != BitsPerSample::BITS_32) ||
+      (pcm_config.channelMode != ChannelMode::MONO &&
+       pcm_config.channelMode != ChannelMode::STEREO)) {
+    LOG(WARNING) << __func__
+                 << ": Invalid PCM Configuration=" << toString(pcm_config);
+    return false;
+  } else if (pcm_config.sampleRate &
+                 kDefaultSoftwarePcmCapabilities_2_1.sampleRate &&
+             pcm_config.bitsPerSample &
+                 kDefaultSoftwarePcmCapabilities_2_1.bitsPerSample &&
+             pcm_config.channelMode &
+                 kDefaultSoftwarePcmCapabilities_2_1.channelMode &&
+             pcm_config.dataIntervalUs != 0) {
+    return true;
+  }
+  LOG(WARNING) << __func__
+               << ": Unsupported PCM Configuration=" << toString(pcm_config);
+  return false;
+}
+
+bool IsOffloadCodecConfigurationValid(const SessionType& session_type,
+                                      const CodecConfiguration& codec_config) {
+  if (session_type != SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH) {
+    LOG(ERROR) << __func__
+               << ": Invalid SessionType=" << toString(session_type);
+    return false;
+  } else if (codec_config.encodedAudioBitrate < 0x00000001 ||
+             0x00ffffff < codec_config.encodedAudioBitrate) {
+    LOG(ERROR) << __func__ << ": Unsupported Codec Configuration="
+               << toString(codec_config);
+    return false;
+  }
+  const CodecConfiguration::CodecSpecific& codec_specific = codec_config.config;
+  switch (codec_config.codecType) {
+    case CodecType::SBC:
+      if (IsOffloadSbcConfigurationValid(codec_specific)) {
+        return true;
+      }
+      return false;
+    case CodecType::AAC:
+      if (IsOffloadAacConfigurationValid(codec_specific)) {
+        return true;
+      }
+      return false;
+    case CodecType::LDAC:
+      if (IsOffloadLdacConfigurationValid(codec_specific)) {
+        return true;
+      }
+      return false;
+    case CodecType::APTX:
+      if (IsOffloadAptxConfigurationValid(codec_specific)) {
+        return true;
+      }
+      return false;
+    case CodecType::APTX_HD:
+      if (IsOffloadAptxHdConfigurationValid(codec_specific)) {
+        return true;
+      }
+      return false;
+    case CodecType::UNKNOWN:
+      return false;
+  }
+  return false;
+}
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace android
diff --git a/bluetooth/audio/2.1/default/session/BluetoothAudioSupportedCodecsDB.h b/bluetooth/audio/2.1/default/session/BluetoothAudioSupportedCodecsDB.h
new file mode 100644
index 0000000..9b2f680
--- /dev/null
+++ b/bluetooth/audio/2.1/default/session/BluetoothAudioSupportedCodecsDB.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright 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/bluetooth/audio/2.0/types.h>
+#include <android/hardware/bluetooth/audio/2.1/types.h>
+
+namespace android {
+namespace bluetooth {
+namespace audio {
+
+using ::android::hardware::bluetooth::audio::V2_0::CodecCapabilities;
+using ::android::hardware::bluetooth::audio::V2_0::CodecConfiguration;
+using ::android::hardware::bluetooth::audio::V2_1::PcmParameters;
+using ::android::hardware::bluetooth::audio::V2_1::SessionType;
+
+std::vector<::android::hardware::bluetooth::audio::V2_0::PcmParameters>
+GetSoftwarePcmCapabilities();
+std::vector<PcmParameters> GetSoftwarePcmCapabilities_2_1();
+std::vector<CodecCapabilities> GetOffloadCodecCapabilities(
+    const SessionType& session_type);
+std::vector<CodecCapabilities> GetOffloadCodecCapabilities(
+    const ::android::hardware::bluetooth::audio::V2_0::SessionType&
+        session_type);
+
+bool IsSoftwarePcmConfigurationValid_2_1(const PcmParameters& pcm_config);
+bool IsSoftwarePcmConfigurationValid(
+    const ::android::hardware::bluetooth::audio::V2_0::PcmParameters&
+        pcm_config);
+bool IsOffloadCodecConfigurationValid(const SessionType& session_type,
+                                      const CodecConfiguration& codec_config);
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace android
diff --git a/bluetooth/audio/2.1/types.hal b/bluetooth/audio/2.1/types.hal
new file mode 100644
index 0000000..5604c38
--- /dev/null
+++ b/bluetooth/audio/2.1/types.hal
@@ -0,0 +1,62 @@
+/*
+ * Copyright 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.
+ */
+
+package android.hardware.bluetooth.audio@2.1;
+
+import @2.0::PcmParameters;
+import @2.0::SessionType;
+import @2.0::SampleRate;
+import @2.0::ChannelMode;
+import @2.0::BitsPerSample;
+import @2.0::CodecConfiguration;
+import @2.0::CodecCapabilities;
+
+enum SessionType : @2.0::SessionType {
+    /** Used when encoded by Bluetooth Stack and streaming to LE Audio device */
+    LE_AUDIO_SOFTWARE_ENCODING_DATAPATH,
+    /** Used when decoded by Bluetooth Stack and streaming to audio framework */
+    LE_AUDIO_SOFTWARE_DECODED_DATAPATH,
+    /** Encoding is done by HW an there is control only */
+    LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH,
+    /** Decoding is done by HW an there is control only */
+    LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH,
+};
+
+enum SampleRate : @2.0::SampleRate {
+    RATE_8000 = 0x100,
+    RATE_32000 = 0x200,
+};
+
+/** Used for Software Encoding audio feed parameters */
+struct PcmParameters {
+    SampleRate sampleRate;
+    ChannelMode channelMode;
+    BitsPerSample bitsPerSample;
+    /** Data interval for data transfer */
+    uint32_t dataIntervalUs;
+};
+
+/** Used to configure either a Hardware or Software Encoding session based on session type */
+safe_union AudioConfiguration {
+    PcmParameters pcmConfig;
+    CodecConfiguration codecConfig;
+};
+
+/** Used to specify the capabilities of the different session types */
+safe_union AudioCapabilities {
+    PcmParameters pcmCapabilities;
+    CodecCapabilities codecCapabilities;
+};
diff --git a/bluetooth/audio/2.1/vts/OWNERS b/bluetooth/audio/2.1/vts/OWNERS
new file mode 100644
index 0000000..b6c0813
--- /dev/null
+++ b/bluetooth/audio/2.1/vts/OWNERS
@@ -0,0 +1,3 @@
+include platform/system/bt:/OWNERS
+
+cheneyni@google.com
diff --git a/bluetooth/audio/2.1/vts/functional/Android.bp b/bluetooth/audio/2.1/vts/functional/Android.bp
new file mode 100644
index 0000000..6ec5537
--- /dev/null
+++ b/bluetooth/audio/2.1/vts/functional/Android.bp
@@ -0,0 +1,14 @@
+cc_test {
+    name: "VtsHalBluetoothAudioV2_1TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: ["VtsHalBluetoothAudioV2_1TargetTest.cpp"],
+    static_libs: [
+        "android.hardware.audio.common@5.0",
+        "android.hardware.bluetooth.audio@2.1",
+        "android.hardware.bluetooth.audio@2.0",
+    ],
+    shared_libs: [
+        "libfmq",
+    ],
+    test_suites: ["general-tests", "vts"],
+}
diff --git a/bluetooth/audio/2.1/vts/functional/VtsHalBluetoothAudioV2_1TargetTest.cpp b/bluetooth/audio/2.1/vts/functional/VtsHalBluetoothAudioV2_1TargetTest.cpp
new file mode 100644
index 0000000..c0ec907
--- /dev/null
+++ b/bluetooth/audio/2.1/vts/functional/VtsHalBluetoothAudioV2_1TargetTest.cpp
@@ -0,0 +1,1209 @@
+/*
+ * Copyright 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 "bluetooth_audio_hidl_hal_test"
+
+#include <VtsHalHidlTargetCallbackBase.h>
+#include <android-base/logging.h>
+#include <android/hardware/bluetooth/audio/2.0/IBluetoothAudioPort.h>
+#include <android/hardware/bluetooth/audio/2.1/IBluetoothAudioProvider.h>
+#include <android/hardware/bluetooth/audio/2.1/IBluetoothAudioProvidersFactory.h>
+#include <fmq/MessageQueue.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/ServiceManagement.h>
+#include <utils/Log.h>
+
+using ::android::sp;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::kSynchronizedReadWrite;
+using ::android::hardware::MessageQueue;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::audio::common::V5_0::SourceMetadata;
+using ::android::hardware::bluetooth::audio::V2_0::AacObjectType;
+using ::android::hardware::bluetooth::audio::V2_0::AacParameters;
+using ::android::hardware::bluetooth::audio::V2_0::AacVariableBitRate;
+using ::android::hardware::bluetooth::audio::V2_0::AptxParameters;
+using ::android::hardware::bluetooth::audio::V2_0::AudioCapabilities;
+using ::android::hardware::bluetooth::audio::V2_0::AudioConfiguration;
+using ::android::hardware::bluetooth::audio::V2_0::BitsPerSample;
+using ::android::hardware::bluetooth::audio::V2_0::ChannelMode;
+using ::android::hardware::bluetooth::audio::V2_0::CodecCapabilities;
+using ::android::hardware::bluetooth::audio::V2_0::CodecConfiguration;
+using ::android::hardware::bluetooth::audio::V2_0::CodecType;
+using ::android::hardware::bluetooth::audio::V2_0::IBluetoothAudioPort;
+using ::android::hardware::bluetooth::audio::V2_0::IBluetoothAudioProvider;
+using ::android::hardware::bluetooth::audio::V2_0::LdacChannelMode;
+using ::android::hardware::bluetooth::audio::V2_0::LdacParameters;
+using ::android::hardware::bluetooth::audio::V2_0::LdacQualityIndex;
+using ::android::hardware::bluetooth::audio::V2_0::PcmParameters;
+using ::android::hardware::bluetooth::audio::V2_0::SbcAllocMethod;
+using ::android::hardware::bluetooth::audio::V2_0::SbcBlockLength;
+using ::android::hardware::bluetooth::audio::V2_0::SbcChannelMode;
+using ::android::hardware::bluetooth::audio::V2_0::SbcNumSubbands;
+using ::android::hardware::bluetooth::audio::V2_0::SbcParameters;
+using ::android::hardware::bluetooth::audio::V2_0::SessionType;
+using ::android::hardware::bluetooth::audio::V2_1::
+    IBluetoothAudioProvidersFactory;
+using ::android::hardware::bluetooth::audio::V2_1::SampleRate;
+
+using DataMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
+using BluetoothAudioStatus =
+    ::android::hardware::bluetooth::audio::V2_0::Status;
+using CodecSpecificConfig = ::android::hardware::bluetooth::audio::V2_0::
+    CodecConfiguration::CodecSpecific;
+
+namespace {
+constexpr android::hardware::bluetooth::audio::V2_0::SampleRate
+    a2dp_sample_rates[5] = {
+        android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_UNKNOWN,
+        android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_44100,
+        android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_48000,
+        android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_88200,
+        android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_96000};
+constexpr BitsPerSample a2dp_bits_per_samples[4] = {
+    BitsPerSample::BITS_UNKNOWN, BitsPerSample::BITS_16, BitsPerSample::BITS_24,
+    BitsPerSample::BITS_32};
+constexpr ChannelMode a2dp_channel_modes[3] = {
+    ChannelMode::UNKNOWN, ChannelMode::MONO, ChannelMode::STEREO};
+constexpr CodecType a2dp_codec_types[6] = {CodecType::UNKNOWN, CodecType::SBC,
+                                           CodecType::AAC,     CodecType::APTX,
+                                           CodecType::APTX_HD, CodecType::LDAC};
+
+template <typename T>
+std::vector<T> ExtractValuesFromBitmask(T bitmasks, uint32_t bitfield,
+                                        bool supported) {
+  std::vector<T> retval;
+  if (!supported) {
+    retval.push_back(static_cast<T>(bitfield));
+  }
+  uint32_t test_bit = 0x00000001;
+  while (test_bit <= static_cast<uint32_t>(bitmasks) && test_bit <= bitfield) {
+    if ((bitfield & test_bit)) {
+      if ((!(bitmasks & test_bit) && !supported) ||
+          ((bitmasks & test_bit) && supported)) {
+        retval.push_back(static_cast<T>(test_bit));
+      }
+    }
+    if (test_bit == 0x80000000) {
+      break;
+    }
+    test_bit <<= 1;
+  }
+  return retval;
+}
+}  // namespace
+
+// The base test class for Bluetooth Audio HAL.
+class BluetoothAudioProvidersFactoryHidlTest
+    : public ::testing::TestWithParam<std::string> {
+ public:
+  virtual void SetUp() override {
+    providers_factory_ =
+        IBluetoothAudioProvidersFactory::getService(GetParam());
+    ASSERT_NE(providers_factory_, nullptr);
+  }
+
+  virtual void TearDown() override { providers_factory_ = nullptr; }
+
+  // A simple test implementation of IBluetoothAudioPort.
+  class BluetoothAudioPort : public ::testing::VtsHalHidlTargetCallbackBase<
+                                 BluetoothAudioProvidersFactoryHidlTest>,
+                             public IBluetoothAudioPort {
+    BluetoothAudioProvidersFactoryHidlTest& parent_;
+
+   public:
+    BluetoothAudioPort(BluetoothAudioProvidersFactoryHidlTest& parent)
+        : parent_(parent) {}
+    virtual ~BluetoothAudioPort() = default;
+
+    Return<void> startStream() override {
+      parent_.audio_provider_->streamStarted(BluetoothAudioStatus::SUCCESS);
+      return Void();
+    }
+
+    Return<void> suspendStream() override {
+      parent_.audio_provider_->streamSuspended(BluetoothAudioStatus::SUCCESS);
+      return Void();
+    }
+
+    Return<void> stopStream() override { return Void(); }
+
+    Return<void> getPresentationPosition(getPresentationPosition_cb _hidl_cb) {
+      _hidl_cb(BluetoothAudioStatus::SUCCESS, 0, 0, {.tvSec = 0, .tvNSec = 0});
+      return Void();
+    }
+
+    Return<void> updateMetadata(const SourceMetadata& sourceMetadata __unused) {
+      return Void();
+    }
+  };
+
+  void GetProviderCapabilitiesHelper(const SessionType& session_type) {
+    temp_provider_capabilities_.clear();
+    auto hidl_cb = [&temp_capabilities = this->temp_provider_capabilities_](
+                       const hidl_vec<AudioCapabilities>& audioCapabilities) {
+      for (auto audioCapability : audioCapabilities)
+        temp_capabilities.push_back(audioCapability);
+    };
+    auto hidl_retval =
+        providers_factory_->getProviderCapabilities(session_type, hidl_cb);
+    // HIDL calls should not be failed and callback has to be executed
+    ASSERT_TRUE(hidl_retval.isOk());
+    if (session_type == SessionType::UNKNOWN) {
+      ASSERT_TRUE(temp_provider_capabilities_.empty());
+    } else if (session_type != SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH) {
+      // All software paths are mandatory and must have exact 1 "PcmParameters"
+      ASSERT_EQ(temp_provider_capabilities_.size(), 1);
+      ASSERT_EQ(temp_provider_capabilities_[0].getDiscriminator(),
+                AudioCapabilities::hidl_discriminator::pcmCapabilities);
+    } else {
+      uint32_t codec_type_bitmask = 0x00000000;
+      // empty capability means offload is unsupported
+      for (auto audio_capability : temp_provider_capabilities_) {
+        ASSERT_EQ(audio_capability.getDiscriminator(),
+                  AudioCapabilities::hidl_discriminator::codecCapabilities);
+        const CodecCapabilities& codec_capabilities =
+            audio_capability.codecCapabilities();
+        // Every codec can present once at most
+        ASSERT_EQ(codec_type_bitmask &
+                      static_cast<uint32_t>(codec_capabilities.codecType),
+                  0);
+        switch (codec_capabilities.codecType) {
+          case CodecType::SBC:
+            ASSERT_EQ(codec_capabilities.capabilities.getDiscriminator(),
+                      CodecCapabilities::Capabilities::hidl_discriminator::
+                          sbcCapabilities);
+            break;
+          case CodecType::AAC:
+            ASSERT_EQ(codec_capabilities.capabilities.getDiscriminator(),
+                      CodecCapabilities::Capabilities::hidl_discriminator::
+                          aacCapabilities);
+            break;
+          case CodecType::APTX:
+            FALLTHROUGH_INTENDED;
+          case CodecType::APTX_HD:
+            ASSERT_EQ(codec_capabilities.capabilities.getDiscriminator(),
+                      CodecCapabilities::Capabilities::hidl_discriminator::
+                          aptxCapabilities);
+            break;
+          case CodecType::LDAC:
+            ASSERT_EQ(codec_capabilities.capabilities.getDiscriminator(),
+                      CodecCapabilities::Capabilities::hidl_discriminator::
+                          ldacCapabilities);
+            break;
+          case CodecType::UNKNOWN:
+            break;
+        }
+        codec_type_bitmask |= codec_capabilities.codecType;
+      }
+    }
+  }
+
+  void GetProviderCapabilitiesHelper_2_1(
+      const android::hardware::bluetooth::audio::V2_1::SessionType&
+          session_type) {
+    temp_provider_capabilities_2_1_.clear();
+    auto hidl_cb =
+        [&temp_capabilities = this->temp_provider_capabilities_2_1_](
+            const hidl_vec<
+                android::hardware::bluetooth::audio::V2_1::AudioCapabilities>&
+                audioCapabilities) {
+          for (auto audioCapability : audioCapabilities)
+            temp_capabilities.push_back(audioCapability);
+        };
+    auto hidl_retval =
+        providers_factory_->getProviderCapabilities_2_1(session_type, hidl_cb);
+    // HIDL calls should not be failed and callback has to be executed
+    ASSERT_TRUE(hidl_retval.isOk());
+
+    // All software paths are mandatory and must have exact 1 "PcmParameters"
+    ASSERT_EQ(temp_provider_capabilities_2_1_.size(), 1);
+    ASSERT_EQ(temp_provider_capabilities_2_1_[0].getDiscriminator(),
+              android::hardware::bluetooth::audio::V2_1::AudioCapabilities::
+                  hidl_discriminator::pcmCapabilities);
+  }
+
+  // This helps to open the specified provider and check the openProvider()
+  // has corruct return values. BUT, to keep it simple, it does not consider
+  // the capability, and please do so at the SetUp of each session's test.
+  void OpenProviderHelper(const SessionType& session_type) {
+    BluetoothAudioStatus cb_status;
+    auto hidl_cb = [&cb_status, &local_provider = this->audio_provider_](
+                       BluetoothAudioStatus status,
+                       const sp<IBluetoothAudioProvider>& provider) {
+      cb_status = status;
+      local_provider = provider;
+    };
+    auto hidl_retval = providers_factory_->openProvider(session_type, hidl_cb);
+    // HIDL calls should not be failed and callback has to be executed
+    ASSERT_TRUE(hidl_retval.isOk());
+    if (cb_status == BluetoothAudioStatus::SUCCESS) {
+      ASSERT_NE(session_type, SessionType::UNKNOWN);
+      ASSERT_NE(audio_provider_, nullptr);
+      audio_port_ = new BluetoothAudioPort(*this);
+    } else {
+      // A2DP_HARDWARE_OFFLOAD_DATAPATH is optional
+      ASSERT_TRUE(session_type == SessionType::UNKNOWN ||
+                  session_type == SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
+      ASSERT_EQ(cb_status, BluetoothAudioStatus::FAILURE);
+      ASSERT_EQ(audio_provider_, nullptr);
+    }
+  }
+
+  // This helps to open the specified provider and check the openProvider_2_1()
+  // has corruct return values. BUT, to keep it simple, it does not consider
+  // the capability, and please do so at the SetUp of each session's test.
+  void OpenProviderHelper_2_1(
+      const android::hardware::bluetooth::audio::V2_1::SessionType&
+          session_type) {
+    BluetoothAudioStatus cb_status;
+    auto hidl_cb = [&cb_status, &local_provider = this->audio_provider_2_1_](
+                       BluetoothAudioStatus status,
+                       const sp<android::hardware::bluetooth::audio::V2_1::
+                                    IBluetoothAudioProvider>& provider) {
+      cb_status = status;
+      local_provider = provider;
+    };
+    auto hidl_retval =
+        providers_factory_->openProvider_2_1(session_type, hidl_cb);
+    // HIDL calls should not be failed and callback has to be executed
+    ASSERT_TRUE(hidl_retval.isOk());
+    if (cb_status == BluetoothAudioStatus::SUCCESS) {
+      ASSERT_NE(
+          session_type,
+          android::hardware::bluetooth::audio::V2_1::SessionType::UNKNOWN);
+      ASSERT_NE(audio_provider_2_1_, nullptr);
+      audio_port_ = new BluetoothAudioPort(*this);
+    } else {
+      ASSERT_TRUE(
+          session_type ==
+          android::hardware::bluetooth::audio::V2_1::SessionType::UNKNOWN);
+      ASSERT_EQ(cb_status, BluetoothAudioStatus::FAILURE);
+      ASSERT_EQ(audio_provider_2_1_, nullptr);
+    }
+  }
+
+  bool IsPcmParametersSupported(const PcmParameters& pcm_parameters) {
+    if (temp_provider_capabilities_.size() != 1 ||
+        temp_provider_capabilities_[0].getDiscriminator() !=
+            AudioCapabilities::hidl_discriminator::pcmCapabilities) {
+      return false;
+    }
+    auto pcm_capability = temp_provider_capabilities_[0].pcmCapabilities();
+    bool is_parameter_valid =
+        (pcm_parameters.sampleRate != android::hardware::bluetooth::audio::
+                                          V2_0::SampleRate::RATE_UNKNOWN &&
+         pcm_parameters.channelMode != ChannelMode::UNKNOWN &&
+         pcm_parameters.bitsPerSample != BitsPerSample::BITS_UNKNOWN);
+    bool is_parameter_in_capability =
+        (pcm_capability.sampleRate & pcm_parameters.sampleRate &&
+         pcm_capability.channelMode & pcm_parameters.channelMode &&
+         pcm_capability.bitsPerSample & pcm_parameters.bitsPerSample);
+    return is_parameter_valid && is_parameter_in_capability;
+  }
+
+  bool IsPcmParametersSupported_2_1(
+      const android::hardware::bluetooth::audio::V2_1::PcmParameters&
+          pcm_parameters) {
+    if (temp_provider_capabilities_2_1_.size() != 1 ||
+        temp_provider_capabilities_2_1_[0].getDiscriminator() !=
+            android::hardware::bluetooth::audio::V2_1::AudioCapabilities::
+                hidl_discriminator::pcmCapabilities) {
+      return false;
+    }
+    auto pcm_capability = temp_provider_capabilities_2_1_[0].pcmCapabilities();
+    bool is_parameter_valid =
+        (pcm_parameters.sampleRate != SampleRate::RATE_UNKNOWN &&
+         pcm_parameters.channelMode != ChannelMode::UNKNOWN &&
+         pcm_parameters.bitsPerSample != BitsPerSample::BITS_UNKNOWN &&
+         pcm_parameters.dataIntervalUs != 0);
+    bool is_parameter_in_capability =
+        (pcm_capability.sampleRate & pcm_parameters.sampleRate &&
+         pcm_capability.channelMode & pcm_parameters.channelMode &&
+         pcm_capability.bitsPerSample & pcm_parameters.bitsPerSample);
+    return is_parameter_valid && is_parameter_in_capability;
+  }
+
+  sp<IBluetoothAudioProvidersFactory> providers_factory_;
+
+  // temp storage saves the specified provider capability by
+  // GetProviderCapabilitiesHelper()
+  std::vector<AudioCapabilities> temp_provider_capabilities_;
+  std::vector<android::hardware::bluetooth::audio::V2_1::AudioCapabilities>
+      temp_provider_capabilities_2_1_;
+
+  // audio_provider_ is for the Bluetooth stack to report session started/ended
+  // and handled audio stream started / suspended
+  sp<IBluetoothAudioProvider> audio_provider_;
+  sp<android::hardware::bluetooth::audio::V2_1::IBluetoothAudioProvider>
+      audio_provider_2_1_;
+
+  // audio_port_ is for the Audio HAL to send stream start/suspend/stop commands
+  // to Bluetooth stack
+  sp<IBluetoothAudioPort> audio_port_;
+
+  static constexpr SessionType session_types_[4] = {
+      SessionType::UNKNOWN, SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH,
+      SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH,
+      SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH};
+};
+
+/**
+ * Test whether we can get the FactoryService from HIDL
+ */
+TEST_P(BluetoothAudioProvidersFactoryHidlTest, GetProvidersFactoryService) {}
+
+/**
+ * Test whether we can open a provider for each provider returned by
+ * getProviderCapabilities() with non-empty capabalities
+ */
+TEST_P(BluetoothAudioProvidersFactoryHidlTest,
+       OpenProviderAndCheckCapabilitiesBySession) {
+  for (auto session_type : session_types_) {
+    GetProviderCapabilitiesHelper(session_type);
+    OpenProviderHelper(session_type);
+    // We must be able to open a provider if its getProviderCapabilities()
+    // returns non-empty list.
+    EXPECT_TRUE(temp_provider_capabilities_.empty() ||
+                audio_provider_ != nullptr);
+  }
+}
+
+/**
+ * openProvider A2DP_SOFTWARE_ENCODING_DATAPATH
+ */
+class BluetoothAudioProviderA2dpSoftwareHidlTest
+    : public BluetoothAudioProvidersFactoryHidlTest {
+ public:
+  virtual void SetUp() override {
+    BluetoothAudioProvidersFactoryHidlTest::SetUp();
+    GetProviderCapabilitiesHelper(SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH);
+    OpenProviderHelper(SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH);
+    ASSERT_NE(audio_provider_, nullptr);
+  }
+
+  virtual void TearDown() override {
+    audio_port_ = nullptr;
+    audio_provider_ = nullptr;
+    BluetoothAudioProvidersFactoryHidlTest::TearDown();
+  }
+};
+
+/**
+ * Test whether we can open a provider of type
+ */
+TEST_P(BluetoothAudioProviderA2dpSoftwareHidlTest, OpenA2dpSoftwareProvider) {}
+
+/**
+ * Test whether each provider of type
+ * SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH can be started and stopped with
+ * different PCM config
+ */
+TEST_P(BluetoothAudioProviderA2dpSoftwareHidlTest,
+       StartAndEndA2dpSoftwareSessionWithPossiblePcmConfig) {
+  bool is_codec_config_valid;
+  std::unique_ptr<DataMQ> tempDataMQ;
+  auto hidl_cb = [&is_codec_config_valid, &tempDataMQ](
+                     BluetoothAudioStatus status,
+                     const DataMQ::Descriptor& dataMQ) {
+    if (is_codec_config_valid) {
+      ASSERT_EQ(status, BluetoothAudioStatus::SUCCESS);
+      ASSERT_TRUE(dataMQ.isHandleValid());
+      tempDataMQ.reset(new DataMQ(dataMQ));
+    } else {
+      EXPECT_EQ(status, BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION);
+      EXPECT_FALSE(dataMQ.isHandleValid());
+    }
+  };
+  AudioConfiguration audio_config = {};
+  PcmParameters pcm_parameters = {};
+  for (auto sample_rate : a2dp_sample_rates) {
+    pcm_parameters.sampleRate = sample_rate;
+    for (auto bits_per_sample : a2dp_bits_per_samples) {
+      pcm_parameters.bitsPerSample = bits_per_sample;
+      for (auto channel_mode : a2dp_channel_modes) {
+        pcm_parameters.channelMode = channel_mode;
+        is_codec_config_valid = IsPcmParametersSupported(pcm_parameters);
+        audio_config.pcmConfig(pcm_parameters);
+        auto hidl_retval =
+            audio_provider_->startSession(audio_port_, audio_config, hidl_cb);
+        // HIDL calls should not be failed and callback has to be executed
+        ASSERT_TRUE(hidl_retval.isOk());
+        if (is_codec_config_valid) {
+          EXPECT_TRUE(tempDataMQ != nullptr && tempDataMQ->isValid());
+        }
+        EXPECT_TRUE(audio_provider_->endSession().isOk());
+      }  // ChannelMode
+    }    // BitsPerSampple
+  }      // SampleRate
+}
+
+/**
+ * openProvider A2DP_HARDWARE_OFFLOAD_DATAPATH
+ */
+class BluetoothAudioProviderA2dpHardwareHidlTest
+    : public BluetoothAudioProvidersFactoryHidlTest {
+ public:
+  virtual void SetUp() override {
+    BluetoothAudioProvidersFactoryHidlTest::SetUp();
+    GetProviderCapabilitiesHelper(SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
+    OpenProviderHelper(SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
+    ASSERT_TRUE(temp_provider_capabilities_.empty() ||
+                audio_provider_ != nullptr);
+  }
+
+  virtual void TearDown() override {
+    audio_port_ = nullptr;
+    audio_provider_ = nullptr;
+    BluetoothAudioProvidersFactoryHidlTest::TearDown();
+  }
+
+  bool IsOffloadSupported() { return (temp_provider_capabilities_.size() > 0); }
+
+  void GetOffloadCodecCapabilityHelper(const CodecType& codec_type) {
+    temp_codec_capabilities_ = {};
+    for (auto codec_capability : temp_provider_capabilities_) {
+      if (codec_capability.codecCapabilities().codecType != codec_type) {
+        continue;
+      }
+      temp_codec_capabilities_ = codec_capability.codecCapabilities();
+    }
+  }
+
+  std::vector<CodecSpecificConfig> GetSbcCodecSpecificSupportedList(
+      bool supported) {
+    std::vector<CodecSpecificConfig> sbc_codec_specifics;
+    GetOffloadCodecCapabilityHelper(CodecType::SBC);
+    if (temp_codec_capabilities_.codecType != CodecType::SBC) {
+      return sbc_codec_specifics;
+    }
+    // parse the capability
+    SbcParameters sbc_capability =
+        temp_codec_capabilities_.capabilities.sbcCapabilities();
+    if (sbc_capability.minBitpool > sbc_capability.maxBitpool) {
+      return sbc_codec_specifics;
+    }
+    std::vector<android::hardware::bluetooth::audio::V2_0::SampleRate>
+        sample_rates = ExtractValuesFromBitmask<
+            android::hardware::bluetooth::audio::V2_0::SampleRate>(
+            sbc_capability.sampleRate, 0xff, supported);
+    std::vector<SbcChannelMode> channel_modes =
+        ExtractValuesFromBitmask<SbcChannelMode>(sbc_capability.channelMode,
+                                                 0x0f, supported);
+    std::vector<SbcBlockLength> block_lengths =
+        ExtractValuesFromBitmask<SbcBlockLength>(sbc_capability.blockLength,
+                                                 0xf0, supported);
+    std::vector<SbcNumSubbands> num_subbandss =
+        ExtractValuesFromBitmask<SbcNumSubbands>(sbc_capability.numSubbands,
+                                                 0x0c, supported);
+    std::vector<SbcAllocMethod> alloc_methods =
+        ExtractValuesFromBitmask<SbcAllocMethod>(sbc_capability.allocMethod,
+                                                 0x03, supported);
+    std::vector<BitsPerSample> bits_per_samples =
+        ExtractValuesFromBitmask<BitsPerSample>(sbc_capability.bitsPerSample,
+                                                0x07, supported);
+    // combine those parameters into one list of
+    // CodecConfiguration::CodecSpecific
+    CodecSpecificConfig codec_specific = {};
+    SbcParameters sbc_data;
+    for (auto sample_rate : sample_rates) {
+      for (auto channel_mode : channel_modes) {
+        for (auto block_length : block_lengths) {
+          for (auto num_subbands : num_subbandss) {
+            for (auto alloc_method : alloc_methods) {
+              for (auto bits_per_sample : bits_per_samples) {
+                sbc_data = {.sampleRate = sample_rate,
+                            .channelMode = channel_mode,
+                            .blockLength = block_length,
+                            .numSubbands = num_subbands,
+                            .allocMethod = alloc_method,
+                            .bitsPerSample = bits_per_sample,
+                            .minBitpool = sbc_capability.minBitpool,
+                            .maxBitpool = sbc_capability.maxBitpool};
+                codec_specific.sbcConfig(sbc_data);
+                sbc_codec_specifics.push_back(codec_specific);
+              }
+            }
+          }
+        }
+      }
+    }
+    return sbc_codec_specifics;
+  }
+
+  std::vector<CodecSpecificConfig> GetAacCodecSpecificSupportedList(
+      bool supported) {
+    std::vector<CodecSpecificConfig> aac_codec_specifics;
+    GetOffloadCodecCapabilityHelper(CodecType::AAC);
+    if (temp_codec_capabilities_.codecType != CodecType::AAC) {
+      return aac_codec_specifics;
+    }
+    // parse the capability
+    AacParameters aac_capability =
+        temp_codec_capabilities_.capabilities.aacCapabilities();
+    std::vector<AacObjectType> object_types =
+        ExtractValuesFromBitmask<AacObjectType>(aac_capability.objectType, 0xf0,
+                                                supported);
+    std::vector<android::hardware::bluetooth::audio::V2_0::SampleRate>
+        sample_rates = ExtractValuesFromBitmask<
+            android::hardware::bluetooth::audio::V2_0::SampleRate>(
+            aac_capability.sampleRate, 0xff, supported);
+    std::vector<ChannelMode> channel_modes =
+        ExtractValuesFromBitmask<ChannelMode>(aac_capability.channelMode, 0x03,
+                                              supported);
+    std::vector<AacVariableBitRate> variable_bit_rate_enableds = {
+        AacVariableBitRate::DISABLED};
+    if (aac_capability.variableBitRateEnabled == AacVariableBitRate::ENABLED) {
+      variable_bit_rate_enableds.push_back(AacVariableBitRate::ENABLED);
+    }
+    std::vector<BitsPerSample> bits_per_samples =
+        ExtractValuesFromBitmask<BitsPerSample>(aac_capability.bitsPerSample,
+                                                0x07, supported);
+    // combine those parameters into one list of
+    // CodecConfiguration::CodecSpecific
+    CodecSpecificConfig codec_specific = {};
+    AacParameters aac_data;
+    for (auto object_type : object_types) {
+      for (auto sample_rate : sample_rates) {
+        for (auto channel_mode : channel_modes) {
+          for (auto variable_bit_rate_enabled : variable_bit_rate_enableds) {
+            for (auto bits_per_sample : bits_per_samples) {
+              aac_data = {.objectType = object_type,
+                          .sampleRate = sample_rate,
+                          .channelMode = channel_mode,
+                          .variableBitRateEnabled = variable_bit_rate_enabled,
+                          .bitsPerSample = bits_per_sample};
+              codec_specific.aacConfig(aac_data);
+              aac_codec_specifics.push_back(codec_specific);
+            }
+          }
+        }
+      }
+    }
+    return aac_codec_specifics;
+  }
+
+  std::vector<CodecSpecificConfig> GetLdacCodecSpecificSupportedList(
+      bool supported) {
+    std::vector<CodecSpecificConfig> ldac_codec_specifics;
+    GetOffloadCodecCapabilityHelper(CodecType::LDAC);
+    if (temp_codec_capabilities_.codecType != CodecType::LDAC) {
+      return ldac_codec_specifics;
+    }
+    // parse the capability
+    LdacParameters ldac_capability =
+        temp_codec_capabilities_.capabilities.ldacCapabilities();
+    std::vector<android::hardware::bluetooth::audio::V2_0::SampleRate>
+        sample_rates = ExtractValuesFromBitmask<
+            android::hardware::bluetooth::audio::V2_0::SampleRate>(
+            ldac_capability.sampleRate, 0xff, supported);
+    std::vector<LdacChannelMode> channel_modes =
+        ExtractValuesFromBitmask<LdacChannelMode>(ldac_capability.channelMode,
+                                                  0x07, supported);
+    std::vector<LdacQualityIndex> quality_indexes = {
+        LdacQualityIndex::QUALITY_HIGH, LdacQualityIndex::QUALITY_MID,
+        LdacQualityIndex::QUALITY_LOW, LdacQualityIndex::QUALITY_ABR};
+    std::vector<BitsPerSample> bits_per_samples =
+        ExtractValuesFromBitmask<BitsPerSample>(ldac_capability.bitsPerSample,
+                                                0x07, supported);
+    // combine those parameters into one list of
+    // CodecConfiguration::CodecSpecific
+    CodecSpecificConfig codec_specific = {};
+    LdacParameters ldac_data;
+    for (auto sample_rate : sample_rates) {
+      for (auto channel_mode : channel_modes) {
+        for (auto quality_index : quality_indexes) {
+          for (auto bits_per_sample : bits_per_samples) {
+            ldac_data = {.sampleRate = sample_rate,
+                         .channelMode = channel_mode,
+                         .qualityIndex = quality_index,
+                         .bitsPerSample = bits_per_sample};
+            codec_specific.ldacConfig(ldac_data);
+            ldac_codec_specifics.push_back(codec_specific);
+          }
+        }
+      }
+    }
+    return ldac_codec_specifics;
+  }
+
+  std::vector<CodecSpecificConfig> GetAptxCodecSpecificSupportedList(
+      bool is_hd, bool supported) {
+    std::vector<CodecSpecificConfig> aptx_codec_specifics;
+    GetOffloadCodecCapabilityHelper(
+        (is_hd ? CodecType::APTX_HD : CodecType::APTX));
+    if ((is_hd && temp_codec_capabilities_.codecType != CodecType::APTX_HD) ||
+        (!is_hd && temp_codec_capabilities_.codecType != CodecType::APTX)) {
+      return aptx_codec_specifics;
+    }
+    // parse the capability
+    AptxParameters aptx_capability =
+        temp_codec_capabilities_.capabilities.aptxCapabilities();
+    std::vector<android::hardware::bluetooth::audio::V2_0::SampleRate>
+        sample_rates = ExtractValuesFromBitmask<
+            android::hardware::bluetooth::audio::V2_0::SampleRate>(
+            aptx_capability.sampleRate, 0xff, supported);
+    std::vector<ChannelMode> channel_modes =
+        ExtractValuesFromBitmask<ChannelMode>(aptx_capability.channelMode, 0x03,
+                                              supported);
+    std::vector<BitsPerSample> bits_per_samples =
+        ExtractValuesFromBitmask<BitsPerSample>(aptx_capability.bitsPerSample,
+                                                0x07, supported);
+    // combine those parameters into one list of
+    // CodecConfiguration::CodecSpecific
+    CodecSpecificConfig codec_specific = {};
+    AptxParameters aptx_data;
+    for (auto sample_rate : sample_rates) {
+      for (auto channel_mode : channel_modes) {
+        for (auto bits_per_sample : bits_per_samples) {
+          aptx_data = {.sampleRate = sample_rate,
+                       .channelMode = channel_mode,
+                       .bitsPerSample = bits_per_sample};
+          codec_specific.aptxConfig(aptx_data);
+          aptx_codec_specifics.push_back(codec_specific);
+        }
+      }
+    }
+    return aptx_codec_specifics;
+  }
+
+  // temp storage saves the specified codec capability by
+  // GetOffloadCodecCapabilityHelper()
+  CodecCapabilities temp_codec_capabilities_;
+};
+
+/**
+ * Test whether we can open a provider of type
+ */
+TEST_P(BluetoothAudioProviderA2dpHardwareHidlTest, OpenA2dpHardwareProvider) {}
+
+/**
+ * Test whether each provider of type
+ * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with
+ * SBC hardware encoding config
+ */
+TEST_P(BluetoothAudioProviderA2dpHardwareHidlTest,
+       StartAndEndA2dpSbcHardwareSession) {
+  if (!IsOffloadSupported()) {
+    return;
+  }
+
+  CodecConfiguration codec_config = {};
+  codec_config.codecType = CodecType::SBC;
+  codec_config.encodedAudioBitrate = 328000;
+  codec_config.peerMtu = 1005;
+  codec_config.isScmstEnabled = false;
+  AudioConfiguration audio_config = {};
+  std::vector<CodecSpecificConfig> sbc_codec_specifics =
+      GetSbcCodecSpecificSupportedList(true);
+  auto hidl_cb = [](BluetoothAudioStatus status,
+                    const DataMQ::Descriptor& dataMQ) {
+    EXPECT_EQ(status, BluetoothAudioStatus::SUCCESS);
+    EXPECT_FALSE(dataMQ.isHandleValid());
+  };
+  for (auto codec_specific : sbc_codec_specifics) {
+    codec_config.config = codec_specific;
+    audio_config.codecConfig(codec_config);
+    auto hidl_retval =
+        audio_provider_->startSession(audio_port_, audio_config, hidl_cb);
+    // HIDL calls should not be failed and callback has to be executed
+    ASSERT_TRUE(hidl_retval.isOk());
+    EXPECT_TRUE(audio_provider_->endSession().isOk());
+  }
+}
+
+/**
+ * Test whether each provider of type
+ * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with
+ * AAC hardware encoding config
+ */
+TEST_P(BluetoothAudioProviderA2dpHardwareHidlTest,
+       StartAndEndA2dpAacHardwareSession) {
+  if (!IsOffloadSupported()) {
+    return;
+  }
+
+  CodecConfiguration codec_config = {};
+  codec_config.codecType = CodecType::AAC;
+  codec_config.encodedAudioBitrate = 320000;
+  codec_config.peerMtu = 1005;
+  codec_config.isScmstEnabled = false;
+  AudioConfiguration audio_config = {};
+  std::vector<CodecSpecificConfig> aac_codec_specifics =
+      GetAacCodecSpecificSupportedList(true);
+  auto hidl_cb = [](BluetoothAudioStatus status,
+                    const DataMQ::Descriptor& dataMQ) {
+    EXPECT_EQ(status, BluetoothAudioStatus::SUCCESS);
+    EXPECT_FALSE(dataMQ.isHandleValid());
+  };
+  for (auto codec_specific : aac_codec_specifics) {
+    codec_config.config = codec_specific;
+    audio_config.codecConfig(codec_config);
+    auto hidl_retval =
+        audio_provider_->startSession(audio_port_, audio_config, hidl_cb);
+    // HIDL calls should not be failed and callback has to be executed
+    ASSERT_TRUE(hidl_retval.isOk());
+    EXPECT_TRUE(audio_provider_->endSession().isOk());
+  }
+}
+
+/**
+ * Test whether each provider of type
+ * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with
+ * LDAC hardware encoding config
+ */
+TEST_P(BluetoothAudioProviderA2dpHardwareHidlTest,
+       StartAndEndA2dpLdacHardwareSession) {
+  if (!IsOffloadSupported()) {
+    return;
+  }
+
+  CodecConfiguration codec_config = {};
+  codec_config.codecType = CodecType::LDAC;
+  codec_config.encodedAudioBitrate = 990000;
+  codec_config.peerMtu = 1005;
+  codec_config.isScmstEnabled = false;
+  AudioConfiguration audio_config = {};
+  std::vector<CodecSpecificConfig> ldac_codec_specifics =
+      GetLdacCodecSpecificSupportedList(true);
+  auto hidl_cb = [](BluetoothAudioStatus status,
+                    const DataMQ::Descriptor& dataMQ) {
+    EXPECT_EQ(status, BluetoothAudioStatus::SUCCESS);
+    EXPECT_FALSE(dataMQ.isHandleValid());
+  };
+  for (auto codec_specific : ldac_codec_specifics) {
+    codec_config.config = codec_specific;
+    audio_config.codecConfig(codec_config);
+    auto hidl_retval =
+        audio_provider_->startSession(audio_port_, audio_config, hidl_cb);
+    // HIDL calls should not be failed and callback has to be executed
+    ASSERT_TRUE(hidl_retval.isOk());
+    EXPECT_TRUE(audio_provider_->endSession().isOk());
+  }
+}
+
+/**
+ * Test whether each provider of type
+ * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with
+ * AptX hardware encoding config
+ */
+TEST_P(BluetoothAudioProviderA2dpHardwareHidlTest,
+       StartAndEndA2dpAptxHardwareSession) {
+  if (!IsOffloadSupported()) {
+    return;
+  }
+
+  for (auto codec_type : {CodecType::APTX, CodecType::APTX_HD}) {
+    CodecConfiguration codec_config = {};
+    codec_config.codecType = codec_type;
+    codec_config.encodedAudioBitrate =
+        (codec_type == CodecType::APTX ? 352000 : 576000);
+    codec_config.peerMtu = 1005;
+    codec_config.isScmstEnabled = false;
+    AudioConfiguration audio_config = {};
+    std::vector<CodecSpecificConfig> aptx_codec_specifics =
+        GetAptxCodecSpecificSupportedList(
+            (codec_type == CodecType::APTX_HD ? true : false), true);
+    auto hidl_cb = [](BluetoothAudioStatus status,
+                      const DataMQ::Descriptor& dataMQ) {
+      EXPECT_EQ(status, BluetoothAudioStatus::SUCCESS);
+      EXPECT_FALSE(dataMQ.isHandleValid());
+    };
+    for (auto codec_specific : aptx_codec_specifics) {
+      codec_config.config = codec_specific;
+      audio_config.codecConfig(codec_config);
+      auto hidl_retval =
+          audio_provider_->startSession(audio_port_, audio_config, hidl_cb);
+      // HIDL calls should not be failed and callback has to be executed
+      ASSERT_TRUE(hidl_retval.isOk());
+      EXPECT_TRUE(audio_provider_->endSession().isOk());
+    }
+  }
+}
+
+/**
+ * Test whether each provider of type
+ * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with
+ * an invalid codec config
+ */
+TEST_P(BluetoothAudioProviderA2dpHardwareHidlTest,
+       StartAndEndA2dpHardwareSessionInvalidCodecConfig) {
+  if (!IsOffloadSupported()) {
+    return;
+  }
+  ASSERT_NE(audio_provider_, nullptr);
+
+  std::vector<CodecSpecificConfig> codec_specifics;
+  for (auto codec_type : a2dp_codec_types) {
+    switch (codec_type) {
+      case CodecType::SBC:
+        codec_specifics = GetSbcCodecSpecificSupportedList(false);
+        break;
+      case CodecType::AAC:
+        codec_specifics = GetAacCodecSpecificSupportedList(false);
+        break;
+      case CodecType::LDAC:
+        codec_specifics = GetLdacCodecSpecificSupportedList(false);
+        break;
+      case CodecType::APTX:
+        codec_specifics = GetAptxCodecSpecificSupportedList(false, false);
+        break;
+      case CodecType::APTX_HD:
+        codec_specifics = GetAptxCodecSpecificSupportedList(true, false);
+        break;
+      case CodecType::UNKNOWN:
+        codec_specifics.clear();
+        break;
+    }
+    if (codec_specifics.empty()) {
+      continue;
+    }
+
+    CodecConfiguration codec_config = {};
+    codec_config.codecType = codec_type;
+    codec_config.encodedAudioBitrate = 328000;
+    codec_config.peerMtu = 1005;
+    codec_config.isScmstEnabled = false;
+    AudioConfiguration audio_config = {};
+    auto hidl_cb = [](BluetoothAudioStatus status,
+                      const DataMQ::Descriptor& dataMQ) {
+      EXPECT_EQ(status, BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION);
+      EXPECT_FALSE(dataMQ.isHandleValid());
+    };
+    for (auto codec_specific : codec_specifics) {
+      codec_config.config = codec_specific;
+      audio_config.codecConfig(codec_config);
+      auto hidl_retval =
+          audio_provider_->startSession(audio_port_, audio_config, hidl_cb);
+      // HIDL calls should not be failed and callback has to be executed
+      ASSERT_TRUE(hidl_retval.isOk());
+      EXPECT_TRUE(audio_provider_->endSession().isOk());
+    }
+  }
+}
+
+/**
+ * openProvider HEARING_AID_SOFTWARE_ENCODING_DATAPATH
+ */
+class BluetoothAudioProviderHearingAidSoftwareHidlTest
+    : public BluetoothAudioProvidersFactoryHidlTest {
+ public:
+  virtual void SetUp() override {
+    BluetoothAudioProvidersFactoryHidlTest::SetUp();
+    GetProviderCapabilitiesHelper(
+        SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH);
+    OpenProviderHelper(SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH);
+    ASSERT_NE(audio_provider_, nullptr);
+  }
+
+  virtual void TearDown() override {
+    audio_port_ = nullptr;
+    audio_provider_ = nullptr;
+    BluetoothAudioProvidersFactoryHidlTest::TearDown();
+  }
+
+  static constexpr android::hardware::bluetooth::audio::V2_0::SampleRate
+      hearing_aid_sample_rates_[3] = {
+          android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_UNKNOWN,
+          android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_16000,
+          android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_24000};
+  static constexpr BitsPerSample hearing_aid_bits_per_samples_[3] = {
+      BitsPerSample::BITS_UNKNOWN, BitsPerSample::BITS_16,
+      BitsPerSample::BITS_24};
+  static constexpr ChannelMode hearing_aid_channel_modes_[3] = {
+      ChannelMode::UNKNOWN, ChannelMode::MONO, ChannelMode::STEREO};
+};
+
+/**
+ * Test whether each provider of type
+ * SessionType::HEARING_AID_HARDWARE_ENCODING_DATAPATH can be started and
+ * stopped with SBC hardware encoding config
+ */
+TEST_P(BluetoothAudioProviderHearingAidSoftwareHidlTest,
+       OpenHearingAidSoftwareProvider) {}
+
+/**
+ * Test whether each provider of type
+ * SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH can be started and
+ * stopped with different PCM config
+ */
+TEST_P(BluetoothAudioProviderHearingAidSoftwareHidlTest,
+       StartAndEndHearingAidSessionWithPossiblePcmConfig) {
+  bool is_codec_config_valid;
+  std::unique_ptr<DataMQ> tempDataMQ;
+  auto hidl_cb = [&is_codec_config_valid, &tempDataMQ](
+                     BluetoothAudioStatus status,
+                     const DataMQ::Descriptor& dataMQ) {
+    if (is_codec_config_valid) {
+      ASSERT_EQ(status, BluetoothAudioStatus::SUCCESS);
+      ASSERT_TRUE(dataMQ.isHandleValid());
+      tempDataMQ.reset(new DataMQ(dataMQ));
+    } else {
+      EXPECT_EQ(status, BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION);
+      EXPECT_FALSE(dataMQ.isHandleValid());
+    }
+  };
+  AudioConfiguration audio_config = {};
+  PcmParameters pcm_parameters = {};
+  for (auto sample_rate : hearing_aid_sample_rates_) {
+    pcm_parameters.sampleRate = sample_rate;
+    for (auto bits_per_sample : hearing_aid_bits_per_samples_) {
+      pcm_parameters.bitsPerSample = bits_per_sample;
+      for (auto channel_mode : hearing_aid_channel_modes_) {
+        pcm_parameters.channelMode = channel_mode;
+        is_codec_config_valid = IsPcmParametersSupported(pcm_parameters);
+        audio_config.pcmConfig(pcm_parameters);
+        auto hidl_retval =
+            audio_provider_->startSession(audio_port_, audio_config, hidl_cb);
+        // HIDL calls should not be failed and callback has to be executed
+        ASSERT_TRUE(hidl_retval.isOk());
+        if (is_codec_config_valid) {
+          EXPECT_TRUE(tempDataMQ != nullptr && tempDataMQ->isValid());
+        }
+        EXPECT_TRUE(audio_provider_->endSession().isOk());
+      }  // ChannelMode
+    }    // BitsPerSampple
+  }      // SampleRate
+}
+
+/**
+ * openProvider LE_AUDIO_SOFTWARE_ENCODING_DATAPATH
+ */
+class BluetoothAudioProviderLeAudioOutputSoftwareHidlTest
+    : public BluetoothAudioProvidersFactoryHidlTest {
+ public:
+  virtual void SetUp() override {
+    BluetoothAudioProvidersFactoryHidlTest::SetUp();
+    GetProviderCapabilitiesHelper_2_1(
+        android::hardware::bluetooth::audio::V2_1::SessionType::
+            LE_AUDIO_SOFTWARE_ENCODING_DATAPATH);
+    OpenProviderHelper_2_1(
+        android::hardware::bluetooth::audio::V2_1::SessionType::
+            LE_AUDIO_SOFTWARE_ENCODING_DATAPATH);
+    ASSERT_NE(audio_provider_2_1_, nullptr);
+  }
+
+  virtual void TearDown() override {
+    audio_port_ = nullptr;
+    audio_provider_2_1_ = nullptr;
+    BluetoothAudioProvidersFactoryHidlTest::TearDown();
+  }
+
+  static constexpr SampleRate le_audio_output_sample_rates_[3] = {
+      SampleRate::RATE_UNKNOWN, SampleRate::RATE_16000, SampleRate::RATE_24000};
+  static constexpr BitsPerSample le_audio_output_bits_per_samples_[3] = {
+      BitsPerSample::BITS_UNKNOWN, BitsPerSample::BITS_16,
+      BitsPerSample::BITS_24};
+  static constexpr ChannelMode le_audio_output_channel_modes_[3] = {
+      ChannelMode::UNKNOWN, ChannelMode::MONO, ChannelMode::STEREO};
+  static constexpr uint32_t le_audio_output_data_interval_us_[2] = {
+      0 /* Invalid */, 10000 /* Valid 10ms */};
+};
+
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH can be started and
+ * stopped
+ */
+TEST_P(BluetoothAudioProviderLeAudioOutputSoftwareHidlTest,
+       OpenLeAudioOutputSoftwareProvider) {}
+
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH can be started and
+ * stopped with different PCM config
+ */
+TEST_P(BluetoothAudioProviderLeAudioOutputSoftwareHidlTest,
+       StartAndEndLeAudioOutputSessionWithPossiblePcmConfig) {
+  bool is_codec_config_valid;
+  std::unique_ptr<DataMQ> tempDataMQ;
+  auto hidl_cb = [&is_codec_config_valid, &tempDataMQ](
+                     BluetoothAudioStatus status,
+                     const DataMQ::Descriptor& dataMQ) {
+    if (is_codec_config_valid) {
+      ASSERT_EQ(status, BluetoothAudioStatus::SUCCESS);
+      ASSERT_TRUE(dataMQ.isHandleValid());
+      tempDataMQ.reset(new DataMQ(dataMQ));
+    } else {
+      EXPECT_EQ(status, BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION);
+      EXPECT_FALSE(dataMQ.isHandleValid());
+    }
+  };
+  android::hardware::bluetooth::audio::V2_1::AudioConfiguration audio_config =
+      {};
+  android::hardware::bluetooth::audio::V2_1::PcmParameters pcm_parameters = {};
+  for (auto sample_rate : le_audio_output_sample_rates_) {
+    pcm_parameters.sampleRate = sample_rate;
+    for (auto bits_per_sample : le_audio_output_bits_per_samples_) {
+      pcm_parameters.bitsPerSample = bits_per_sample;
+      for (auto channel_mode : le_audio_output_channel_modes_) {
+        pcm_parameters.channelMode = channel_mode;
+        for (auto data_interval_us : le_audio_output_data_interval_us_) {
+          pcm_parameters.dataIntervalUs = data_interval_us;
+          is_codec_config_valid = IsPcmParametersSupported_2_1(pcm_parameters);
+          audio_config.pcmConfig(pcm_parameters);
+          auto hidl_retval = audio_provider_2_1_->startSession_2_1(
+              audio_port_, audio_config, hidl_cb);
+          // HIDL calls should not be failed and callback has to be executed
+          ASSERT_TRUE(hidl_retval.isOk());
+          if (is_codec_config_valid) {
+            EXPECT_TRUE(tempDataMQ != nullptr && tempDataMQ->isValid());
+          }
+          EXPECT_TRUE(audio_provider_2_1_->endSession().isOk());
+        }  // uint32_t (data interval in microseconds)
+      }    // ChannelMode
+    }      // BitsPerSampple
+  }        // SampleRate
+}
+
+/**
+ * openProvider LE_AUDIO_SOFTWARE_DECODED_DATAPATH
+ */
+class BluetoothAudioProviderLeAudioInputSoftwareHidlTest
+    : public BluetoothAudioProvidersFactoryHidlTest {
+ public:
+  virtual void SetUp() override {
+    BluetoothAudioProvidersFactoryHidlTest::SetUp();
+    GetProviderCapabilitiesHelper_2_1(
+        android::hardware::bluetooth::audio::V2_1::SessionType::
+            LE_AUDIO_SOFTWARE_DECODED_DATAPATH);
+    OpenProviderHelper_2_1(android::hardware::bluetooth::audio::V2_1::
+                               SessionType::LE_AUDIO_SOFTWARE_DECODED_DATAPATH);
+    ASSERT_NE(audio_provider_2_1_, nullptr);
+  }
+
+  virtual void TearDown() override {
+    audio_port_ = nullptr;
+    audio_provider_2_1_ = nullptr;
+    BluetoothAudioProvidersFactoryHidlTest::TearDown();
+  }
+
+  static constexpr SampleRate le_audio_output_sample_rates_[3] = {
+      SampleRate::RATE_UNKNOWN, SampleRate::RATE_16000, SampleRate::RATE_24000};
+  static constexpr BitsPerSample le_audio_output_bits_per_samples_[3] = {
+      BitsPerSample::BITS_UNKNOWN, BitsPerSample::BITS_16,
+      BitsPerSample::BITS_24};
+  static constexpr ChannelMode le_audio_output_channel_modes_[3] = {
+      ChannelMode::UNKNOWN, ChannelMode::MONO, ChannelMode::STEREO};
+  static constexpr uint32_t le_audio_output_data_interval_us_[2] = {
+      0 /* Invalid */, 10000 /* Valid 10ms */};
+};
+
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_SOFTWARE_DECODED_DATAPATH can be started and
+ * stopped
+ */
+TEST_P(BluetoothAudioProviderLeAudioInputSoftwareHidlTest,
+       OpenLeAudioInputSoftwareProvider) {}
+
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_SOFTWARE_DECODED_DATAPATH can be started and
+ * stopped with different PCM config
+ */
+TEST_P(BluetoothAudioProviderLeAudioInputSoftwareHidlTest,
+       StartAndEndLeAudioInputSessionWithPossiblePcmConfig) {
+  bool is_codec_config_valid;
+  std::unique_ptr<DataMQ> tempDataMQ;
+  auto hidl_cb = [&is_codec_config_valid, &tempDataMQ](
+                     BluetoothAudioStatus status,
+                     const DataMQ::Descriptor& dataMQ) {
+    if (is_codec_config_valid) {
+      ASSERT_EQ(status, BluetoothAudioStatus::SUCCESS);
+      ASSERT_TRUE(dataMQ.isHandleValid());
+      tempDataMQ.reset(new DataMQ(dataMQ));
+    } else {
+      EXPECT_EQ(status, BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION);
+      EXPECT_FALSE(dataMQ.isHandleValid());
+    }
+  };
+  android::hardware::bluetooth::audio::V2_1::AudioConfiguration audio_config =
+      {};
+  android::hardware::bluetooth::audio::V2_1::PcmParameters pcm_parameters = {};
+  for (auto sample_rate : le_audio_output_sample_rates_) {
+    pcm_parameters.sampleRate = sample_rate;
+    for (auto bits_per_sample : le_audio_output_bits_per_samples_) {
+      pcm_parameters.bitsPerSample = bits_per_sample;
+      for (auto channel_mode : le_audio_output_channel_modes_) {
+        pcm_parameters.channelMode = channel_mode;
+        for (auto data_interval_us : le_audio_output_data_interval_us_) {
+          pcm_parameters.dataIntervalUs = data_interval_us;
+          is_codec_config_valid = IsPcmParametersSupported_2_1(pcm_parameters);
+          audio_config.pcmConfig(pcm_parameters);
+          auto hidl_retval = audio_provider_2_1_->startSession_2_1(
+              audio_port_, audio_config, hidl_cb);
+          // HIDL calls should not be failed and callback has to be executed
+          ASSERT_TRUE(hidl_retval.isOk());
+          if (is_codec_config_valid) {
+            EXPECT_TRUE(tempDataMQ != nullptr && tempDataMQ->isValid());
+          } else {
+            EXPECT_TRUE(tempDataMQ == nullptr);
+          }
+          EXPECT_TRUE(audio_provider_2_1_->endSession().isOk());
+        }  // uint32_t (data interval in microseconds)
+      }    // ChannelMode
+    }      // BitsPerSampple
+  }        // SampleRate
+}
+
+static const std::vector<std::string> kAudioInstances =
+    android::hardware::getAllHalInstanceNames(
+        IBluetoothAudioProvidersFactory::descriptor);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
+    BluetoothAudioProvidersFactoryHidlTest);
+INSTANTIATE_TEST_SUITE_P(PerInstance, BluetoothAudioProvidersFactoryHidlTest,
+                         testing::ValuesIn(kAudioInstances),
+                         android::hardware::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
+    BluetoothAudioProviderA2dpSoftwareHidlTest);
+INSTANTIATE_TEST_SUITE_P(PerInstance,
+                         BluetoothAudioProviderA2dpSoftwareHidlTest,
+                         testing::ValuesIn(kAudioInstances),
+                         android::hardware::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
+    BluetoothAudioProviderA2dpHardwareHidlTest);
+INSTANTIATE_TEST_SUITE_P(PerInstance,
+                         BluetoothAudioProviderA2dpHardwareHidlTest,
+                         testing::ValuesIn(kAudioInstances),
+                         android::hardware::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
+    BluetoothAudioProviderHearingAidSoftwareHidlTest);
+INSTANTIATE_TEST_SUITE_P(PerInstance,
+                         BluetoothAudioProviderHearingAidSoftwareHidlTest,
+                         testing::ValuesIn(kAudioInstances),
+                         android::hardware::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
+    BluetoothAudioProviderLeAudioOutputSoftwareHidlTest);
+INSTANTIATE_TEST_SUITE_P(PerInstance,
+                         BluetoothAudioProviderLeAudioOutputSoftwareHidlTest,
+                         testing::ValuesIn(kAudioInstances),
+                         android::hardware::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
+    BluetoothAudioProviderLeAudioInputSoftwareHidlTest);
+INSTANTIATE_TEST_SUITE_P(PerInstance,
+                         BluetoothAudioProviderLeAudioInputSoftwareHidlTest,
+                         testing::ValuesIn(kAudioInstances),
+                         android::hardware::PrintInstanceNameToString);
diff --git a/camera/provider/2.4/default/Android.bp b/camera/provider/2.4/default/Android.bp
index 627ddf4..bbb21c7 100644
--- a/camera/provider/2.4/default/Android.bp
+++ b/camera/provider/2.4/default/Android.bp
@@ -76,7 +76,7 @@
     header_libs: [
         "camera.device@3.4-external-impl_headers",
         "camera.device@3.5-external-impl_headers",
-        "camera.device@3.6-external-impl_headers"
+        "camera.device@3.6-external-impl_headers",
     ],
     export_include_dirs: ["."],
 }
@@ -150,6 +150,7 @@
         "android.hidl.memory@1.0",
         "libbinder",
         "libcamera_metadata",
+        "libcutils",
         "libhardware",
         "libhidlbase",
         "liblog",
diff --git a/camera/provider/2.4/default/service.cpp b/camera/provider/2.4/default/service.cpp
index 4475f7d..84f4839 100644
--- a/camera/provider/2.4/default/service.cpp
+++ b/camera/provider/2.4/default/service.cpp
@@ -22,6 +22,8 @@
 
 #include <android/hardware/camera/provider/2.4/ICameraProvider.h>
 #include <binder/ProcessState.h>
+#include <cutils/memory.h>
+#include <cutils/properties.h>
 #include <hidl/LegacySupport.h>
 
 using android::status_t;
@@ -41,6 +43,12 @@
     // The camera HAL may communicate to other vendor components via
     // /dev/vndbinder
     android::ProcessState::initWithDriver("/dev/vndbinder");
+
+    // b/166675194
+    if (property_get_bool("ro.vendor.camera.provider24.disable_mem_init", false)) {
+        process_disable_memory_mitigations();
+    }
+
     status_t status;
     if (kLazyService) {
         status = defaultLazyPassthroughServiceImplementation<ICameraProvider>("legacy/0",
diff --git a/common/fmq/aidl/Android.bp b/common/fmq/aidl/Android.bp
new file mode 100644
index 0000000..004adab
--- /dev/null
+++ b/common/fmq/aidl/Android.bp
@@ -0,0 +1,21 @@
+aidl_interface {
+    name: "android.hardware.common.fmq",
+    host_supported: true,
+    vendor_available: true,
+    vndk: {
+        enabled: true,
+        support_system_process: true,
+    },
+    srcs: [
+        "android/hardware/common/fmq/*.aidl",
+    ],
+    stability: "vintf",
+    backend: {
+        java: {
+            enabled: false,
+        },
+        cpp: {
+            enabled: false,
+        },
+    },
+}
diff --git a/common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/GrantorDescriptor.aidl b/common/fmq/aidl/aidl_api/android.hardware.common.fmq/current/android/hardware/common/fmq/GrantorDescriptor.aidl
similarity index 96%
rename from common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/GrantorDescriptor.aidl
rename to common/fmq/aidl/aidl_api/android.hardware.common.fmq/current/android/hardware/common/fmq/GrantorDescriptor.aidl
index 07bceb0..7ac1930 100644
--- a/common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/GrantorDescriptor.aidl
+++ b/common/fmq/aidl/aidl_api/android.hardware.common.fmq/current/android/hardware/common/fmq/GrantorDescriptor.aidl
@@ -15,7 +15,7 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.common;
+package android.hardware.common.fmq;
 @VintfStability
 parcelable GrantorDescriptor {
   int offset;
diff --git a/common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/MQDescriptor.aidl b/common/fmq/aidl/aidl_api/android.hardware.common.fmq/current/android/hardware/common/fmq/MQDescriptor.aidl
similarity index 91%
rename from common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/MQDescriptor.aidl
rename to common/fmq/aidl/aidl_api/android.hardware.common.fmq/current/android/hardware/common/fmq/MQDescriptor.aidl
index c9fe1d7..2607369 100644
--- a/common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/MQDescriptor.aidl
+++ b/common/fmq/aidl/aidl_api/android.hardware.common.fmq/current/android/hardware/common/fmq/MQDescriptor.aidl
@@ -15,10 +15,10 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.common;
+package android.hardware.common.fmq;
 @VintfStability
 parcelable MQDescriptor {
-  android.hardware.common.GrantorDescriptor[] grantors;
+  android.hardware.common.fmq.GrantorDescriptor[] grantors;
   ParcelFileDescriptor fileDescriptor;
   int quantum;
   int flags;
diff --git a/common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/SynchronizedReadWrite.aidl b/common/fmq/aidl/aidl_api/android.hardware.common.fmq/current/android/hardware/common/fmq/SynchronizedReadWrite.aidl
similarity index 96%
rename from common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/SynchronizedReadWrite.aidl
rename to common/fmq/aidl/aidl_api/android.hardware.common.fmq/current/android/hardware/common/fmq/SynchronizedReadWrite.aidl
index aec3d6d..2142bdb 100644
--- a/common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/SynchronizedReadWrite.aidl
+++ b/common/fmq/aidl/aidl_api/android.hardware.common.fmq/current/android/hardware/common/fmq/SynchronizedReadWrite.aidl
@@ -15,7 +15,7 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.common;
+package android.hardware.common.fmq;
 @VintfStability
 enum SynchronizedReadWrite {
   EMPTY = 0,
diff --git a/common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/UnsynchronizedWrite.aidl b/common/fmq/aidl/aidl_api/android.hardware.common.fmq/current/android/hardware/common/fmq/UnsynchronizedWrite.aidl
similarity index 96%
rename from common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/UnsynchronizedWrite.aidl
rename to common/fmq/aidl/aidl_api/android.hardware.common.fmq/current/android/hardware/common/fmq/UnsynchronizedWrite.aidl
index e390d20..1220674 100644
--- a/common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/UnsynchronizedWrite.aidl
+++ b/common/fmq/aidl/aidl_api/android.hardware.common.fmq/current/android/hardware/common/fmq/UnsynchronizedWrite.aidl
@@ -15,7 +15,7 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.common;
+package android.hardware.common.fmq;
 @VintfStability
 enum UnsynchronizedWrite {
   EMPTY = 0,
diff --git a/common/aidl/android/hardware/common/GrantorDescriptor.aidl b/common/fmq/aidl/android/hardware/common/fmq/GrantorDescriptor.aidl
similarity index 95%
rename from common/aidl/android/hardware/common/GrantorDescriptor.aidl
rename to common/fmq/aidl/android/hardware/common/fmq/GrantorDescriptor.aidl
index 3552e9e..ca69d94 100644
--- a/common/aidl/android/hardware/common/GrantorDescriptor.aidl
+++ b/common/fmq/aidl/android/hardware/common/fmq/GrantorDescriptor.aidl
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.hardware.common;
+package android.hardware.common.fmq;
 
 /*
  * Included in MQDescriptor, for use with libfmq.
diff --git a/common/aidl/android/hardware/common/MQDescriptor.aidl b/common/fmq/aidl/android/hardware/common/fmq/MQDescriptor.aidl
similarity index 94%
rename from common/aidl/android/hardware/common/MQDescriptor.aidl
rename to common/fmq/aidl/android/hardware/common/fmq/MQDescriptor.aidl
index 7e89b15..82917d6 100644
--- a/common/aidl/android/hardware/common/MQDescriptor.aidl
+++ b/common/fmq/aidl/android/hardware/common/fmq/MQDescriptor.aidl
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package android.hardware.common;
+package android.hardware.common.fmq;
 
-import android.hardware.common.GrantorDescriptor;
+import android.hardware.common.fmq.GrantorDescriptor;
 
 /*
  * For use with libfmq. This is created from an instance of AidlMessageQueue,
diff --git a/common/aidl/android/hardware/common/SynchronizedReadWrite.aidl b/common/fmq/aidl/android/hardware/common/fmq/SynchronizedReadWrite.aidl
similarity index 95%
rename from common/aidl/android/hardware/common/SynchronizedReadWrite.aidl
rename to common/fmq/aidl/android/hardware/common/fmq/SynchronizedReadWrite.aidl
index ef93bf2..8c33442 100644
--- a/common/aidl/android/hardware/common/SynchronizedReadWrite.aidl
+++ b/common/fmq/aidl/android/hardware/common/fmq/SynchronizedReadWrite.aidl
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.hardware.common;
+package android.hardware.common.fmq;
 
 /*
  * For use with android.hardware.common.MQDescriptor to specify which type of
diff --git a/common/aidl/android/hardware/common/UnsynchronizedWrite.aidl b/common/fmq/aidl/android/hardware/common/fmq/UnsynchronizedWrite.aidl
similarity index 95%
rename from common/aidl/android/hardware/common/UnsynchronizedWrite.aidl
rename to common/fmq/aidl/android/hardware/common/fmq/UnsynchronizedWrite.aidl
index aa27c8d..24c4cce 100644
--- a/common/aidl/android/hardware/common/UnsynchronizedWrite.aidl
+++ b/common/fmq/aidl/android/hardware/common/fmq/UnsynchronizedWrite.aidl
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.hardware.common;
+package android.hardware.common.fmq;
 
 /*
  * For use with android.hardware.common.MQDescriptor to specify which type of
diff --git a/compatibility_matrices/Android.mk b/compatibility_matrices/Android.mk
index 96191c8..b88d40b 100644
--- a/compatibility_matrices/Android.mk
+++ b/compatibility_matrices/Android.mk
@@ -33,7 +33,7 @@
 LOCAL_SRC_FILES := compatibility_matrix.empty.xml
 else
 
-# DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE specify an absolute path
+# DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE specifies absolute paths
 LOCAL_GENERATED_SOURCES := $(DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE)
 
 # Enforce that DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE does not specify required HALs
@@ -77,7 +77,7 @@
 LOCAL_MODULE_CLASS := ETC
 LOCAL_MODULE_RELATIVE_PATH := vintf
 
-# DEVICE_PRODUCT_COMPATIBILITY_MATRIX_FILE specify an absolute path
+# DEVICE_PRODUCT_COMPATIBILITY_MATRIX_FILE specifies absolute paths
 LOCAL_GENERATED_SOURCES := $(DEVICE_PRODUCT_COMPATIBILITY_MATRIX_FILE)
 
 # Enforce that DEVICE_PRODUCT_COMPATIBILITY_MATRIX_FILE does not specify required HALs
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index bb26bd3..d1d254b 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -96,6 +96,13 @@
             <instance>default</instance>
         </interface>
     </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.biometrics.face</name>
+        <interface>
+            <name>IFace</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.biometrics.fingerprint</name>
         <version>2.1-3</version>
@@ -121,7 +128,7 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.bluetooth.audio</name>
-        <version>2.0</version>
+        <version>2.0-1</version>
         <interface>
             <name>IBluetoothAudioProvidersFactory</name>
             <instance>default</instance>
@@ -177,7 +184,7 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.contexthub</name>
-        <version>1.0-1</version>
+        <version>1.0-2</version>
         <interface>
             <name>IContexthub</name>
             <instance>default</instance>
@@ -220,6 +227,13 @@
             <instance>default</instance>
         </interface>
     </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.gnss</name>
+        <interface>
+            <name>IGnss</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
     <hal format="hidl" optional="false">
         <name>android.hardware.graphics.allocator</name>
         <!-- New, non-Go devices should use 4.0, tested in vts_treble_vintf_vendor_test -->
@@ -374,7 +388,7 @@
         </interface>
     </hal>
     <hal format="aidl" optional="true">
-        <name>android.hardware.powerstats</name>
+        <name>android.hardware.power.stats</name>
         <interface>
             <name>IPowerStats</name>
             <instance>default</instance>
@@ -540,7 +554,7 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.wifi</name>
-        <version>1.0-5</version>
+        <version>1.3-5</version>
         <interface>
             <name>IWifi</name>
             <instance>default</instance>
@@ -556,7 +570,7 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.wifi.supplicant</name>
-        <version>1.0-4</version>
+        <version>1.2-4</version>
         <interface>
             <name>ISupplicant</name>
             <instance>default</instance>
diff --git a/compatibility_matrices/exclude/fcm_exclude.cpp b/compatibility_matrices/exclude/fcm_exclude.cpp
index 20b7281..29dc130 100644
--- a/compatibility_matrices/exclude/fcm_exclude.cpp
+++ b/compatibility_matrices/exclude/fcm_exclude.cpp
@@ -53,12 +53,14 @@
             // AIDL
             "android.hardware.biometrics.common",
             "android.hardware.common",
+            "android.hardware.common.fmq",
             "android.hardware.graphics.common",
             "android.hardware.keymaster",
 
             // Fastboot HAL is only used by recovery. Recovery is owned by OEM. Framework
             // does not depend on this HAL, hence it is not declared in any manifests or matrices.
             "android.hardware.fastboot@1.0",
+            "android.hardware.fastboot@1.1",
     };
 
     auto package_has_prefix = [&](const std::string& prefix) {
diff --git a/contexthub/1.0/vts/functional/OWNERS b/contexthub/1.0/vts/functional/OWNERS
index 161b2f0..1a33a9e 100644
--- a/contexthub/1.0/vts/functional/OWNERS
+++ b/contexthub/1.0/vts/functional/OWNERS
@@ -5,4 +5,3 @@
 
 #VTS team
 dshi@google.com
-trong@google.com
diff --git a/contexthub/1.1/default/Android.bp b/contexthub/1.1/default/Android.bp
index 86858c0..5c9ec4e 100644
--- a/contexthub/1.1/default/Android.bp
+++ b/contexthub/1.1/default/Android.bp
@@ -38,5 +38,8 @@
         "liblog",
         "libutils",
     ],
+    header_libs: [
+        "android.hardware.contexthub@1.X-common-impl",
+    ],
     vintf_fragments: ["android.hardware.contexthub@1.1.xml"],
 }
diff --git a/contexthub/1.1/default/Contexthub.cpp b/contexthub/1.1/default/Contexthub.cpp
index 19cc262..e7fde84 100644
--- a/contexthub/1.1/default/Contexthub.cpp
+++ b/contexthub/1.1/default/Contexthub.cpp
@@ -23,81 +23,6 @@
 namespace V1_1 {
 namespace implementation {
 
-using ::android::hardware::contexthub::V1_0::ContextHub;
-using ::android::hardware::contexthub::V1_0::HubAppInfo;
-using ::android::hardware::contexthub::V1_0::Result;
-
-namespace {
-
-constexpr uint32_t kMockHubId = 0;
-
-}  // anonymous namespace
-
-Return<void> Contexthub::getHubs(getHubs_cb _hidl_cb) {
-    ContextHub hub = {};
-    hub.name = "Mock Context Hub";
-    hub.vendor = "AOSP";
-    hub.toolchain = "n/a";
-    hub.platformVersion = 1;
-    hub.toolchainVersion = 1;
-    hub.hubId = kMockHubId;
-    hub.peakMips = 1;
-    hub.peakPowerDrawMw = 1;
-    hub.maxSupportedMsgLen = 4096;
-    hub.chrePlatformId = UINT64_C(0x476f6f6754000000);
-    hub.chreApiMajorVersion = 1;
-    hub.chreApiMinorVersion = 4;
-
-    // Report a single mock hub
-    std::vector<ContextHub> hubs;
-    hubs.push_back(hub);
-
-    _hidl_cb(hubs);
-    return Void();
-}
-
-Return<Result> Contexthub::registerCallback(uint32_t hubId, const sp<IContexthubCallback>& cb) {
-    if (hubId == kMockHubId) {
-        mCallback = cb;
-        return Result::OK;
-    }
-    return Result::BAD_PARAMS;
-}
-
-// We don't expose any nanoapps, therefore all nanoapp-related API calls return with BAD_PARAMS
-Return<Result> Contexthub::sendMessageToHub(uint32_t /*hubId*/, const ContextHubMsg& /*msg*/) {
-    return Result::BAD_PARAMS;
-}
-
-Return<Result> Contexthub::loadNanoApp(uint32_t /*hubId*/, const NanoAppBinary& /*appBinary*/,
-                                       uint32_t /*transactionId*/) {
-    return Result::BAD_PARAMS;
-}
-
-Return<Result> Contexthub::unloadNanoApp(uint32_t /*hubId*/, uint64_t /*appId*/,
-                                         uint32_t /*transactionId*/) {
-    return Result::BAD_PARAMS;
-}
-
-Return<Result> Contexthub::enableNanoApp(uint32_t /*hubId*/, uint64_t /*appId*/,
-                                         uint32_t /*transactionId*/) {
-    return Result::BAD_PARAMS;
-}
-
-Return<Result> Contexthub::disableNanoApp(uint32_t /*hubId*/, uint64_t /*appId*/,
-                                          uint32_t /*transactionId*/) {
-    return Result::BAD_PARAMS;
-}
-
-Return<Result> Contexthub::queryApps(uint32_t hubId) {
-    if (hubId == kMockHubId && mCallback != nullptr) {
-        std::vector<HubAppInfo> nanoapps;
-        mCallback->handleAppsInfo(nanoapps);
-        return Result::OK;
-    }
-    return Result::BAD_PARAMS;
-}
-
 Return<void> Contexthub::onSettingChanged(Setting /*setting*/, SettingValue /*newValue*/) {
     return Void();
 }
diff --git a/contexthub/1.1/default/Contexthub.h b/contexthub/1.1/default/Contexthub.h
index 0da61d1..1468fcf 100644
--- a/contexthub/1.1/default/Contexthub.h
+++ b/contexthub/1.1/default/Contexthub.h
@@ -15,6 +15,8 @@
  */
 #pragma once
 
+#include "ContextHub.h"
+
 #include <android/hardware/contexthub/1.1/IContexthub.h>
 
 namespace android {
@@ -23,30 +25,11 @@
 namespace V1_1 {
 namespace implementation {
 
-class Contexthub : public V1_1::IContexthub {
-    using ContextHubMsg = ::android::hardware::contexthub::V1_0::ContextHubMsg;
-    using IContexthubCallback = ::android::hardware::contexthub::V1_0::IContexthubCallback;
-    using NanoAppBinary = ::android::hardware::contexthub::V1_0::NanoAppBinary;
-    using Result = ::android::hardware::contexthub::V1_0::Result;
-
+class Contexthub
+    : public ::android::hardware::contexthub::V1_X::implementation::ContextHub<IContexthub> {
   public:
-    // Methods from V1_0::IContexthub
-    Return<void> getHubs(getHubs_cb _hidl_cb) override;
-    Return<Result> registerCallback(uint32_t hubId,
-                                    const ::android::sp<IContexthubCallback>& cb) override;
-    Return<Result> sendMessageToHub(uint32_t hubId, const ContextHubMsg& msg) override;
-    Return<Result> loadNanoApp(uint32_t hubId, const NanoAppBinary& appBinary,
-                               uint32_t transactionId) override;
-    Return<Result> unloadNanoApp(uint32_t hubId, uint64_t appId, uint32_t transactionId) override;
-    Return<Result> enableNanoApp(uint32_t hubId, uint64_t appId, uint32_t transactionId) override;
-    Return<Result> disableNanoApp(uint32_t hubId, uint64_t appId, uint32_t transactionId) override;
-    Return<Result> queryApps(uint32_t hubId) override;
-
     // Methods from V1_1::IContexthub
     Return<void> onSettingChanged(Setting setting, SettingValue newValue) override;
-
-  private:
-    sp<IContexthubCallback> mCallback;
 };
 
 }  // namespace implementation
diff --git a/contexthub/1.1/vts/functional/OWNERS b/contexthub/1.1/vts/functional/OWNERS
index 161b2f0..1a33a9e 100644
--- a/contexthub/1.1/vts/functional/OWNERS
+++ b/contexthub/1.1/vts/functional/OWNERS
@@ -5,4 +5,3 @@
 
 #VTS team
 dshi@google.com
-trong@google.com
diff --git a/contexthub/1.2/Android.bp b/contexthub/1.2/Android.bp
new file mode 100644
index 0000000..e819482
--- /dev/null
+++ b/contexthub/1.2/Android.bp
@@ -0,0 +1,16 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.contexthub@1.2",
+    root: "android.hardware",
+    srcs: [
+        "types.hal",
+        "IContexthub.hal",
+    ],
+    interfaces: [
+        "android.hardware.contexthub@1.0",
+        "android.hardware.contexthub@1.1",
+        "android.hidl.base@1.0",
+    ],
+    gen_java: true,
+}
diff --git a/contexthub/1.2/IContexthub.hal b/contexthub/1.2/IContexthub.hal
new file mode 100644
index 0000000..819fc1d
--- /dev/null
+++ b/contexthub/1.2/IContexthub.hal
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+package android.hardware.contexthub@1.2;
+
+import @1.1::IContexthub;
+import @1.1::SettingValue;
+
+interface IContexthub extends @1.1::IContexthub {
+    /**
+     * Notification sent by the framework to indicate that the user
+     * has changed a setting.
+     *
+     * @param setting User setting that has been modified.
+     * @param newValue The update value of the user setting.
+     */
+    onSettingChanged_1_2(Setting setting, @1.1::SettingValue newValue);
+};
diff --git a/contexthub/1.2/default/Android.bp b/contexthub/1.2/default/Android.bp
new file mode 100644
index 0000000..49b54fc
--- /dev/null
+++ b/contexthub/1.2/default/Android.bp
@@ -0,0 +1,46 @@
+/*
+ * 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.contexthub@1.2-service.mock",
+    defaults: ["hidl_defaults"],
+    vendor: true,
+    relative_install_path: "hw",
+    init_rc: ["android.hardware.contexthub@1.2-service.rc"],
+    srcs: [
+        "Contexthub.cpp",
+        "service.cpp",
+    ],
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+    shared_libs: [
+        "android.hardware.contexthub@1.0",
+        "android.hardware.contexthub@1.1",
+        "android.hardware.contexthub@1.2",
+        "libbase",
+        "libcutils",
+        "libhardware",
+        "libhidlbase",
+        "liblog",
+        "libutils",
+    ],
+    header_libs: [
+        "android.hardware.contexthub@1.X-common-impl",
+    ],
+    vintf_fragments: ["android.hardware.contexthub@1.2.xml"],
+}
diff --git a/contexthub/1.2/default/Contexthub.cpp b/contexthub/1.2/default/Contexthub.cpp
new file mode 100644
index 0000000..d7ac7bf
--- /dev/null
+++ b/contexthub/1.2/default/Contexthub.cpp
@@ -0,0 +1,38 @@
+/*
+ * 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 "Contexthub.h"
+
+#include <vector>
+
+namespace android {
+namespace hardware {
+namespace contexthub {
+namespace V1_2 {
+namespace implementation {
+
+Return<void> Contexthub::onSettingChanged(SettingV1_1 /*setting*/, SettingValue /*newValue*/) {
+    return Void();
+}
+
+Return<void> Contexthub::onSettingChanged_1_2(Setting /*setting*/, SettingValue /*newValue*/) {
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace V1_2
+}  // namespace contexthub
+}  // namespace hardware
+}  // namespace android
diff --git a/contexthub/1.2/default/Contexthub.h b/contexthub/1.2/default/Contexthub.h
new file mode 100644
index 0000000..d2f8d69
--- /dev/null
+++ b/contexthub/1.2/default/Contexthub.h
@@ -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.
+ */
+#pragma once
+
+#include "ContextHub.h"
+
+#include <android/hardware/contexthub/1.2/IContexthub.h>
+
+namespace android {
+namespace hardware {
+namespace contexthub {
+namespace V1_2 {
+namespace implementation {
+
+class Contexthub
+    : public ::android::hardware::contexthub::V1_X::implementation::ContextHub<IContexthub> {
+    using SettingValue = ::android::hardware::contexthub::V1_1::SettingValue;
+    using SettingV1_1 = ::android::hardware::contexthub::V1_1::Setting;
+
+  public:
+    // Methods from V1_1::IContexthub
+    Return<void> onSettingChanged(SettingV1_1 setting, SettingValue newValue) override;
+
+    // Methods from V1_2::IContexthub
+    Return<void> onSettingChanged_1_2(Setting setting, SettingValue newValue) override;
+};
+
+}  // namespace implementation
+}  // namespace V1_2
+}  // namespace contexthub
+}  // namespace hardware
+}  // namespace android
diff --git a/contexthub/1.2/default/OWNERS b/contexthub/1.2/default/OWNERS
new file mode 100644
index 0000000..90c2330
--- /dev/null
+++ b/contexthub/1.2/default/OWNERS
@@ -0,0 +1,3 @@
+arthuri@google.com
+bduddie@google.com
+stange@google.com
diff --git a/contexthub/1.2/default/android.hardware.contexthub@1.2-service.rc b/contexthub/1.2/default/android.hardware.contexthub@1.2-service.rc
new file mode 100644
index 0000000..936222a
--- /dev/null
+++ b/contexthub/1.2/default/android.hardware.contexthub@1.2-service.rc
@@ -0,0 +1,7 @@
+service vendor.contexthub-hal-1.2-mock /vendor/bin/hw/android.hardware.contexthub@1.2-service.mock
+    interface android.hardware.contexthub@1.0::IContexthub default
+    interface android.hardware.contexthub@1.1::IContexthub default
+    interface android.hardware.contexthub@1.2::IContexthub default
+    class hal
+    user context_hub
+    group context_hub
diff --git a/contexthub/1.2/default/android.hardware.contexthub@1.2.xml b/contexthub/1.2/default/android.hardware.contexthub@1.2.xml
new file mode 100644
index 0000000..ec6c684
--- /dev/null
+++ b/contexthub/1.2/default/android.hardware.contexthub@1.2.xml
@@ -0,0 +1,11 @@
+<manifest version="1.0" type="device">
+    <hal format="hidl">
+        <name>android.hardware.contexthub</name>
+        <transport>hwbinder</transport>
+        <version>1.2</version>
+        <interface>
+            <name>IContexthub</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+</manifest>
diff --git a/contexthub/1.2/default/service.cpp b/contexthub/1.2/default/service.cpp
new file mode 100644
index 0000000..41cb753
--- /dev/null
+++ b/contexthub/1.2/default/service.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.
+ */
+
+#define LOG_TAG "android.hardware.contexthub@1.2-service"
+
+#include <android/hardware/contexthub/1.2/IContexthub.h>
+#include <hidl/HidlTransportSupport.h>
+#include <log/log.h>
+#include <utils/StrongPointer.h>
+#include "Contexthub.h"
+
+using ::android::hardware::configureRpcThreadpool;
+using ::android::hardware::joinRpcThreadpool;
+using ::android::hardware::contexthub::V1_2::IContexthub;
+using ::android::hardware::contexthub::V1_2::implementation::Contexthub;
+
+int main() {
+    configureRpcThreadpool(1, true /* callerWillJoin */);
+
+    ::android::sp<IContexthub> contexthub = new Contexthub();
+    if (contexthub->registerAsService() != ::android::OK) {
+        ALOGE("Failed to register Contexthub HAL instance");
+        return 1;
+    }
+
+    joinRpcThreadpool();
+    ALOGE("Service exited");
+    return 1;
+}
diff --git a/contexthub/1.2/types.hal b/contexthub/1.2/types.hal
new file mode 100644
index 0000000..38f9f7a
--- /dev/null
+++ b/contexthub/1.2/types.hal
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+package android.hardware.contexthub@1.2;
+
+import @1.1::Setting;
+
+/**
+ * Used to indicate the type of user setting that has changed.
+ */
+enum Setting : @1.1::Setting {
+    /**
+     * Indicates that the WiFi capabilities can be used in CHRE. This setting
+     * follows the overall availability of WiFi-related functionality within
+     * the Android framework, for example if WiFi is disabled for connectivity
+     * purposes but is enabled for location purposes (scanning), then
+     * WIFI_AVAILABLE is enabled.
+     */
+    WIFI_AVAILABLE,
+    AIRPLANE_MODE,
+};
diff --git a/powerstats/aidl/vts/Android.bp b/contexthub/1.2/vts/functional/Android.bp
similarity index 69%
copy from powerstats/aidl/vts/Android.bp
copy to contexthub/1.2/vts/functional/Android.bp
index c61022e..6e425be 100644
--- a/powerstats/aidl/vts/Android.bp
+++ b/contexthub/1.2/vts/functional/Android.bp
@@ -1,3 +1,4 @@
+//
 // Copyright (C) 2020 The Android Open Source Project
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
@@ -11,19 +12,17 @@
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 // See the License for the specific language governing permissions and
 // limitations under the License.
+//
 
 cc_test {
-    name: "VtsHalPowerStatsTargetTest",
-    defaults: [
-        "VtsHalTargetTestDefaults",
-        "use_libaidlvintf_gtest_helper_static",
-    ],
-    srcs: ["VtsHalPowerStatsTargetTest.cpp"],
-    shared_libs: [
-        "libbinder_ndk",
-    ],
+    name: "VtsHalContexthubV1_2TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: ["VtsHalContexthubV1_2TargetTest.cpp"],
     static_libs: [
-        "android.hardware.powerstats-ndk_platform",
+        "android.hardware.contexthub@1.0",
+        "android.hardware.contexthub@1.1",
+        "android.hardware.contexthub@1.2",
+        "VtsHalContexthubUtils",
     ],
     test_suites: [
         "general-tests",
diff --git a/contexthub/1.2/vts/functional/OWNERS b/contexthub/1.2/vts/functional/OWNERS
new file mode 100644
index 0000000..1a33a9e
--- /dev/null
+++ b/contexthub/1.2/vts/functional/OWNERS
@@ -0,0 +1,7 @@
+#Context Hub team
+arthuri@google.com
+bduddie@google.com
+stange@google.com
+
+#VTS team
+dshi@google.com
diff --git a/contexthub/1.2/vts/functional/VtsHalContexthubV1_2TargetTest.cpp b/contexthub/1.2/vts/functional/VtsHalContexthubV1_2TargetTest.cpp
new file mode 100644
index 0000000..77883c2
--- /dev/null
+++ b/contexthub/1.2/vts/functional/VtsHalContexthubV1_2TargetTest.cpp
@@ -0,0 +1,69 @@
+/*
+ * 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 "contexthub_hidl_hal_test"
+
+#include "ContexthubCallbackBase.h"
+#include "ContexthubHidlTestBase.h"
+#include "VtsHalContexthubUtils.h"
+
+#include <android-base/logging.h>
+#include <android/hardware/contexthub/1.0/IContexthub.h>
+#include <android/hardware/contexthub/1.1/IContexthub.h>
+#include <android/hardware/contexthub/1.2/IContexthub.h>
+#include <android/log.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
+#include <log/log.h>
+
+#include <cinttypes>
+
+using ::android::hardware::contexthub::V1_1::SettingValue;
+using ::android::hardware::contexthub::V1_2::IContexthub;
+using ::android::hardware::contexthub::V1_2::Setting;
+using ::android::hardware::contexthub::vts_utils::ContexthubCallbackBase;
+using ::android::hardware::contexthub::vts_utils::ContexthubHidlTestBase;
+using ::android::hardware::contexthub::vts_utils::getHalAndHubIdList;
+
+namespace {
+
+const std::vector<std::tuple<std::string, std::string>> kTestParameters =
+        getHalAndHubIdList<IContexthub>();
+
+class ContexthubHidlTest : public ContexthubHidlTestBase<IContexthub> {};
+
+// In VTS, we only test that sending the values doesn't cause things to blow up - other test
+// suites verify the expected E2E behavior in CHRE
+TEST_P(ContexthubHidlTest, TestOnWifiSettingChanged) {
+    ASSERT_OK(registerCallback(new ContexthubCallbackBase()));
+    hubApi->onSettingChanged_1_2(Setting::WIFI_AVAILABLE, SettingValue::DISABLED);
+    hubApi->onSettingChanged_1_2(Setting::WIFI_AVAILABLE, SettingValue::ENABLED);
+    ASSERT_OK(registerCallback(nullptr));
+}
+
+TEST_P(ContexthubHidlTest, TestOnAirplaneModeSettingChanged) {
+    ASSERT_OK(registerCallback(new ContexthubCallbackBase()));
+    hubApi->onSettingChanged_1_2(Setting::AIRPLANE_MODE, SettingValue::DISABLED);
+    hubApi->onSettingChanged_1_2(Setting::AIRPLANE_MODE, SettingValue::ENABLED);
+    ASSERT_OK(registerCallback(nullptr));
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ContexthubHidlTest);
+INSTANTIATE_TEST_SUITE_P(HubIdSpecificTests, ContexthubHidlTest, testing::ValuesIn(kTestParameters),
+                         android::hardware::PrintInstanceTupleNameToString<>);
+
+}  // anonymous namespace
diff --git a/powerstats/aidl/Android.bp b/contexthub/common/default/1.X/Android.bp
similarity index 63%
copy from powerstats/aidl/Android.bp
copy to contexthub/common/default/1.X/Android.bp
index 1aa58cb..691a1b7 100644
--- a/powerstats/aidl/Android.bp
+++ b/contexthub/common/default/1.X/Android.bp
@@ -1,3 +1,4 @@
+//
 // Copyright (C) 2020 The Android Open Source Project
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
@@ -12,24 +13,16 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-aidl_interface {
-    name: "android.hardware.powerstats",
+cc_library_headers {
+    name: "android.hardware.contexthub@1.X-common-impl",
     vendor_available: true,
-    srcs: [
-        "android/hardware/powerstats/*.aidl",
+    defaults: ["hidl_defaults"],
+    export_include_dirs: ["."],
+    shared_libs: [
+        "android.hardware.contexthub@1.0",
+        "libbinder",
+        "libcutils",
+        "libhidlbase",
+        "libutils",
     ],
-    stability: "vintf",
-    backend: {
-        java: {
-            platform_apis: true,
-        },
-        ndk: {
-            vndk: {
-                enabled: true,
-            },
-        },
-        cpp: {
-            enabled: false,
-        },
-    },
 }
diff --git a/contexthub/common/default/1.X/ContextHub.h b/contexthub/common/default/1.X/ContextHub.h
new file mode 100644
index 0000000..73d0631
--- /dev/null
+++ b/contexthub/common/default/1.X/ContextHub.h
@@ -0,0 +1,117 @@
+/*
+ * 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_CONTEXTHUB_V1_X_CONTEXTHUB_H
+#define ANDROID_HARDWARE_CONTEXTHUB_V1_X_CONTEXTHUB_H
+
+#include <android/hardware/contexthub/1.0/IContexthub.h>
+#include <android/hardware/contexthub/1.0/types.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace contexthub {
+namespace V1_X {
+namespace implementation {
+
+template <class IContextHubInterface>
+struct ContextHub : public IContextHubInterface {
+    using ContextHubMsg = ::android::hardware::contexthub::V1_0::ContextHubMsg;
+    using HubAppInfo = ::android::hardware::contexthub::V1_0::HubAppInfo;
+    using IContexthubCallback = ::android::hardware::contexthub::V1_0::IContexthubCallback;
+    using NanoAppBinary = ::android::hardware::contexthub::V1_0::NanoAppBinary;
+    using Result = ::android::hardware::contexthub::V1_0::Result;
+    using getHubs_cb = ::android::hardware::contexthub::V1_0::IContexthub::getHubs_cb;
+
+  public:
+    Return<void> getHubs(getHubs_cb _hidl_cb) override {
+        ::android::hardware::contexthub::V1_0::ContextHub hub = {};
+        hub.name = "Mock Context Hub";
+        hub.vendor = "AOSP";
+        hub.toolchain = "n/a";
+        hub.platformVersion = 1;
+        hub.toolchainVersion = 1;
+        hub.hubId = kMockHubId;
+        hub.peakMips = 1;
+        hub.peakPowerDrawMw = 1;
+        hub.maxSupportedMsgLen = 4096;
+        hub.chrePlatformId = UINT64_C(0x476f6f6754000000);
+        hub.chreApiMajorVersion = 1;
+        hub.chreApiMinorVersion = 4;
+
+        // Report a single mock hub
+        std::vector<::android::hardware::contexthub::V1_0::ContextHub> hubs;
+        hubs.push_back(hub);
+
+        _hidl_cb(hubs);
+        return Void();
+    }
+
+    Return<Result> registerCallback(uint32_t hubId, const sp<IContexthubCallback>& cb) override {
+        if (hubId == kMockHubId) {
+            mCallback = cb;
+            return Result::OK;
+        }
+        return Result::BAD_PARAMS;
+    }
+
+    // We don't expose any nanoapps, therefore all nanoapp-related API calls return with BAD_PARAMS
+    Return<Result> sendMessageToHub(uint32_t /*hubId*/, const ContextHubMsg& /*msg*/) override {
+        return Result::BAD_PARAMS;
+    }
+
+    Return<Result> loadNanoApp(uint32_t /*hubId*/, const NanoAppBinary& /*appBinary*/,
+                               uint32_t /*transactionId*/) override {
+        return Result::BAD_PARAMS;
+    }
+
+    Return<Result> unloadNanoApp(uint32_t /*hubId*/, uint64_t /*appId*/,
+                                 uint32_t /*transactionId*/) override {
+        return Result::BAD_PARAMS;
+    }
+
+    Return<Result> enableNanoApp(uint32_t /*hubId*/, uint64_t /*appId*/,
+                                 uint32_t /*transactionId*/) override {
+        return Result::BAD_PARAMS;
+    }
+
+    Return<Result> disableNanoApp(uint32_t /*hubId*/, uint64_t /*appId*/,
+                                  uint32_t /*transactionId*/) override {
+        return Result::BAD_PARAMS;
+    }
+
+    Return<Result> queryApps(uint32_t hubId) override {
+        if (hubId == kMockHubId && mCallback != nullptr) {
+            std::vector<HubAppInfo> nanoapps;
+            mCallback->handleAppsInfo(nanoapps);
+            return Result::OK;
+        }
+        return Result::BAD_PARAMS;
+    }
+
+  private:
+    static constexpr uint32_t kMockHubId = 0;
+
+    sp<IContexthubCallback> mCallback;
+};
+
+}  // namespace implementation
+}  // namespace V1_X
+}  // namespace contexthub
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_CONTEXTHUB_V1_X_CONTEXTHUB_H
diff --git a/current.txt b/current.txt
index 9c5091b..d8ca42c 100644
--- a/current.txt
+++ b/current.txt
@@ -767,6 +767,7 @@
 98592d193a717066facf91428426e5abe211e3bd718bc372e29fb944ddbe6e7c android.hardware.wifi.supplicant@1.3::types
 
 # ABI preserving changes to HALs during Android S
+3da3ce039247872d95c6bd48621dbfdfa1c2d2a91a90f257862f87ee2bc46300 android.hardware.health@2.1::types
 cd84ab19c590e0e73dd2307b591a3093ee18147ef95e6d5418644463a6620076 android.hardware.neuralnetworks@1.2::IDevice
 9625e85f56515ad2cf87b6a1847906db669f746ea4ab02cd3d4ca25abc9b0109 android.hardware.neuralnetworks@1.2::types
 9e758e208d14f7256e0885d6d8ad0b61121b21d8c313864f981727ae55bffd16 android.hardware.neuralnetworks@1.3::types
@@ -777,7 +778,5 @@
 # HALs released in Android S
 # NOTE: waiting to freeze HALs until later in the release
 # NOTE: new HALs are recommended to be in AIDL
-57d183b10b13ec0a8e542c0b3d61991ae541c60e85dbbc5499bb21dfd068cbb8 android.hardware.wifi.supplicant@1.4::types
-17818b6b1952a75e4364ae82c534b9d2f5c0a9765a56256b16faa5a5cf45d3a8 android.hardware.wifi.supplicant@1.4::ISupplicant
-8342b5f6ec8f48ad2b741128aede010995d0b5709257b7ec09bb469b4f61ef1a android.hardware.wifi.supplicant@1.4::ISupplicantStaIface
-6f969b191f0b699ceab0573548f1ac505853e56e704711edc51b51976d4f87ad android.hardware.wifi.supplicant@1.4::ISupplicantStaNetwork
+6e64b33f1b720b66b0deb5e08dee37a99deaa94e2e9ebf7806703cabab56e21d android.hardware.contexthub@1.2::IContexthub
+3fb83f4539cab2c7bf9fdbecf7265d1c1dd6e8de9694046fe512b493c127ccea android.hardware.contexthub@1.2::types
diff --git a/fastboot/1.1/Android.bp b/fastboot/1.1/Android.bp
new file mode 100644
index 0000000..46306cf
--- /dev/null
+++ b/fastboot/1.1/Android.bp
@@ -0,0 +1,14 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.fastboot@1.1",
+    root: "android.hardware",
+    srcs: [
+        "IFastboot.hal",
+    ],
+    interfaces: [
+        "android.hardware.fastboot@1.0",
+        "android.hidl.base@1.0",
+    ],
+    gen_java: true,
+}
diff --git a/fastboot/1.1/IFastboot.hal b/fastboot/1.1/IFastboot.hal
new file mode 100644
index 0000000..c8f1ad0
--- /dev/null
+++ b/fastboot/1.1/IFastboot.hal
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+package android.hardware.fastboot@1.1;
+import android.hardware.fastboot@1.0;
+
+/**
+ * IFastboot interface implements vendor specific fastboot commands.
+ */
+interface IFastboot extends @1.0::IFastboot {
+    /**
+     * Executes an OEM specific erase after fastboot erase userdata.
+     *
+     * @return result Returns the status SUCCESS if the operation is successful,
+     *     NOT_SUPPORTED for unsupported command.
+     *     INVALID_ARGUMENT for bad arguments,
+     *     FAILURE_UNKNOWN for unknown error in the oem specific command.
+     */
+    doOemSpecificErase() generates (Result result);
+};
diff --git a/powerstats/aidl/default/Android.bp b/fastboot/1.1/default/Android.bp
similarity index 70%
copy from powerstats/aidl/default/Android.bp
copy to fastboot/1.1/default/Android.bp
index caecd88..980586b 100644
--- a/powerstats/aidl/default/Android.bp
+++ b/fastboot/1.1/default/Android.bp
@@ -1,3 +1,4 @@
+//
 // Copyright (C) 2020 The Android Open Source Project
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
@@ -12,19 +13,19 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-cc_binary {
-    name: "android.hardware.powerstats-service.example",
+cc_library {
+    name: "android.hardware.fastboot@1.1-impl-mock",
+    recovery: true,
+    srcs: [
+        "Fastboot.cpp",
+    ],
     relative_install_path: "hw",
-    init_rc: ["powerstats-default.rc"],
-    vintf_fragments: ["powerstats-default.xml"],
-    vendor: true,
     shared_libs: [
         "libbase",
-        "libbinder_ndk",
-        "android.hardware.powerstats-ndk_platform",
-    ],
-    srcs: [
-        "main.cpp",
-        "PowerStats.cpp",
+        "libhidlbase",
+        "libutils",
+        "libcutils",
+        "android.hardware.fastboot@1.0",
+        "android.hardware.fastboot@1.1",
     ],
 }
diff --git a/fastboot/1.1/default/Fastboot.cpp b/fastboot/1.1/default/Fastboot.cpp
new file mode 100644
index 0000000..0b502e0
--- /dev/null
+++ b/fastboot/1.1/default/Fastboot.cpp
@@ -0,0 +1,66 @@
+/*
+ * 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 "Fastboot.h"
+
+namespace android {
+namespace hardware {
+namespace fastboot {
+namespace V1_1 {
+namespace implementation {
+
+// Methods from ::android::hardware::fastboot::V1_1::IFastboot follow.
+Return<void> Fastboot::getPartitionType(const hidl_string& /* partitionName */,
+                                        getPartitionType_cb _hidl_cb) {
+    _hidl_cb(FileSystemType::RAW, {Status::SUCCESS, ""});
+    return Void();
+}
+
+Return<void> Fastboot::doOemCommand(const hidl_string& /* oemCmd */, doOemCommand_cb _hidl_cb) {
+    _hidl_cb({Status::FAILURE_UNKNOWN, "Command not supported in default implementation"});
+    return Void();
+}
+
+Return<void> Fastboot::getVariant(getVariant_cb _hidl_cb) {
+    _hidl_cb("NA", {Status::SUCCESS, ""});
+    return Void();
+}
+
+Return<void> Fastboot::getOffModeChargeState(getOffModeChargeState_cb _hidl_cb) {
+    _hidl_cb(false, {Status::SUCCESS, ""});
+    return Void();
+}
+
+Return<void> Fastboot::getBatteryVoltageFlashingThreshold(
+        getBatteryVoltageFlashingThreshold_cb _hidl_cb) {
+    _hidl_cb(0, {Status::SUCCESS, ""});
+    return Void();
+}
+
+Return<void> Fastboot::doOemSpecificErase(doOemSpecificErase_cb _hidl_cb) {
+    _hidl_cb({Status::NOT_SUPPORTED, "Command not supported in default implementation"});
+    return Void();
+}
+
+extern "C" IFastboot* HIDL_FETCH_IFastboot(const char* /* name */) {
+    return new Fastboot();
+}
+
+}  // namespace implementation
+}  // namespace V1_1
+}  // namespace fastboot
+}  // namespace hardware
+}  // namespace android
diff --git a/fastboot/1.1/default/Fastboot.h b/fastboot/1.1/default/Fastboot.h
new file mode 100644
index 0000000..09b39c2
--- /dev/null
+++ b/fastboot/1.1/default/Fastboot.h
@@ -0,0 +1,52 @@
+/*
+ * 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/fastboot/1.1/IFastboot.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace fastboot {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::hardware::hidl_string;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::fastboot::V1_0::FileSystemType;
+using ::android::hardware::fastboot::V1_0::Status;
+using ::android::hardware::fastboot::V1_0::Result;
+
+struct Fastboot : public IFastboot {
+    // Methods from ::android::hardware::fastboot::V1_0::IFastboot follow.
+    Return<void> getPartitionType(const hidl_string& partitionName,
+                                  getPartitionType_cb _hidl_cb) override;
+    Return<void> doOemCommand(const hidl_string& oemCmd, doOemCommand_cb _hidl_cb) override;
+    Return<void> getVariant(getVariant_cb _hidl_cb) override;
+    Return<void> getOffModeChargeState(getOffModeChargeState_cb _hidl_cb) override;
+    Return<void> getBatteryVoltageFlashingThreshold(
+            getBatteryVoltageFlashingThreshold_cb _hidl_cb) override;
+    Return<void> doOemSpecificErase(doOemSpecificErase_cb _hidl_cb) override;
+};
+
+extern "C" IFastboot* HIDL_FETCH_IFastboot(const char* name);
+
+}  // namespace implementation
+}  // namespace V1_1
+}  // namespace fastboot
+}  // namespace hardware
+}  // namespace android
diff --git a/gnss/1.0/vts/functional/VtsHalGnssV1_0TargetTest.cpp b/gnss/1.0/vts/functional/VtsHalGnssV1_0TargetTest.cpp
index 97e7c27..237e8ec 100644
--- a/gnss/1.0/vts/functional/VtsHalGnssV1_0TargetTest.cpp
+++ b/gnss/1.0/vts/functional/VtsHalGnssV1_0TargetTest.cpp
@@ -39,6 +39,10 @@
 using android::hardware::gnss::V1_0::IGnssMeasurement;
 using android::sp;
 
+/*
+ * Since Utils.cpp depends on Gnss Hal 2.0, the tests for Gnss Hal 1.0 will use
+ * there own version of IsAutomotiveDevice() instead of the common version.
+ */
 static bool IsAutomotiveDevice() {
     char buffer[PROPERTY_VALUE_MAX] = {0};
     property_get("ro.hardware.type", buffer, "");
@@ -492,9 +496,9 @@
  * Verifies that modern hardware supports measurement capabilities.
  */
 TEST_P(GnssHalTest, MeasurementCapabilites) {
-  if (info_called_count_ > 0 && last_info_.yearOfHw >= 2016) {
-    EXPECT_TRUE(last_capabilities_ & IGnssCallback::Capabilities::MEASUREMENTS);
-  }
+    if (!IsAutomotiveDevice() && info_called_count_ > 0 && last_info_.yearOfHw >= 2016) {
+        EXPECT_TRUE(last_capabilities_ & IGnssCallback::Capabilities::MEASUREMENTS);
+    }
 }
 
 /*
@@ -529,4 +533,4 @@
   }
 
   return RUN_ALL_TESTS();
-}
\ No newline at end of file
+}
diff --git a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp
index 51dcf0d..3e0058f 100644
--- a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp
+++ b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp
@@ -62,6 +62,15 @@
     auto gnssMeasurement_1_0 = gnss_hal_->getExtensionGnssMeasurement();
     ASSERT_TRUE(gnssMeasurement_2_0.isOk() && gnssMeasurement_1_1.isOk() &&
                 gnssMeasurement_1_0.isOk());
+
+    // CDD does not require Android Automotive OS devices to support
+    // GnssMeasurements.
+    if (Utils::isAutomotiveDevice()) {
+        ALOGI("Test GnssMeasurementExtension skipped. Android Automotive OS deice is not required "
+              "to support GNSS measurements.");
+        return;
+    }
+
     sp<IGnssMeasurement_2_0> iGnssMeas_2_0 = gnssMeasurement_2_0;
     sp<IGnssMeasurement_1_1> iGnssMeas_1_1 = gnssMeasurement_1_1;
     sp<IGnssMeasurement_1_0> iGnssMeas_1_0 = gnssMeasurement_1_0;
diff --git a/gnss/2.1/vts/functional/gnss_hal_test_cases.cpp b/gnss/2.1/vts/functional/gnss_hal_test_cases.cpp
index 16e634f..2902809 100644
--- a/gnss/2.1/vts/functional/gnss_hal_test_cases.cpp
+++ b/gnss/2.1/vts/functional/gnss_hal_test_cases.cpp
@@ -63,6 +63,15 @@
     auto gnssMeasurement_1_0 = gnss_hal_->getExtensionGnssMeasurement();
     ASSERT_TRUE(gnssMeasurement_2_1.isOk() && gnssMeasurement_2_0.isOk() &&
                 gnssMeasurement_1_1.isOk() && gnssMeasurement_1_0.isOk());
+
+    // CDD does not require Android Automotive OS devices to support
+    // GnssMeasurements.
+    if (Utils::isAutomotiveDevice()) {
+        ALOGI("Test GnssMeasurementExtension skipped. Android Automotive OS de  ice is not "
+              "required to support GNSS measurements.");
+        return;
+    }
+
     sp<IGnssMeasurement_2_1> iGnssMeas_2_1 = gnssMeasurement_2_1;
     sp<IGnssMeasurement_2_0> iGnssMeas_2_0 = gnssMeasurement_2_0;
     sp<IGnssMeasurement_1_1> iGnssMeas_1_1 = gnssMeasurement_1_1;
diff --git a/powerstats/aidl/android/hardware/powerstats/PowerEntityStateInfo.aidl b/gnss/aidl/Android.bp
similarity index 65%
copy from powerstats/aidl/android/hardware/powerstats/PowerEntityStateInfo.aidl
copy to gnss/aidl/Android.bp
index 69fc798..c503190 100644
--- a/powerstats/aidl/android/hardware/powerstats/PowerEntityStateInfo.aidl
+++ b/gnss/aidl/Android.bp
@@ -14,17 +14,19 @@
  * limitations under the License.
  */
 
-package android.hardware.powerstats;
-
-@VintfStability
-parcelable PowerEntityStateInfo {
-    /**
-     * ID corresponding to the state. Unique for a given PowerEntityStateSpace
-     */
-    int powerEntityStateId;
-    /**
-     * Name of the state (opaque to the framework)
-     */
-    String powerEntityStateName;
+aidl_interface {
+    name: "android.hardware.gnss",
+    vendor_available: true,
+    srcs: ["android/hardware/gnss/*.aidl"],
+    stability: "vintf",
+    backend: {
+        java: {
+            platform_apis: true,
+        },
+        ndk: {
+            vndk: {
+                enabled: true,
+            },
+        },
+    },
 }
-
diff --git a/gnss/aidl/OWNERS b/gnss/aidl/OWNERS
new file mode 100644
index 0000000..b7b4a2e
--- /dev/null
+++ b/gnss/aidl/OWNERS
@@ -0,0 +1,4 @@
+gomo@google.com
+smalkos@google.com
+wyattriley@google.com
+yuhany@google.com
diff --git a/common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/UnsynchronizedWrite.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnss.aidl
similarity index 90%
copy from common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/UnsynchronizedWrite.aidl
copy to gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnss.aidl
index e390d20..33377ca 100644
--- a/common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/UnsynchronizedWrite.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnss.aidl
@@ -15,8 +15,8 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.common;
+package android.hardware.gnss;
 @VintfStability
-enum UnsynchronizedWrite {
-  EMPTY = 0,
+interface IGnss {
+  android.hardware.gnss.IGnssPsds getExtensionPsds();
 }
diff --git a/common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/MQDescriptor.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPsds.aidl
similarity index 82%
copy from common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/MQDescriptor.aidl
copy to gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPsds.aidl
index c9fe1d7..352a694 100644
--- a/common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/MQDescriptor.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPsds.aidl
@@ -15,11 +15,9 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.common;
+package android.hardware.gnss;
 @VintfStability
-parcelable MQDescriptor {
-  android.hardware.common.GrantorDescriptor[] grantors;
-  ParcelFileDescriptor fileDescriptor;
-  int quantum;
-  int flags;
+interface IGnssPsds {
+  boolean injectPsdsData(in android.hardware.gnss.PsdsType psdsType, in byte[] psdsData);
+  boolean setCallback(in android.hardware.gnss.IGnssPsdsCallback callback);
 }
diff --git a/powerstats/aidl/aidl_api/android.hardware.powerstats/current/android/hardware/powerstats/PowerEntityStateInfo.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPsdsCallback.aidl
similarity index 88%
rename from powerstats/aidl/aidl_api/android.hardware.powerstats/current/android/hardware/powerstats/PowerEntityStateInfo.aidl
rename to gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPsdsCallback.aidl
index 9de66ba..8413d2c 100644
--- a/powerstats/aidl/aidl_api/android.hardware.powerstats/current/android/hardware/powerstats/PowerEntityStateInfo.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPsdsCallback.aidl
@@ -15,9 +15,8 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.powerstats;
+package android.hardware.gnss;
 @VintfStability
-parcelable PowerEntityStateInfo {
-  int powerEntityStateId;
-  String powerEntityStateName;
+interface IGnssPsdsCallback {
+  void downloadRequestCb(in android.hardware.gnss.PsdsType psdsType);
 }
diff --git a/common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/UnsynchronizedWrite.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/PsdsType.aidl
similarity index 88%
copy from common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/UnsynchronizedWrite.aidl
copy to gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/PsdsType.aidl
index e390d20..9d1984e 100644
--- a/common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/UnsynchronizedWrite.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/PsdsType.aidl
@@ -15,8 +15,10 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.common;
-@VintfStability
-enum UnsynchronizedWrite {
-  EMPTY = 0,
+package android.hardware.gnss;
+@Backing(type="int") @VintfStability
+enum PsdsType {
+  LONG_TERM = 1,
+  NORMAL = 2,
+  REALTIME = 3,
 }
diff --git a/powerstats/aidl/android/hardware/powerstats/PowerEntityStateInfo.aidl b/gnss/aidl/android/hardware/gnss/IGnss.aidl
similarity index 66%
copy from powerstats/aidl/android/hardware/powerstats/PowerEntityStateInfo.aidl
copy to gnss/aidl/android/hardware/gnss/IGnss.aidl
index 69fc798..1da254c 100644
--- a/powerstats/aidl/android/hardware/powerstats/PowerEntityStateInfo.aidl
+++ b/gnss/aidl/android/hardware/gnss/IGnss.aidl
@@ -14,17 +14,20 @@
  * limitations under the License.
  */
 
-package android.hardware.powerstats;
+package android.hardware.gnss;
 
+import android.hardware.gnss.IGnssPsds;
+
+/**
+ * Represents the standard GNSS (Global Navigation Satellite System) interface.
+ */
 @VintfStability
-parcelable PowerEntityStateInfo {
-    /**
-     * ID corresponding to the state. Unique for a given PowerEntityStateSpace
-     */
-    int powerEntityStateId;
-    /**
-     * Name of the state (opaque to the framework)
-     */
-    String powerEntityStateName;
-}
+interface IGnss {
 
+    /**
+     * This method returns the IGnssPsds interface.
+     *
+     * @return Handle to the IGnssPsds interface.
+     */
+    IGnssPsds getExtensionPsds();
+}
\ No newline at end of file
diff --git a/gnss/aidl/android/hardware/gnss/IGnssPsds.aidl b/gnss/aidl/android/hardware/gnss/IGnssPsds.aidl
new file mode 100644
index 0000000..6f53d6f
--- /dev/null
+++ b/gnss/aidl/android/hardware/gnss/IGnssPsds.aidl
@@ -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.
+ */
+
+package android.hardware.gnss;
+
+import android.hardware.gnss.IGnssPsdsCallback;
+import android.hardware.gnss.PsdsType;
+
+/**
+ * This interface is used by the GNSS HAL to request the framework to download Predicted Satellite
+ * Data Service data.
+ */
+@VintfStability
+interface IGnssPsds {
+
+    /**
+     * Inject the downloaded PSDS data into the GNSS receiver.
+     *
+     * @param psdsType Type of PSDS data.
+     * @param psdsData GNSS PSDS data. Framework must not parse the data since the data format is
+     *                 opaque to framework.
+     *
+     * @return True if the operation is successful.
+     */
+    boolean injectPsdsData(in PsdsType psdsType, in byte[] psdsData);
+
+    /**
+     * Opens the PSDS interface and provides the callback routines to the implementation of this
+     * interface.
+     *
+     * @param callback Handle to the IGnssPsdsCallback interface.
+     *
+     * @return True if the operation is successful.
+     */
+    boolean setCallback(in IGnssPsdsCallback callback);
+}
\ No newline at end of file
diff --git a/gnss/aidl/android/hardware/gnss/IGnssPsdsCallback.aidl b/gnss/aidl/android/hardware/gnss/IGnssPsdsCallback.aidl
new file mode 100644
index 0000000..72b693b
--- /dev/null
+++ b/gnss/aidl/android/hardware/gnss/IGnssPsdsCallback.aidl
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+package android.hardware.gnss;
+
+import android.hardware.gnss.PsdsType;
+
+/**
+ * This interface is used by the GNSS HAL to request download data from Predicted Satellite Data
+ * Service (PSDS).
+ */
+@VintfStability
+interface IGnssPsdsCallback {
+
+    /**
+     * Callback to request the client to download PSDS data from one of the URLs defined in the
+     * framework specified by psdsType. The URLs must be specified via properties on the vendor
+     * partitions. E.g., LONGTERM_PSDS_SERVER_1, NORMAL_PSDS_SERVER, or REALTIME_PSDS_SERVER. The
+     * client must download PSDS data and inject it by calling injectPsdsData().
+     *
+     * @param psdsType Type of PSDS data.
+     */
+    void downloadRequestCb(in PsdsType psdsType);
+}
\ No newline at end of file
diff --git a/gnss/aidl/android/hardware/gnss/PsdsType.aidl b/gnss/aidl/android/hardware/gnss/PsdsType.aidl
new file mode 100644
index 0000000..d4fec77
--- /dev/null
+++ b/gnss/aidl/android/hardware/gnss/PsdsType.aidl
@@ -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.
+ */
+
+package android.hardware.gnss;
+
+/** The type of PSDS data. */
+@VintfStability
+@Backing(type="int")
+enum PsdsType {
+
+    /**
+     * Long-Term type PSDS data, which lasts for many hours to several days and often provides
+     * satellite orbit and clock accuracy of 2 - 20 meters.
+     */
+    LONG_TERM = 1,
+
+    /**
+     * Normal type PSDS data, which is similar to broadcast ephemeris in longevity - lasting for
+     * hours and providings satellite orbit and clock accuracy of 1 - 2 meters.
+     */
+    NORMAL = 2,
+
+    /**
+     * Real-Time type PSDS data, which lasts for minutes and provides brief satellite status
+     * information such as temporary malfunction, but does not include satellite orbit or clock
+     * information.
+     */
+    REALTIME = 3,
+}
diff --git a/gnss/aidl/default/Android.bp b/gnss/aidl/default/Android.bp
new file mode 100644
index 0000000..8c4ee40
--- /dev/null
+++ b/gnss/aidl/default/Android.bp
@@ -0,0 +1,38 @@
+/*
+ * 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.gnss-service.example",
+    relative_install_path: "hw",
+    init_rc: ["gnss-default.rc"],
+    vintf_fragments: ["gnss-default.xml"],
+    vendor: true,
+    cflags: [
+        "-Wall",
+        "-Wextra",
+    ],
+    shared_libs: [
+        "libbase",
+        "libbinder_ndk",
+        "liblog",
+        "android.hardware.gnss-ndk_platform",
+    ],
+    srcs: [
+        "Gnss.cpp",
+        "GnssPsds.cpp",
+        "service.cpp",
+    ],
+}
diff --git a/powerstats/aidl/android/hardware/powerstats/PowerEntityStateInfo.aidl b/gnss/aidl/default/Gnss.cpp
similarity index 61%
copy from powerstats/aidl/android/hardware/powerstats/PowerEntityStateInfo.aidl
copy to gnss/aidl/default/Gnss.cpp
index 69fc798..2a35924 100644
--- a/powerstats/aidl/android/hardware/powerstats/PowerEntityStateInfo.aidl
+++ b/gnss/aidl/default/Gnss.cpp
@@ -14,17 +14,18 @@
  * limitations under the License.
  */
 
-package android.hardware.powerstats;
+#define LOG_TAG "GnssAidl"
 
-@VintfStability
-parcelable PowerEntityStateInfo {
-    /**
-     * ID corresponding to the state. Unique for a given PowerEntityStateSpace
-     */
-    int powerEntityStateId;
-    /**
-     * Name of the state (opaque to the framework)
-     */
-    String powerEntityStateName;
+#include "Gnss.h"
+#include <log/log.h>
+#include "GnssPsds.h"
+
+namespace aidl::android::hardware::gnss {
+
+ndk::ScopedAStatus Gnss::getExtensionPsds(std::shared_ptr<IGnssPsds>* iGnssPsds) {
+    ALOGD("Gnss::getExtensionPsds");
+    *iGnssPsds = SharedRefBase::make<GnssPsds>();
+    return ndk::ScopedAStatus::ok();
 }
 
+}  // namespace aidl::android::hardware::gnss
diff --git a/powerstats/aidl/android/hardware/powerstats/PowerEntityStateInfo.aidl b/gnss/aidl/default/Gnss.h
similarity index 65%
copy from powerstats/aidl/android/hardware/powerstats/PowerEntityStateInfo.aidl
copy to gnss/aidl/default/Gnss.h
index 69fc798..9864e9d 100644
--- a/powerstats/aidl/android/hardware/powerstats/PowerEntityStateInfo.aidl
+++ b/gnss/aidl/default/Gnss.h
@@ -14,17 +14,15 @@
  * limitations under the License.
  */
 
-package android.hardware.powerstats;
+#pragma once
 
-@VintfStability
-parcelable PowerEntityStateInfo {
-    /**
-     * ID corresponding to the state. Unique for a given PowerEntityStateSpace
-     */
-    int powerEntityStateId;
-    /**
-     * Name of the state (opaque to the framework)
-     */
-    String powerEntityStateName;
-}
+#include <aidl/android/hardware/gnss/BnGnss.h>
+#include <aidl/android/hardware/gnss/BnGnssPsds.h>
 
+namespace aidl::android::hardware::gnss {
+
+class Gnss : public BnGnss {
+    ndk::ScopedAStatus getExtensionPsds(std::shared_ptr<IGnssPsds>* iGnssPsds) override;
+};
+
+}  // namespace aidl::android::hardware::gnss
diff --git a/gnss/aidl/default/GnssPsds.cpp b/gnss/aidl/default/GnssPsds.cpp
new file mode 100644
index 0000000..c354217
--- /dev/null
+++ b/gnss/aidl/default/GnssPsds.cpp
@@ -0,0 +1,43 @@
+/*
+ * 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 "GnssPsdsAidl"
+
+#include "GnssPsds.h"
+
+#include <log/log.h>
+
+namespace aidl::android::hardware::gnss {
+
+std::shared_ptr<IGnssPsdsCallback> GnssPsds::sCallback = nullptr;
+
+ndk::ScopedAStatus GnssPsds::setCallback(const std::shared_ptr<IGnssPsdsCallback>& callback,
+                                         bool* success) {
+    ALOGD("setCallback");
+    std::unique_lock<std::mutex> lock(mMutex);
+    sCallback = callback;
+    *success = true;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus GnssPsds::injectPsdsData(PsdsType psdsType, const std::vector<uint8_t>& psdsData,
+                                            bool* success) {
+    ALOGD("injectPsdsData. psdsType: %d, psdsData: %d bytes", static_cast<int>(psdsType),
+          static_cast<int>(psdsData.size()));
+    *success = (psdsData.size() > 0);
+    return ndk::ScopedAStatus::ok();
+}
+}  // namespace aidl::android::hardware::gnss
diff --git a/gnss/aidl/default/GnssPsds.h b/gnss/aidl/default/GnssPsds.h
new file mode 100644
index 0000000..fc65bc1
--- /dev/null
+++ b/gnss/aidl/default/GnssPsds.h
@@ -0,0 +1,38 @@
+/*
+ * 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 <aidl/android/hardware/gnss/BnGnssPsds.h>
+
+namespace aidl::android::hardware::gnss {
+
+struct GnssPsds : public BnGnssPsds {
+  public:
+    ndk::ScopedAStatus setCallback(const std::shared_ptr<IGnssPsdsCallback>& callback,
+                                   bool* success) override;
+    ndk::ScopedAStatus injectPsdsData(PsdsType psdsType, const std::vector<uint8_t>& psdsData,
+                                      bool* success) override;
+
+  private:
+    // Guarded by mMutex
+    static std::shared_ptr<IGnssPsdsCallback> sCallback;
+
+    // Synchronization lock for sCallback
+    mutable std::mutex mMutex;
+};
+
+}  // namespace aidl::android::hardware::gnss
diff --git a/gnss/aidl/default/gnss-default.rc b/gnss/aidl/default/gnss-default.rc
new file mode 100644
index 0000000..fe179c3
--- /dev/null
+++ b/gnss/aidl/default/gnss-default.rc
@@ -0,0 +1,4 @@
+service vendor.gnss-default /vendor/bin/hw/android.hardware.gnss-service.example
+    class hal
+    user nobody
+    group nobody
diff --git a/gnss/aidl/default/gnss-default.xml b/gnss/aidl/default/gnss-default.xml
new file mode 100644
index 0000000..2b06cd2
--- /dev/null
+++ b/gnss/aidl/default/gnss-default.xml
@@ -0,0 +1,9 @@
+<manifest version="1.0" type="device">
+    <hal format="aidl">
+        <name>android.hardware.gnss</name>
+        <interface>
+            <name>IGnss</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+</manifest>
diff --git a/powerstats/aidl/default/main.cpp b/gnss/aidl/default/service.cpp
similarity index 64%
copy from powerstats/aidl/default/main.cpp
copy to gnss/aidl/default/service.cpp
index 1496805..c79a271 100644
--- a/powerstats/aidl/default/main.cpp
+++ b/gnss/aidl/default/service.cpp
@@ -1,11 +1,11 @@
 /*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright 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
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,20 +14,20 @@
  * limitations under the License.
  */
 
-#include "PowerStats.h"
+#include "Gnss.h"
 
 #include <android-base/logging.h>
 #include <android/binder_manager.h>
 #include <android/binder_process.h>
 
-using aidl::android::hardware::powerstats::PowerStats;
+using aidl::android::hardware::gnss::Gnss;
 
 int main() {
     ABinderProcess_setThreadPoolMaxThreadCount(0);
-    std::shared_ptr<PowerStats> p = ndk::SharedRefBase::make<PowerStats>();
+    std::shared_ptr<Gnss> vib = ndk::SharedRefBase::make<Gnss>();
 
-    const std::string instance = std::string() + PowerStats::descriptor + "/default";
-    binder_status_t status = AServiceManager_addService(p->asBinder().get(), instance.c_str());
+    const std::string instance = std::string() + Gnss::descriptor + "/default";
+    binder_status_t status = AServiceManager_addService(vib->asBinder().get(), instance.c_str());
     CHECK(status == STATUS_OK);
 
     ABinderProcess_joinThreadPool();
diff --git a/powerstats/aidl/vts/Android.bp b/gnss/aidl/vts/Android.bp
similarity index 81%
copy from powerstats/aidl/vts/Android.bp
copy to gnss/aidl/vts/Android.bp
index c61022e..e57b421 100644
--- a/powerstats/aidl/vts/Android.bp
+++ b/gnss/aidl/vts/Android.bp
@@ -13,20 +13,19 @@
 // limitations under the License.
 
 cc_test {
-    name: "VtsHalPowerStatsTargetTest",
+    name: "VtsHalGnssTargetTest",
     defaults: [
         "VtsHalTargetTestDefaults",
         "use_libaidlvintf_gtest_helper_static",
     ],
-    srcs: ["VtsHalPowerStatsTargetTest.cpp"],
+    srcs: ["VtsHalGnssTargetTest.cpp"],
     shared_libs: [
-        "libbinder_ndk",
+        "libbinder",
     ],
     static_libs: [
-        "android.hardware.powerstats-ndk_platform",
+        "android.hardware.gnss-cpp",
     ],
     test_suites: [
-        "general-tests",
         "vts",
     ],
 }
diff --git a/gnss/aidl/vts/VtsHalGnssTargetTest.cpp b/gnss/aidl/vts/VtsHalGnssTargetTest.cpp
new file mode 100644
index 0000000..e7ffc05
--- /dev/null
+++ b/gnss/aidl/vts/VtsHalGnssTargetTest.cpp
@@ -0,0 +1,77 @@
+/*
+ * 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 <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+
+#include <android/hardware/gnss/IGnss.h>
+#include <android/hardware/gnss/IGnssPsds.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+
+using android::ProcessState;
+using android::sp;
+using android::String16;
+using android::binder::Status;
+using android::hardware::gnss::IGnss;
+using android::hardware::gnss::IGnssPsds;
+using android::hardware::gnss::PsdsType;
+
+class GnssAidlHalTest : public testing::TestWithParam<std::string> {
+  public:
+    virtual void SetUp() override {
+        gnss_hal_ = android::waitForDeclaredService<IGnss>(String16(GetParam().c_str()));
+        ASSERT_NE(gnss_hal_, nullptr);
+    }
+
+    sp<IGnss> gnss_hal_;
+};
+
+/*
+ * SetupTeardownCreateCleanup:
+ * Requests the gnss HAL then calls cleanup
+ *
+ * Empty test fixture to verify basic Setup & Teardown
+ */
+TEST_P(GnssAidlHalTest, SetupTeardownCreateCleanup) {}
+
+/*
+ * TestPsdsExtension:
+ * 1. Gets the PsdsExtension and verifies that it returns a non-null extension.
+ * 2. Injects empty PSDS data and verifies that it returns false.
+ */
+TEST_P(GnssAidlHalTest, TestPsdsExtension) {
+    sp<IGnssPsds> iGnssPsds;
+    auto status = gnss_hal_->getExtensionPsds(&iGnssPsds);
+    ASSERT_TRUE(status.isOk());
+    ASSERT_TRUE(iGnssPsds != nullptr);
+
+    bool success;
+    status = iGnssPsds->injectPsdsData(PsdsType::LONG_TERM, std::vector<uint8_t>(), &success);
+    ASSERT_TRUE(status.isOk());
+    ASSERT_FALSE(success);
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GnssAidlHalTest);
+INSTANTIATE_TEST_SUITE_P(, GnssAidlHalTest,
+                         testing::ValuesIn(android::getAidlHalInstanceNames(IGnss::descriptor)),
+                         android::PrintInstanceNameToString);
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    ProcessState::self()->setThreadPoolMaxThreadCount(1);
+    ProcessState::self()->startThreadPool();
+    return RUN_ALL_TESTS();
+}
\ No newline at end of file
diff --git a/gnss/common/utils/vts/Utils.cpp b/gnss/common/utils/vts/Utils.cpp
index 9bf68e6..9c84e80 100644
--- a/gnss/common/utils/vts/Utils.cpp
+++ b/gnss/common/utils/vts/Utils.cpp
@@ -17,6 +17,8 @@
 #include <Utils.h>
 #include "gtest/gtest.h"
 
+#include <cutils/properties.h>
+
 namespace android {
 namespace hardware {
 namespace gnss {
@@ -194,6 +196,12 @@
     }
 }
 
+bool Utils::isAutomotiveDevice() {
+    char buffer[PROPERTY_VALUE_MAX] = {0};
+    property_get("ro.hardware.type", buffer, "");
+    return strncmp(buffer, "automotive", PROPERTY_VALUE_MAX) == 0;
+}
+
 }  // namespace common
 }  // namespace gnss
 }  // namespace hardware
diff --git a/gnss/common/utils/vts/include/Utils.h b/gnss/common/utils/vts/include/Utils.h
index 9c838b2..a4aad80 100644
--- a/gnss/common/utils/vts/include/Utils.h
+++ b/gnss/common/utils/vts/include/Utils.h
@@ -49,6 +49,8 @@
     static const MeasurementCorrections_1_1 getMockMeasurementCorrections_1_1();
 
     static GnssConstellationType_1_0 mapConstellationType(GnssConstellationType_2_0 constellation);
+
+    static bool isAutomotiveDevice();
 };
 
 }  // namespace common
diff --git a/graphics/composer/2.1/default/Android.bp b/graphics/composer/2.1/default/Android.bp
index 533687b..a367457 100644
--- a/graphics/composer/2.1/default/Android.bp
+++ b/graphics/composer/2.1/default/Android.bp
@@ -1,31 +1,3 @@
-cc_library_shared {
-    name: "android.hardware.graphics.composer@2.1-impl",
-    defaults: ["hidl_defaults"],
-    vendor: true,
-    relative_install_path: "hw",
-    srcs: ["passthrough.cpp"],
-    header_libs: [
-        "android.hardware.graphics.composer@2.1-passthrough",
-    ],
-    shared_libs: [
-        "android.hardware.graphics.composer@2.1",
-        "android.hardware.graphics.composer@2.1-resources",
-        "libbase",
-        "libcutils",
-        "libfmq",
-        "libhardware",
-        "libhidlbase",
-        "liblog",
-        "libsync",
-        "libutils",
-        "libhwc2on1adapter",
-        "libhwc2onfbadapter",
-    ],
-    cflags: [
-        "-DLOG_TAG=\"ComposerHal\""
-    ],
-}
-
 cc_binary {
     name: "android.hardware.graphics.composer@2.1-service",
     defaults: ["hidl_defaults"],
@@ -33,10 +5,20 @@
     relative_install_path: "hw",
     srcs: ["service.cpp"],
     init_rc: ["android.hardware.graphics.composer@2.1-service.rc"],
+    header_libs: [
+        "android.hardware.graphics.composer@2.1-passthrough",
+    ],
     shared_libs: [
         "android.hardware.graphics.composer@2.1",
+        "android.hardware.graphics.composer@2.1-resources",
+        "libbase",
         "libbinder",
+        "libcutils",
+        "libfmq",
+        "libhardware",
         "libhidlbase",
+        "libhwc2on1adapter",
+        "libhwc2onfbadapter",
         "liblog",
         "libsync",
         "libutils",
diff --git a/graphics/composer/2.1/default/passthrough.cpp b/graphics/composer/2.1/default/passthrough.cpp
deleted file mode 100644
index ef7ed7c..0000000
--- a/graphics/composer/2.1/default/passthrough.cpp
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <android/hardware/graphics/composer/2.1/IComposer.h>
-#include <composer-passthrough/2.1/HwcLoader.h>
-
-using android::hardware::graphics::composer::V2_1::IComposer;
-using android::hardware::graphics::composer::V2_1::passthrough::HwcLoader;
-
-extern "C" IComposer* HIDL_FETCH_IComposer(const char* /* name */) {
-    return HwcLoader::load();
-}
diff --git a/graphics/composer/2.1/default/service.cpp b/graphics/composer/2.1/default/service.cpp
index 82a33f6..1276d2d 100644
--- a/graphics/composer/2.1/default/service.cpp
+++ b/graphics/composer/2.1/default/service.cpp
@@ -21,10 +21,11 @@
 #include <android/hardware/graphics/composer/2.1/IComposer.h>
 
 #include <binder/ProcessState.h>
+#include <composer-passthrough/2.1/HwcLoader.h>
 #include <hidl/LegacySupport.h>
 
 using android::hardware::graphics::composer::V2_1::IComposer;
-using android::hardware::defaultPassthroughServiceImplementation;
+using android::hardware::graphics::composer::V2_1::passthrough::HwcLoader;
 
 int main() {
     // the conventional HAL might start binder services
@@ -40,5 +41,19 @@
         ALOGE("Couldn't set SCHED_FIFO: %d", errno);
     }
 
-    return defaultPassthroughServiceImplementation<IComposer>(4);
+    android::hardware::configureRpcThreadpool(4, true /* will join */);
+
+    android::sp<IComposer> composer = HwcLoader::load();
+    if (composer == nullptr) {
+        return 1;
+    }
+    if (composer->registerAsService() != android::NO_ERROR) {
+        ALOGE("failed to register service");
+        return 1;
+    }
+
+    android::hardware::joinRpcThreadpool();
+
+    ALOGE("service is terminating");
+    return 1;
 }
diff --git a/graphics/composer/2.1/utils/resources/include/composer-resources/2.1/ComposerResources.h b/graphics/composer/2.1/utils/resources/include/composer-resources/2.1/ComposerResources.h
index 3738278..df5513e 100644
--- a/graphics/composer/2.1/utils/resources/include/composer-resources/2.1/ComposerResources.h
+++ b/graphics/composer/2.1/utils/resources/include/composer-resources/2.1/ComposerResources.h
@@ -177,7 +177,8 @@
     bool mustValidateDisplay(Display display);
 
     // When a buffer in the cache is replaced by a new one, we must keep it
-    // alive until it has been replaced in ComposerHal.
+    // alive until it has been replaced in ComposerHal because it is still using
+    // the old buffer.
     class ReplacedHandle {
       public:
         explicit ReplacedHandle(bool isBuffer) : mIsBuffer(isBuffer) {}
diff --git a/health/1.0/default/android.hardware.health@1.0-service.rc b/health/1.0/default/android.hardware.health@1.0-service.rc
index 405784f..569dc88 100644
--- a/health/1.0/default/android.hardware.health@1.0-service.rc
+++ b/health/1.0/default/android.hardware.health@1.0-service.rc
@@ -2,4 +2,4 @@
     class hal
     user system
     group system
-    capabilities WAKE_ALARM
+    capabilities WAKE_ALARM BLOCK_SUSPEND
diff --git a/health/2.1/default/android.hardware.health@2.1-service.rc b/health/2.1/default/android.hardware.health@2.1-service.rc
index b6d9e3b..8728257 100644
--- a/health/2.1/default/android.hardware.health@2.1-service.rc
+++ b/health/2.1/default/android.hardware.health@2.1-service.rc
@@ -2,5 +2,5 @@
     class hal charger
     user system
     group system
-    capabilities WAKE_ALARM
+    capabilities WAKE_ALARM BLOCK_SUSPEND
     file /dev/kmsg w
diff --git a/health/2.1/types.hal b/health/2.1/types.hal
index d775491..6d7b661 100644
--- a/health/2.1/types.hal
+++ b/health/2.1/types.hal
@@ -98,9 +98,8 @@
     /**
      * Estimated battery full charge design capacity (in microamp hours, uAh).
      * Value must be 0 if unknown.
-     * Value must be positive if known.
-     * Value must be greater than 100 000 uAh.
-     * Value must be less than 100 000 000 uAh.
+     * Value must be greater than 100 000 uAh if known.
+     * Value must be less than 100 000 000 uAh if known.
      */
     int32_t batteryFullChargeDesignCapacityUah;
 };
diff --git a/health/2.1/vts/functional/VtsHalHealthV2_1TargetTest.cpp b/health/2.1/vts/functional/VtsHalHealthV2_1TargetTest.cpp
index d0b0d60..4ae443a 100644
--- a/health/2.1/vts/functional/VtsHalHealthV2_1TargetTest.cpp
+++ b/health/2.1/vts/functional/VtsHalHealthV2_1TargetTest.cpp
@@ -235,14 +235,15 @@
         EXPECT_TRUE(IsEnum(value.batteryCapacityLevel)) << " BatteryCapacityLevel";
         EXPECT_GE(value.batteryChargeTimeToFullNowSeconds, -1);
 
-        EXPECT_GE(value.batteryFullChargeDesignCapacityUah, 0)
-                << "batteryFullChargeDesignCapacityUah should not be negative";
+        if (value.batteryFullChargeDesignCapacityUah != 0) {
+            EXPECT_GT((long)value.batteryFullChargeDesignCapacityUah, FULL_CHARGE_DESIGN_CAP_MIN)
+                    << "batteryFullChargeDesignCapacityUah should be greater than 100 mAh, or 0 if "
+                       "unknown";
 
-        EXPECT_GT((long)value.batteryFullChargeDesignCapacityUah, FULL_CHARGE_DESIGN_CAP_MIN)
-                << "batteryFullChargeDesignCapacityUah should be greater than 100 mAh";
-
-        EXPECT_LT((long)value.batteryFullChargeDesignCapacityUah, FULL_CHARGE_DESIGN_CAP_MAX)
-                << "batteryFullChargeDesignCapacityUah should be less than 100,000 mAh";
+            EXPECT_LT((long)value.batteryFullChargeDesignCapacityUah, FULL_CHARGE_DESIGN_CAP_MAX)
+                    << "batteryFullChargeDesignCapacityUah should be less than 100,000 mAh, or 0 "
+                       "if unknown";
+        }
     })));
 }
 
diff --git a/powerstats/aidl/vts/Android.bp b/neuralnetworks/1.0/utils/Android.bp
similarity index 61%
copy from powerstats/aidl/vts/Android.bp
copy to neuralnetworks/1.0/utils/Android.bp
index c61022e..57a052f 100644
--- a/powerstats/aidl/vts/Android.bp
+++ b/neuralnetworks/1.0/utils/Android.bp
@@ -1,3 +1,4 @@
+//
 // Copyright (C) 2020 The Android Open Source Project
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
@@ -11,22 +12,22 @@
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 // See the License for the specific language governing permissions and
 // limitations under the License.
+//
 
-cc_test {
-    name: "VtsHalPowerStatsTargetTest",
-    defaults: [
-        "VtsHalTargetTestDefaults",
-        "use_libaidlvintf_gtest_helper_static",
-    ],
-    srcs: ["VtsHalPowerStatsTargetTest.cpp"],
-    shared_libs: [
-        "libbinder_ndk",
-    ],
+cc_library_static {
+    name: "neuralnetworks_utils_hal_1_0",
+    defaults: ["neuralnetworks_utils_defaults"],
+    srcs: ["src/*"],
+    local_include_dirs: ["include/nnapi/hal/1.0/"],
+    export_include_dirs: ["include"],
     static_libs: [
-        "android.hardware.powerstats-ndk_platform",
+        "neuralnetworks_types",
+        "neuralnetworks_utils_hal_common",
     ],
-    test_suites: [
-        "general-tests",
-        "vts",
+    shared_libs: [
+        "android.hardware.neuralnetworks@1.0",
+    ],
+    export_static_lib_headers: [
+        "neuralnetworks_utils_hal_common",
     ],
 }
diff --git a/neuralnetworks/1.0/utils/OWNERS b/neuralnetworks/1.0/utils/OWNERS
new file mode 100644
index 0000000..e4feee3
--- /dev/null
+++ b/neuralnetworks/1.0/utils/OWNERS
@@ -0,0 +1,11 @@
+# Neuralnetworks team
+butlermichael@google.com
+dgross@google.com
+galarragas@google.com
+jeanluc@google.com
+levp@google.com
+miaowang@google.com
+pszczepaniak@google.com
+slavash@google.com
+vddang@google.com
+xusongw@google.com
diff --git a/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Conversions.h b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Conversions.h
new file mode 100644
index 0000000..8ad98cb
--- /dev/null
+++ b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Conversions.h
@@ -0,0 +1,66 @@
+/*
+ * 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_1_0_CONVERSIONS_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_0_CONVERSIONS_H
+
+#include <android/hardware/neuralnetworks/1.0/types.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+#include <nnapi/hal/CommonUtils.h>
+
+namespace android::nn {
+
+Result<OperandType> convert(const hal::V1_0::OperandType& operandType);
+Result<OperationType> convert(const hal::V1_0::OperationType& operationType);
+Result<Operand::LifeTime> convert(const hal::V1_0::OperandLifeTime& lifetime);
+Result<DeviceStatus> convert(const hal::V1_0::DeviceStatus& deviceStatus);
+Result<Capabilities::PerformanceInfo> convert(const hal::V1_0::PerformanceInfo& performanceInfo);
+Result<Capabilities> convert(const hal::V1_0::Capabilities& capabilities);
+Result<DataLocation> convert(const hal::V1_0::DataLocation& location);
+Result<Operand> convert(const hal::V1_0::Operand& operand);
+Result<Operation> convert(const hal::V1_0::Operation& operation);
+Result<Model::OperandValues> convert(const hardware::hidl_vec<uint8_t>& operandValues);
+Result<Memory> convert(const hardware::hidl_memory& memory);
+Result<Model> convert(const hal::V1_0::Model& model);
+Result<Request::Argument> convert(const hal::V1_0::RequestArgument& requestArgument);
+Result<Request> convert(const hal::V1_0::Request& request);
+Result<ErrorStatus> convert(const hal::V1_0::ErrorStatus& status);
+
+}  // namespace android::nn
+
+namespace android::hardware::neuralnetworks::V1_0::utils {
+
+nn::Result<OperandType> convert(const nn::OperandType& operandType);
+nn::Result<OperationType> convert(const nn::OperationType& operationType);
+nn::Result<OperandLifeTime> convert(const nn::Operand::LifeTime& lifetime);
+nn::Result<DeviceStatus> convert(const nn::DeviceStatus& deviceStatus);
+nn::Result<PerformanceInfo> convert(const nn::Capabilities::PerformanceInfo& performanceInfo);
+nn::Result<Capabilities> convert(const nn::Capabilities& capabilities);
+nn::Result<DataLocation> convert(const nn::DataLocation& location);
+nn::Result<Operand> convert(const nn::Operand& operand);
+nn::Result<Operation> convert(const nn::Operation& operation);
+nn::Result<hidl_vec<uint8_t>> convert(const nn::Model::OperandValues& operandValues);
+nn::Result<hidl_memory> convert(const nn::Memory& memory);
+nn::Result<Model> convert(const nn::Model& model);
+nn::Result<RequestArgument> convert(const nn::Request::Argument& requestArgument);
+nn::Result<hidl_memory> convert(const nn::Request::MemoryPool& memoryPool);
+nn::Result<Request> convert(const nn::Request& request);
+nn::Result<ErrorStatus> convert(const nn::ErrorStatus& status);
+
+}  // namespace android::hardware::neuralnetworks::V1_0::utils
+
+#endif  // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_0_CONVERSIONS_H
diff --git a/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Utils.h b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Utils.h
new file mode 100644
index 0000000..ec8da06
--- /dev/null
+++ b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Utils.h
@@ -0,0 +1,63 @@
+/*
+ * 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_1_0_UTILS_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_0_UTILS_H
+
+#include "nnapi/hal/1.0/Conversions.h"
+
+#include <android-base/logging.h>
+#include <android/hardware/neuralnetworks/1.0/types.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+#include <nnapi/Validation.h>
+
+namespace android::hardware::neuralnetworks::V1_0::utils {
+
+constexpr auto kVersion = nn::Version::ANDROID_OC_MR1;
+
+template <typename Type>
+nn::Result<void> validate(const Type& halObject) {
+    const auto canonical = NN_TRY(nn::convert(halObject));
+    const auto version = NN_TRY(nn::validate(canonical));
+    if (version > utils::kVersion) {
+        return NN_ERROR() << "";
+    }
+    return {};
+}
+
+template <typename Type>
+bool valid(const Type& halObject) {
+    const auto result = utils::validate(halObject);
+    if (!result.has_value()) {
+        LOG(ERROR) << result.error();
+    }
+    return result.has_value();
+}
+
+template <typename Type>
+decltype(nn::convert(std::declval<Type>())) validatedConvertToCanonical(const Type& halObject) {
+    auto canonical = NN_TRY(nn::convert(halObject));
+    const auto version = NN_TRY(nn::validate(canonical));
+    if (version > utils::kVersion) {
+        return NN_ERROR() << "";
+    }
+    return canonical;
+}
+
+}  // namespace android::hardware::neuralnetworks::V1_0::utils
+
+#endif  // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_0_UTILS_H
diff --git a/neuralnetworks/1.0/utils/src/Assertions.cpp b/neuralnetworks/1.0/utils/src/Assertions.cpp
new file mode 100644
index 0000000..0f00951
--- /dev/null
+++ b/neuralnetworks/1.0/utils/src/Assertions.cpp
@@ -0,0 +1,122 @@
+/*
+ * 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 <android/hardware/neuralnetworks/1.0/types.h>
+#include <nnapi/OperandTypes.h>
+#include <nnapi/OperationTypes.h>
+#include <nnapi/Types.h>
+#include <type_traits>
+
+namespace {
+
+#define COMPARE_ENUMS_TYPES(lhsType, rhsType)                                                   \
+    static_assert(                                                                              \
+            std::is_same_v<                                                                     \
+                    std::underlying_type_t<::android::hardware::neuralnetworks::V1_0::lhsType>, \
+                    std::underlying_type_t<::android::nn::rhsType>>,                            \
+            "::android::hardware::neuralnetworks::V1_0::" #lhsType                              \
+            " does not have the same underlying type as ::android::nn::" #rhsType)
+
+COMPARE_ENUMS_TYPES(OperandType, OperandType);
+COMPARE_ENUMS_TYPES(OperationType, OperationType);
+COMPARE_ENUMS_TYPES(ErrorStatus, ErrorStatus);
+COMPARE_ENUMS_TYPES(OperandLifeTime, Operand::LifeTime);
+
+#undef COMPARE_ENUMS_TYPES
+
+#define COMPARE_ENUMS_FULL(lhsSymbol, rhsSymbol, lhsType, rhsType)                               \
+    static_assert(                                                                               \
+            static_cast<                                                                         \
+                    std::underlying_type_t<::android::hardware::neuralnetworks::V1_0::lhsType>>( \
+                    ::android::hardware::neuralnetworks::V1_0::lhsType::lhsSymbol) ==            \
+                    static_cast<std::underlying_type_t<::android::nn::rhsType>>(                 \
+                            ::android::nn::rhsType::rhsSymbol),                                  \
+            "::android::hardware::neuralnetworks::V1_0::" #lhsType "::" #lhsSymbol               \
+            " does not match ::android::nn::" #rhsType "::" #rhsSymbol)
+
+#define COMPARE_ENUMS(symbol) COMPARE_ENUMS_FULL(symbol, symbol, OperandType, OperandType)
+
+COMPARE_ENUMS(FLOAT32);
+COMPARE_ENUMS(INT32);
+COMPARE_ENUMS(UINT32);
+COMPARE_ENUMS(TENSOR_FLOAT32);
+COMPARE_ENUMS(TENSOR_INT32);
+COMPARE_ENUMS(TENSOR_QUANT8_ASYMM);
+COMPARE_ENUMS(OEM);
+COMPARE_ENUMS(TENSOR_OEM_BYTE);
+
+#undef COMPARE_ENUMS
+
+#define COMPARE_ENUMS(symbol) COMPARE_ENUMS_FULL(symbol, symbol, OperationType, OperationType)
+
+COMPARE_ENUMS(ADD);
+COMPARE_ENUMS(AVERAGE_POOL_2D);
+COMPARE_ENUMS(CONCATENATION);
+COMPARE_ENUMS(CONV_2D);
+COMPARE_ENUMS(DEPTHWISE_CONV_2D);
+COMPARE_ENUMS(DEPTH_TO_SPACE);
+COMPARE_ENUMS(DEQUANTIZE);
+COMPARE_ENUMS(EMBEDDING_LOOKUP);
+COMPARE_ENUMS(FLOOR);
+COMPARE_ENUMS(FULLY_CONNECTED);
+COMPARE_ENUMS(HASHTABLE_LOOKUP);
+COMPARE_ENUMS(L2_NORMALIZATION);
+COMPARE_ENUMS(L2_POOL_2D);
+COMPARE_ENUMS(LOCAL_RESPONSE_NORMALIZATION);
+COMPARE_ENUMS(LOGISTIC);
+COMPARE_ENUMS(LSH_PROJECTION);
+COMPARE_ENUMS(LSTM);
+COMPARE_ENUMS(MAX_POOL_2D);
+COMPARE_ENUMS(MUL);
+COMPARE_ENUMS(RELU);
+COMPARE_ENUMS(RELU1);
+COMPARE_ENUMS(RELU6);
+COMPARE_ENUMS(RESHAPE);
+COMPARE_ENUMS(RESIZE_BILINEAR);
+COMPARE_ENUMS(RNN);
+COMPARE_ENUMS(SOFTMAX);
+COMPARE_ENUMS(SPACE_TO_DEPTH);
+COMPARE_ENUMS(SVDF);
+COMPARE_ENUMS(TANH);
+COMPARE_ENUMS(OEM_OPERATION);
+
+#undef COMPARE_ENUMS
+
+#define COMPARE_ENUMS(symbol) COMPARE_ENUMS_FULL(symbol, symbol, ErrorStatus, ErrorStatus)
+
+COMPARE_ENUMS(NONE);
+COMPARE_ENUMS(DEVICE_UNAVAILABLE);
+COMPARE_ENUMS(GENERAL_FAILURE);
+COMPARE_ENUMS(OUTPUT_INSUFFICIENT_SIZE);
+COMPARE_ENUMS(INVALID_ARGUMENT);
+
+#undef COMPARE_ENUMS
+
+#define COMPARE_ENUMS(lhsSymbol, rhsSymbol) \
+    COMPARE_ENUMS_FULL(lhsSymbol, rhsSymbol, OperandLifeTime, Operand::LifeTime)
+
+COMPARE_ENUMS(TEMPORARY_VARIABLE, TEMPORARY_VARIABLE);
+COMPARE_ENUMS(MODEL_INPUT, SUBGRAPH_INPUT);
+COMPARE_ENUMS(MODEL_OUTPUT, SUBGRAPH_OUTPUT);
+COMPARE_ENUMS(CONSTANT_COPY, CONSTANT_COPY);
+COMPARE_ENUMS(CONSTANT_REFERENCE, CONSTANT_REFERENCE);
+COMPARE_ENUMS(NO_VALUE, NO_VALUE);
+
+#undef COMPARE_ENUMS
+
+#undef COMPARE_ENUMS_FULL
+
+}  // anonymous namespace
diff --git a/neuralnetworks/1.0/utils/src/Conversions.cpp b/neuralnetworks/1.0/utils/src/Conversions.cpp
new file mode 100644
index 0000000..4a58f3b
--- /dev/null
+++ b/neuralnetworks/1.0/utils/src/Conversions.cpp
@@ -0,0 +1,361 @@
+/*
+ * 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 "Conversions.h"
+
+#include <android-base/logging.h>
+#include <android/hardware/neuralnetworks/1.0/types.h>
+#include <nnapi/OperandTypes.h>
+#include <nnapi/OperationTypes.h>
+#include <nnapi/Result.h>
+#include <nnapi/SharedMemory.h>
+#include <nnapi/Types.h>
+#include <nnapi/hal/CommonUtils.h>
+
+#include <algorithm>
+#include <functional>
+#include <iterator>
+#include <memory>
+#include <type_traits>
+#include <utility>
+#include <variant>
+
+namespace {
+
+template <typename Type>
+constexpr std::underlying_type_t<Type> underlyingType(Type value) {
+    return static_cast<std::underlying_type_t<Type>>(value);
+}
+
+}  // namespace
+
+namespace android::nn {
+namespace {
+
+using hardware::hidl_memory;
+using hardware::hidl_vec;
+
+template <typename Input>
+using ConvertOutput = std::decay_t<decltype(convert(std::declval<Input>()).value())>;
+
+template <typename Type>
+Result<std::vector<ConvertOutput<Type>>> convert(const hidl_vec<Type>& arguments) {
+    std::vector<ConvertOutput<Type>> canonical;
+    canonical.reserve(arguments.size());
+    for (const auto& argument : arguments) {
+        canonical.push_back(NN_TRY(nn::convert(argument)));
+    }
+    return canonical;
+}
+
+}  // anonymous namespace
+
+Result<OperandType> convert(const hal::V1_0::OperandType& operandType) {
+    return static_cast<OperandType>(operandType);
+}
+
+Result<OperationType> convert(const hal::V1_0::OperationType& operationType) {
+    return static_cast<OperationType>(operationType);
+}
+
+Result<Operand::LifeTime> convert(const hal::V1_0::OperandLifeTime& lifetime) {
+    return static_cast<Operand::LifeTime>(lifetime);
+}
+
+Result<DeviceStatus> convert(const hal::V1_0::DeviceStatus& deviceStatus) {
+    return static_cast<DeviceStatus>(deviceStatus);
+}
+
+Result<Capabilities::PerformanceInfo> convert(const hal::V1_0::PerformanceInfo& performanceInfo) {
+    return Capabilities::PerformanceInfo{
+            .execTime = performanceInfo.execTime,
+            .powerUsage = performanceInfo.powerUsage,
+    };
+}
+
+Result<Capabilities> convert(const hal::V1_0::Capabilities& capabilities) {
+    const auto quantized8Performance = NN_TRY(convert(capabilities.quantized8Performance));
+    const auto float32Performance = NN_TRY(convert(capabilities.float32Performance));
+
+    auto table = hal::utils::makeQuantized8PerformanceConsistentWithP(float32Performance,
+                                                                      quantized8Performance);
+
+    return Capabilities{
+            .relaxedFloat32toFloat16PerformanceScalar = float32Performance,
+            .relaxedFloat32toFloat16PerformanceTensor = float32Performance,
+            .operandPerformance = std::move(table),
+    };
+}
+
+Result<DataLocation> convert(const hal::V1_0::DataLocation& location) {
+    return DataLocation{
+            .poolIndex = location.poolIndex,
+            .offset = location.offset,
+            .length = location.length,
+    };
+}
+
+Result<Operand> convert(const hal::V1_0::Operand& operand) {
+    return Operand{
+            .type = NN_TRY(convert(operand.type)),
+            .dimensions = operand.dimensions,
+            .scale = operand.scale,
+            .zeroPoint = operand.zeroPoint,
+            .lifetime = NN_TRY(convert(operand.lifetime)),
+            .location = NN_TRY(convert(operand.location)),
+    };
+}
+
+Result<Operation> convert(const hal::V1_0::Operation& operation) {
+    return Operation{
+            .type = NN_TRY(convert(operation.type)),
+            .inputs = operation.inputs,
+            .outputs = operation.outputs,
+    };
+}
+
+Result<Model::OperandValues> convert(const hidl_vec<uint8_t>& operandValues) {
+    return Model::OperandValues(operandValues.data(), operandValues.size());
+}
+
+Result<Memory> convert(const hidl_memory& memory) {
+    return createSharedMemoryFromHidlMemory(memory);
+}
+
+Result<Model> convert(const hal::V1_0::Model& model) {
+    auto operations = NN_TRY(convert(model.operations));
+
+    // Verify number of consumers.
+    const auto numberOfConsumers =
+            hal::utils::countNumberOfConsumers(model.operands.size(), operations);
+    CHECK(model.operands.size() == numberOfConsumers.size());
+    for (size_t i = 0; i < model.operands.size(); ++i) {
+        if (model.operands[i].numberOfConsumers != numberOfConsumers[i]) {
+            return NN_ERROR() << "Invalid numberOfConsumers for operand " << i << ", expected "
+                              << numberOfConsumers[i] << " but found "
+                              << model.operands[i].numberOfConsumers;
+        }
+    }
+
+    auto main = Model::Subgraph{
+            .operands = NN_TRY(convert(model.operands)),
+            .operations = std::move(operations),
+            .inputIndexes = model.inputIndexes,
+            .outputIndexes = model.outputIndexes,
+    };
+
+    return Model{
+            .main = std::move(main),
+            .operandValues = NN_TRY(convert(model.operandValues)),
+            .pools = NN_TRY(convert(model.pools)),
+    };
+}
+
+Result<Request::Argument> convert(const hal::V1_0::RequestArgument& argument) {
+    const auto lifetime = argument.hasNoValue ? Request::Argument::LifeTime::NO_VALUE
+                                              : Request::Argument::LifeTime::POOL;
+    return Request::Argument{
+            .lifetime = lifetime,
+            .location = NN_TRY(convert(argument.location)),
+            .dimensions = argument.dimensions,
+    };
+}
+
+Result<Request> convert(const hal::V1_0::Request& request) {
+    auto memories = NN_TRY(convert(request.pools));
+    std::vector<Request::MemoryPool> pools;
+    pools.reserve(memories.size());
+    std::move(memories.begin(), memories.end(), std::back_inserter(pools));
+
+    return Request{
+            .inputs = NN_TRY(convert(request.inputs)),
+            .outputs = NN_TRY(convert(request.outputs)),
+            .pools = std::move(pools),
+    };
+}
+
+Result<ErrorStatus> convert(const hal::V1_0::ErrorStatus& status) {
+    switch (status) {
+        case hal::V1_0::ErrorStatus::NONE:
+        case hal::V1_0::ErrorStatus::DEVICE_UNAVAILABLE:
+        case hal::V1_0::ErrorStatus::GENERAL_FAILURE:
+        case hal::V1_0::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE:
+        case hal::V1_0::ErrorStatus::INVALID_ARGUMENT:
+            return static_cast<ErrorStatus>(status);
+    }
+    return NN_ERROR() << "Invalid ErrorStatus " << underlyingType(status);
+}
+
+}  // namespace android::nn
+
+namespace android::hardware::neuralnetworks::V1_0::utils {
+namespace {
+
+template <typename Input>
+using ConvertOutput = std::decay_t<decltype(convert(std::declval<Input>()).value())>;
+
+template <typename Type>
+nn::Result<hidl_vec<ConvertOutput<Type>>> convert(const std::vector<Type>& arguments) {
+    hidl_vec<ConvertOutput<Type>> halObject(arguments.size());
+    for (size_t i = 0; i < arguments.size(); ++i) {
+        halObject[i] = NN_TRY(utils::convert(arguments[i]));
+    }
+    return halObject;
+}
+
+}  // anonymous namespace
+
+nn::Result<OperandType> convert(const nn::OperandType& operandType) {
+    return static_cast<OperandType>(operandType);
+}
+
+nn::Result<OperationType> convert(const nn::OperationType& operationType) {
+    return static_cast<OperationType>(operationType);
+}
+
+nn::Result<OperandLifeTime> convert(const nn::Operand::LifeTime& lifetime) {
+    if (lifetime == nn::Operand::LifeTime::POINTER) {
+        return NN_ERROR() << "Model cannot be converted because it contains pointer-based memory";
+    }
+    return static_cast<OperandLifeTime>(lifetime);
+}
+
+nn::Result<DeviceStatus> convert(const nn::DeviceStatus& deviceStatus) {
+    return static_cast<DeviceStatus>(deviceStatus);
+}
+
+nn::Result<PerformanceInfo> convert(const nn::Capabilities::PerformanceInfo& performanceInfo) {
+    return PerformanceInfo{
+            .execTime = performanceInfo.execTime,
+            .powerUsage = performanceInfo.powerUsage,
+    };
+}
+
+nn::Result<Capabilities> convert(const nn::Capabilities& capabilities) {
+    return Capabilities{
+            .float32Performance = NN_TRY(convert(
+                    capabilities.operandPerformance.lookup(nn::OperandType::TENSOR_FLOAT32))),
+            .quantized8Performance = NN_TRY(convert(
+                    capabilities.operandPerformance.lookup(nn::OperandType::TENSOR_QUANT8_ASYMM))),
+    };
+}
+
+nn::Result<DataLocation> convert(const nn::DataLocation& location) {
+    return DataLocation{
+            .poolIndex = location.poolIndex,
+            .offset = location.offset,
+            .length = location.length,
+    };
+}
+
+nn::Result<Operand> convert(const nn::Operand& operand) {
+    return Operand{
+            .type = NN_TRY(convert(operand.type)),
+            .dimensions = operand.dimensions,
+            .numberOfConsumers = 0,
+            .scale = operand.scale,
+            .zeroPoint = operand.zeroPoint,
+            .lifetime = NN_TRY(convert(operand.lifetime)),
+            .location = NN_TRY(convert(operand.location)),
+    };
+}
+
+nn::Result<Operation> convert(const nn::Operation& operation) {
+    return Operation{
+            .type = NN_TRY(convert(operation.type)),
+            .inputs = operation.inputs,
+            .outputs = operation.outputs,
+    };
+}
+
+nn::Result<hidl_vec<uint8_t>> convert(const nn::Model::OperandValues& operandValues) {
+    return hidl_vec<uint8_t>(operandValues.data(), operandValues.data() + operandValues.size());
+}
+
+nn::Result<hidl_memory> convert(const nn::Memory& memory) {
+    const auto hidlMemory = hidl_memory(memory.name, memory.handle->handle(), memory.size);
+    // Copy memory to force the native_handle_t to be copied.
+    auto copiedMemory = hidlMemory;
+    return copiedMemory;
+}
+
+nn::Result<Model> convert(const nn::Model& model) {
+    if (!hal::utils::hasNoPointerData(model)) {
+        return NN_ERROR() << "Mdoel cannot be converted because it contains pointer-based memory";
+    }
+
+    auto operands = NN_TRY(convert(model.main.operands));
+
+    // Update number of consumers.
+    const auto numberOfConsumers =
+            hal::utils::countNumberOfConsumers(operands.size(), model.main.operations);
+    CHECK(operands.size() == numberOfConsumers.size());
+    for (size_t i = 0; i < operands.size(); ++i) {
+        operands[i].numberOfConsumers = numberOfConsumers[i];
+    }
+
+    return Model{
+            .operands = std::move(operands),
+            .operations = NN_TRY(convert(model.main.operations)),
+            .inputIndexes = model.main.inputIndexes,
+            .outputIndexes = model.main.outputIndexes,
+            .operandValues = NN_TRY(convert(model.operandValues)),
+            .pools = NN_TRY(convert(model.pools)),
+    };
+}
+
+nn::Result<RequestArgument> convert(const nn::Request::Argument& requestArgument) {
+    if (requestArgument.lifetime == nn::Request::Argument::LifeTime::POINTER) {
+        return NN_ERROR() << "Request cannot be converted because it contains pointer-based memory";
+    }
+    const bool hasNoValue = requestArgument.lifetime == nn::Request::Argument::LifeTime::NO_VALUE;
+    return RequestArgument{
+            .hasNoValue = hasNoValue,
+            .location = NN_TRY(convert(requestArgument.location)),
+            .dimensions = requestArgument.dimensions,
+    };
+}
+
+nn::Result<hidl_memory> convert(const nn::Request::MemoryPool& memoryPool) {
+    return convert(std::get<nn::Memory>(memoryPool));
+}
+
+nn::Result<Request> convert(const nn::Request& request) {
+    if (!hal::utils::hasNoPointerData(request)) {
+        return NN_ERROR() << "Request cannot be converted because it contains pointer-based memory";
+    }
+
+    return Request{
+            .inputs = NN_TRY(convert(request.inputs)),
+            .outputs = NN_TRY(convert(request.outputs)),
+            .pools = NN_TRY(convert(request.pools)),
+    };
+}
+
+nn::Result<ErrorStatus> convert(const nn::ErrorStatus& status) {
+    switch (status) {
+        case nn::ErrorStatus::NONE:
+        case nn::ErrorStatus::DEVICE_UNAVAILABLE:
+        case nn::ErrorStatus::GENERAL_FAILURE:
+        case nn::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE:
+        case nn::ErrorStatus::INVALID_ARGUMENT:
+            return static_cast<ErrorStatus>(status);
+        default:
+            return ErrorStatus::GENERAL_FAILURE;
+    }
+}
+
+}  // namespace android::hardware::neuralnetworks::V1_0::utils
diff --git a/neuralnetworks/1.1/utils/Android.bp b/neuralnetworks/1.1/utils/Android.bp
new file mode 100644
index 0000000..85a32c5
--- /dev/null
+++ b/neuralnetworks/1.1/utils/Android.bp
@@ -0,0 +1,35 @@
+//
+// 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_library_static {
+    name: "neuralnetworks_utils_hal_1_1",
+    defaults: ["neuralnetworks_utils_defaults"],
+    srcs: ["src/*"],
+    local_include_dirs: ["include/nnapi/hal/1.1/"],
+    export_include_dirs: ["include"],
+    static_libs: [
+        "neuralnetworks_types",
+        "neuralnetworks_utils_hal_common",
+        "neuralnetworks_utils_hal_1_0",
+    ],
+    shared_libs: [
+        "android.hardware.neuralnetworks@1.0",
+        "android.hardware.neuralnetworks@1.1",
+    ],
+    export_static_lib_headers: [
+        "neuralnetworks_utils_hal_common",
+    ],
+}
diff --git a/neuralnetworks/1.1/utils/OWNERS b/neuralnetworks/1.1/utils/OWNERS
new file mode 100644
index 0000000..e4feee3
--- /dev/null
+++ b/neuralnetworks/1.1/utils/OWNERS
@@ -0,0 +1,11 @@
+# Neuralnetworks team
+butlermichael@google.com
+dgross@google.com
+galarragas@google.com
+jeanluc@google.com
+levp@google.com
+miaowang@google.com
+pszczepaniak@google.com
+slavash@google.com
+vddang@google.com
+xusongw@google.com
diff --git a/neuralnetworks/1.1/utils/include/nnapi/hal/1.1/Conversions.h b/neuralnetworks/1.1/utils/include/nnapi/hal/1.1/Conversions.h
new file mode 100644
index 0000000..d0c5397
--- /dev/null
+++ b/neuralnetworks/1.1/utils/include/nnapi/hal/1.1/Conversions.h
@@ -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.
+ */
+
+#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_1_CONVERSIONS_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_1_CONVERSIONS_H
+
+#include <android/hardware/neuralnetworks/1.1/types.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+#include <nnapi/hal/CommonUtils.h>
+
+namespace android::nn {
+
+Result<OperationType> convert(const hal::V1_1::OperationType& operationType);
+Result<Capabilities> convert(const hal::V1_1::Capabilities& capabilities);
+Result<Operation> convert(const hal::V1_1::Operation& operation);
+Result<Model> convert(const hal::V1_1::Model& model);
+Result<ExecutionPreference> convert(const hal::V1_1::ExecutionPreference& executionPreference);
+
+}  // namespace android::nn
+
+namespace android::hardware::neuralnetworks::V1_1::utils {
+
+nn::Result<OperationType> convert(const nn::OperationType& operationType);
+nn::Result<Capabilities> convert(const nn::Capabilities& capabilities);
+nn::Result<Operation> convert(const nn::Operation& operation);
+nn::Result<Model> convert(const nn::Model& model);
+nn::Result<ExecutionPreference> convert(const nn::ExecutionPreference& executionPreference);
+
+}  // namespace android::hardware::neuralnetworks::V1_1::utils
+
+#endif  // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_1_CONVERSIONS_H
diff --git a/neuralnetworks/1.1/utils/include/nnapi/hal/1.1/Utils.h b/neuralnetworks/1.1/utils/include/nnapi/hal/1.1/Utils.h
new file mode 100644
index 0000000..6f9aa60
--- /dev/null
+++ b/neuralnetworks/1.1/utils/include/nnapi/hal/1.1/Utils.h
@@ -0,0 +1,65 @@
+/*
+ * 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_1_1_UTILS_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_1_UTILS_H
+
+#include "nnapi/hal/1.1/Conversions.h"
+
+#include <android-base/logging.h>
+#include <android/hardware/neuralnetworks/1.1/types.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+#include <nnapi/Validation.h>
+#include <nnapi/hal/1.0/Conversions.h>
+
+namespace android::hardware::neuralnetworks::V1_1::utils {
+
+constexpr auto kDefaultExecutionPreference = ExecutionPreference::FAST_SINGLE_ANSWER;
+constexpr auto kVersion = nn::Version::ANDROID_P;
+
+template <typename Type>
+nn::Result<void> validate(const Type& halObject) {
+    const auto canonical = NN_TRY(nn::convert(halObject));
+    const auto version = NN_TRY(nn::validate(canonical));
+    if (version > utils::kVersion) {
+        return NN_ERROR() << "";
+    }
+    return {};
+}
+
+template <typename Type>
+bool valid(const Type& halObject) {
+    const auto result = utils::validate(halObject);
+    if (!result.has_value()) {
+        LOG(ERROR) << result.error();
+    }
+    return result.has_value();
+}
+
+template <typename Type>
+decltype(nn::convert(std::declval<Type>())) validatedConvertToCanonical(const Type& halObject) {
+    auto canonical = NN_TRY(nn::convert(halObject));
+    const auto version = NN_TRY(nn::validate(canonical));
+    if (version > utils::kVersion) {
+        return NN_ERROR() << "";
+    }
+    return canonical;
+}
+
+}  // namespace android::hardware::neuralnetworks::V1_1::utils
+
+#endif  // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_1_UTILS_H
diff --git a/neuralnetworks/1.1/utils/src/Assertions.cpp b/neuralnetworks/1.1/utils/src/Assertions.cpp
new file mode 100644
index 0000000..ba4a388
--- /dev/null
+++ b/neuralnetworks/1.1/utils/src/Assertions.cpp
@@ -0,0 +1,100 @@
+/*
+ * 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 <android/hardware/neuralnetworks/1.1/types.h>
+#include <nnapi/OperandTypes.h>
+#include <nnapi/OperationTypes.h>
+#include <nnapi/Types.h>
+#include <type_traits>
+
+namespace {
+
+#define COMPARE_ENUMS_TYPES(type)                                                                  \
+    static_assert(std::is_same_v<                                                                  \
+                          std::underlying_type_t<::android::hardware::neuralnetworks::V1_1::type>, \
+                          std::underlying_type_t<::android::nn::type>>,                            \
+                  "::android::hardware::neuralnetworks::V1_1::" #type                              \
+                  " does not have the same underlying type as ::android::nn::" #type)
+
+COMPARE_ENUMS_TYPES(OperationType);
+COMPARE_ENUMS_TYPES(ExecutionPreference);
+
+#undef COMPARE_ENUMS_TYPES
+
+#define COMPARE_ENUMS_FULL(symbol, type)                                                          \
+    static_assert(                                                                                \
+            static_cast<std::underlying_type_t<::android::hardware::neuralnetworks::V1_1::type>>( \
+                    ::android::hardware::neuralnetworks::V1_1::type::symbol) ==                   \
+                    static_cast<std::underlying_type_t<::android::nn::type>>(                     \
+                            ::android::nn::type::symbol),                                         \
+            "::android::hardware::neuralnetworks::V1_1::" #type "::" #symbol                      \
+            " does not match ::android::nn::" #type "::" #symbol)
+
+#define COMPARE_ENUMS(symbol) COMPARE_ENUMS_FULL(symbol, OperationType)
+
+COMPARE_ENUMS(ADD);
+COMPARE_ENUMS(AVERAGE_POOL_2D);
+COMPARE_ENUMS(CONCATENATION);
+COMPARE_ENUMS(CONV_2D);
+COMPARE_ENUMS(DEPTHWISE_CONV_2D);
+COMPARE_ENUMS(DEPTH_TO_SPACE);
+COMPARE_ENUMS(DEQUANTIZE);
+COMPARE_ENUMS(EMBEDDING_LOOKUP);
+COMPARE_ENUMS(FLOOR);
+COMPARE_ENUMS(FULLY_CONNECTED);
+COMPARE_ENUMS(HASHTABLE_LOOKUP);
+COMPARE_ENUMS(L2_NORMALIZATION);
+COMPARE_ENUMS(L2_POOL_2D);
+COMPARE_ENUMS(LOCAL_RESPONSE_NORMALIZATION);
+COMPARE_ENUMS(LOGISTIC);
+COMPARE_ENUMS(LSH_PROJECTION);
+COMPARE_ENUMS(LSTM);
+COMPARE_ENUMS(MAX_POOL_2D);
+COMPARE_ENUMS(MUL);
+COMPARE_ENUMS(RELU);
+COMPARE_ENUMS(RELU1);
+COMPARE_ENUMS(RELU6);
+COMPARE_ENUMS(RESHAPE);
+COMPARE_ENUMS(RESIZE_BILINEAR);
+COMPARE_ENUMS(RNN);
+COMPARE_ENUMS(SOFTMAX);
+COMPARE_ENUMS(SPACE_TO_DEPTH);
+COMPARE_ENUMS(SVDF);
+COMPARE_ENUMS(TANH);
+COMPARE_ENUMS(BATCH_TO_SPACE_ND);
+COMPARE_ENUMS(DIV);
+COMPARE_ENUMS(MEAN);
+COMPARE_ENUMS(PAD);
+COMPARE_ENUMS(SPACE_TO_BATCH_ND);
+COMPARE_ENUMS(SQUEEZE);
+COMPARE_ENUMS(STRIDED_SLICE);
+COMPARE_ENUMS(SUB);
+COMPARE_ENUMS(TRANSPOSE);
+COMPARE_ENUMS(OEM_OPERATION);
+
+#undef COMPARE_ENUMS
+
+#define COMPARE_ENUMS(symbol) COMPARE_ENUMS_FULL(symbol, ExecutionPreference)
+
+COMPARE_ENUMS(LOW_POWER);
+COMPARE_ENUMS(FAST_SINGLE_ANSWER);
+COMPARE_ENUMS(SUSTAINED_SPEED);
+
+#undef COMPARE_ENUMS
+
+#undef COMPARE_ENUMS_FULL
+
+}  // anonymous namespace
diff --git a/neuralnetworks/1.1/utils/src/Conversions.cpp b/neuralnetworks/1.1/utils/src/Conversions.cpp
new file mode 100644
index 0000000..7fee16b
--- /dev/null
+++ b/neuralnetworks/1.1/utils/src/Conversions.cpp
@@ -0,0 +1,209 @@
+/*
+ * 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 "Conversions.h"
+
+#include <android-base/logging.h>
+#include <android/hardware/neuralnetworks/1.0/types.h>
+#include <android/hardware/neuralnetworks/1.1/types.h>
+#include <nnapi/OperandTypes.h>
+#include <nnapi/OperationTypes.h>
+#include <nnapi/Result.h>
+#include <nnapi/SharedMemory.h>
+#include <nnapi/Types.h>
+#include <nnapi/hal/1.0/Conversions.h>
+#include <nnapi/hal/CommonUtils.h>
+
+#include <algorithm>
+#include <functional>
+#include <iterator>
+#include <type_traits>
+#include <utility>
+
+namespace android::nn {
+namespace {
+
+using hardware::hidl_vec;
+
+template <typename Input>
+using convertOutput = std::decay_t<decltype(convert(std::declval<Input>()).value())>;
+
+template <typename Type>
+Result<std::vector<convertOutput<Type>>> convert(const hidl_vec<Type>& arguments) {
+    std::vector<convertOutput<Type>> canonical;
+    canonical.reserve(arguments.size());
+    for (const auto& argument : arguments) {
+        canonical.push_back(NN_TRY(nn::convert(argument)));
+    }
+    return canonical;
+}
+
+}  // anonymous namespace
+
+Result<OperationType> convert(const hal::V1_1::OperationType& operationType) {
+    return static_cast<OperationType>(operationType);
+}
+
+Result<Capabilities> convert(const hal::V1_1::Capabilities& capabilities) {
+    const auto quantized8Performance = NN_TRY(convert(capabilities.quantized8Performance));
+    const auto float32Performance = NN_TRY(convert(capabilities.float32Performance));
+    const auto relaxedFloat32toFloat16Performance =
+            NN_TRY(convert(capabilities.relaxedFloat32toFloat16Performance));
+
+    auto table = hal::utils::makeQuantized8PerformanceConsistentWithP(float32Performance,
+                                                                      quantized8Performance);
+
+    return Capabilities{
+            .relaxedFloat32toFloat16PerformanceScalar = relaxedFloat32toFloat16Performance,
+            .relaxedFloat32toFloat16PerformanceTensor = relaxedFloat32toFloat16Performance,
+            .operandPerformance = std::move(table),
+    };
+}
+
+Result<Operation> convert(const hal::V1_1::Operation& operation) {
+    return Operation{
+            .type = NN_TRY(convert(operation.type)),
+            .inputs = operation.inputs,
+            .outputs = operation.outputs,
+    };
+}
+
+Result<Model> convert(const hal::V1_1::Model& model) {
+    auto operations = NN_TRY(convert(model.operations));
+
+    // Verify number of consumers.
+    const auto numberOfConsumers =
+            hal::utils::countNumberOfConsumers(model.operands.size(), operations);
+    CHECK(model.operands.size() == numberOfConsumers.size());
+    for (size_t i = 0; i < model.operands.size(); ++i) {
+        if (model.operands[i].numberOfConsumers != numberOfConsumers[i]) {
+            return NN_ERROR() << "Invalid numberOfConsumers for operand " << i << ", expected "
+                              << numberOfConsumers[i] << " but found "
+                              << model.operands[i].numberOfConsumers;
+        }
+    }
+
+    auto main = Model::Subgraph{
+            .operands = NN_TRY(convert(model.operands)),
+            .operations = std::move(operations),
+            .inputIndexes = model.inputIndexes,
+            .outputIndexes = model.outputIndexes,
+    };
+
+    return Model{
+            .main = std::move(main),
+            .operandValues = NN_TRY(convert(model.operandValues)),
+            .pools = NN_TRY(convert(model.pools)),
+            .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16,
+    };
+}
+
+Result<ExecutionPreference> convert(const hal::V1_1::ExecutionPreference& executionPreference) {
+    return static_cast<ExecutionPreference>(executionPreference);
+}
+
+}  // namespace android::nn
+
+namespace android::hardware::neuralnetworks::V1_1::utils {
+namespace {
+
+using utils::convert;
+
+nn::Result<V1_0::PerformanceInfo> convert(
+        const nn::Capabilities::PerformanceInfo& performanceInfo) {
+    return V1_0::utils::convert(performanceInfo);
+}
+
+nn::Result<V1_0::Operand> convert(const nn::Operand& operand) {
+    return V1_0::utils::convert(operand);
+}
+
+nn::Result<hidl_vec<uint8_t>> convert(const nn::Model::OperandValues& operandValues) {
+    return V1_0::utils::convert(operandValues);
+}
+
+nn::Result<hidl_memory> convert(const nn::Memory& memory) {
+    return V1_0::utils::convert(memory);
+}
+
+template <typename Input>
+using convertOutput = std::decay_t<decltype(convert(std::declval<Input>()).value())>;
+
+template <typename Type>
+nn::Result<hidl_vec<convertOutput<Type>>> convert(const std::vector<Type>& arguments) {
+    hidl_vec<convertOutput<Type>> halObject(arguments.size());
+    for (size_t i = 0; i < arguments.size(); ++i) {
+        halObject[i] = NN_TRY(convert(arguments[i]));
+    }
+    return halObject;
+}
+
+}  // anonymous namespace
+
+nn::Result<OperationType> convert(const nn::OperationType& operationType) {
+    return static_cast<OperationType>(operationType);
+}
+
+nn::Result<Capabilities> convert(const nn::Capabilities& capabilities) {
+    return Capabilities{
+            .float32Performance = NN_TRY(convert(
+                    capabilities.operandPerformance.lookup(nn::OperandType::TENSOR_FLOAT32))),
+            .quantized8Performance = NN_TRY(convert(
+                    capabilities.operandPerformance.lookup(nn::OperandType::TENSOR_QUANT8_ASYMM))),
+            .relaxedFloat32toFloat16Performance =
+                    NN_TRY(convert(capabilities.relaxedFloat32toFloat16PerformanceTensor)),
+    };
+}
+
+nn::Result<Operation> convert(const nn::Operation& operation) {
+    return Operation{
+            .type = NN_TRY(convert(operation.type)),
+            .inputs = operation.inputs,
+            .outputs = operation.outputs,
+    };
+}
+
+nn::Result<Model> convert(const nn::Model& model) {
+    if (!hal::utils::hasNoPointerData(model)) {
+        return NN_ERROR() << "Mdoel cannot be converted because it contains pointer-based memory";
+    }
+
+    auto operands = NN_TRY(convert(model.main.operands));
+
+    // Update number of consumers.
+    const auto numberOfConsumers =
+            hal::utils::countNumberOfConsumers(operands.size(), model.main.operations);
+    CHECK(operands.size() == numberOfConsumers.size());
+    for (size_t i = 0; i < operands.size(); ++i) {
+        operands[i].numberOfConsumers = numberOfConsumers[i];
+    }
+
+    return Model{
+            .operands = std::move(operands),
+            .operations = NN_TRY(convert(model.main.operations)),
+            .inputIndexes = model.main.inputIndexes,
+            .outputIndexes = model.main.outputIndexes,
+            .operandValues = NN_TRY(convert(model.operandValues)),
+            .pools = NN_TRY(convert(model.pools)),
+            .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16,
+    };
+}
+
+nn::Result<ExecutionPreference> convert(const nn::ExecutionPreference& executionPreference) {
+    return static_cast<ExecutionPreference>(executionPreference);
+}
+
+}  // namespace android::hardware::neuralnetworks::V1_1::utils
diff --git a/neuralnetworks/1.2/utils/Android.bp b/neuralnetworks/1.2/utils/Android.bp
new file mode 100644
index 0000000..a1dd3d0
--- /dev/null
+++ b/neuralnetworks/1.2/utils/Android.bp
@@ -0,0 +1,37 @@
+//
+// 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_library_static {
+    name: "neuralnetworks_utils_hal_1_2",
+    defaults: ["neuralnetworks_utils_defaults"],
+    srcs: ["src/*"],
+    local_include_dirs: ["include/nnapi/hal/1.2/"],
+    export_include_dirs: ["include"],
+    static_libs: [
+        "neuralnetworks_types",
+        "neuralnetworks_utils_hal_common",
+        "neuralnetworks_utils_hal_1_0",
+        "neuralnetworks_utils_hal_1_1",
+    ],
+    shared_libs: [
+        "android.hardware.neuralnetworks@1.0",
+        "android.hardware.neuralnetworks@1.1",
+        "android.hardware.neuralnetworks@1.2",
+    ],
+    export_static_lib_headers: [
+        "neuralnetworks_utils_hal_common",
+    ],
+}
diff --git a/neuralnetworks/1.2/utils/OWNERS b/neuralnetworks/1.2/utils/OWNERS
new file mode 100644
index 0000000..e4feee3
--- /dev/null
+++ b/neuralnetworks/1.2/utils/OWNERS
@@ -0,0 +1,11 @@
+# Neuralnetworks team
+butlermichael@google.com
+dgross@google.com
+galarragas@google.com
+jeanluc@google.com
+levp@google.com
+miaowang@google.com
+pszczepaniak@google.com
+slavash@google.com
+vddang@google.com
+xusongw@google.com
diff --git a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Conversions.h b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Conversions.h
new file mode 100644
index 0000000..81bf792
--- /dev/null
+++ b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Conversions.h
@@ -0,0 +1,86 @@
+/*
+ * 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_1_2_CONVERSIONS_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_2_CONVERSIONS_H
+
+#include <android/hardware/neuralnetworks/1.2/types.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+#include <nnapi/hal/CommonUtils.h>
+
+namespace android::nn {
+
+Result<OperandType> convert(const hal::V1_2::OperandType& operandType);
+Result<OperationType> convert(const hal::V1_2::OperationType& operationType);
+Result<DeviceType> convert(const hal::V1_2::DeviceType& deviceType);
+Result<Capabilities> convert(const hal::V1_2::Capabilities& capabilities);
+Result<Capabilities::OperandPerformance> convert(
+        const hal::V1_2::Capabilities::OperandPerformance& operandPerformance);
+Result<Operation> convert(const hal::V1_2::Operation& operation);
+Result<Operand::SymmPerChannelQuantParams> convert(
+        const hal::V1_2::SymmPerChannelQuantParams& symmPerChannelQuantParams);
+Result<Operand> convert(const hal::V1_2::Operand& operand);
+Result<Operand::ExtraParams> convert(const hal::V1_2::Operand::ExtraParams& extraParams);
+Result<Model> convert(const hal::V1_2::Model& model);
+Result<Model::ExtensionNameAndPrefix> convert(
+        const hal::V1_2::Model::ExtensionNameAndPrefix& extensionNameAndPrefix);
+Result<OutputShape> convert(const hal::V1_2::OutputShape& outputShape);
+Result<MeasureTiming> convert(const hal::V1_2::MeasureTiming& measureTiming);
+Result<Timing> convert(const hal::V1_2::Timing& timing);
+Result<Extension> convert(const hal::V1_2::Extension& extension);
+Result<Extension::OperandTypeInformation> convert(
+        const hal::V1_2::Extension::OperandTypeInformation& operandTypeInformation);
+Result<NativeHandle> convert(const hardware::hidl_handle& handle);
+
+Result<std::vector<Extension>> convert(const hardware::hidl_vec<hal::V1_2::Extension>& extensions);
+Result<std::vector<NativeHandle>> convert(const hardware::hidl_vec<hardware::hidl_handle>& handles);
+Result<std::vector<OutputShape>> convert(
+        const hardware::hidl_vec<hal::V1_2::OutputShape>& outputShapes);
+
+}  // namespace android::nn
+
+namespace android::hardware::neuralnetworks::V1_2::utils {
+
+nn::Result<OperandType> convert(const nn::OperandType& operandType);
+nn::Result<OperationType> convert(const nn::OperationType& operationType);
+nn::Result<DeviceType> convert(const nn::DeviceType& deviceType);
+nn::Result<Capabilities> convert(const nn::Capabilities& capabilities);
+nn::Result<Capabilities::OperandPerformance> convert(
+        const nn::Capabilities::OperandPerformance& operandPerformance);
+nn::Result<Operation> convert(const nn::Operation& operation);
+nn::Result<SymmPerChannelQuantParams> convert(
+        const nn::Operand::SymmPerChannelQuantParams& symmPerChannelQuantParams);
+nn::Result<Operand> convert(const nn::Operand& operand);
+nn::Result<Operand::ExtraParams> convert(const nn::Operand::ExtraParams& extraParams);
+nn::Result<Model> convert(const nn::Model& model);
+nn::Result<Model::ExtensionNameAndPrefix> convert(
+        const nn::Model::ExtensionNameAndPrefix& extensionNameAndPrefix);
+nn::Result<OutputShape> convert(const nn::OutputShape& outputShape);
+nn::Result<MeasureTiming> convert(const nn::MeasureTiming& measureTiming);
+nn::Result<Timing> convert(const nn::Timing& timing);
+nn::Result<Extension> convert(const nn::Extension& extension);
+nn::Result<Extension::OperandTypeInformation> convert(
+        const nn::Extension::OperandTypeInformation& operandTypeInformation);
+nn::Result<hidl_handle> convert(const nn::NativeHandle& handle);
+
+nn::Result<hidl_vec<Extension>> convert(const std::vector<nn::Extension>& extensions);
+nn::Result<hidl_vec<hidl_handle>> convert(const std::vector<nn::NativeHandle>& handles);
+nn::Result<hidl_vec<OutputShape>> convert(const std::vector<nn::OutputShape>& outputShapes);
+
+}  // namespace android::hardware::neuralnetworks::V1_2::utils
+
+#endif  // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_2_CONVERSIONS_H
diff --git a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Utils.h b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Utils.h
new file mode 100644
index 0000000..b1c2f1a
--- /dev/null
+++ b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Utils.h
@@ -0,0 +1,70 @@
+/*
+ * 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_1_2_UTILS_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_2_UTILS_H
+
+#include "nnapi/hal/1.2/Conversions.h"
+
+#include <android-base/logging.h>
+#include <android/hardware/neuralnetworks/1.2/types.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+#include <nnapi/Validation.h>
+#include <nnapi/hal/1.0/Conversions.h>
+#include <nnapi/hal/1.1/Conversions.h>
+
+#include <limits>
+
+namespace android::hardware::neuralnetworks::V1_2::utils {
+
+constexpr auto kDefaultMesaureTiming = MeasureTiming::NO;
+constexpr auto kNoTiming = Timing{.timeOnDevice = std::numeric_limits<uint64_t>::max(),
+                                  .timeInDriver = std::numeric_limits<uint64_t>::max()};
+constexpr auto kVersion = nn::Version::ANDROID_Q;
+
+template <typename Type>
+nn::Result<void> validate(const Type& halObject) {
+    const auto canonical = NN_TRY(nn::convert(halObject));
+    const auto version = NN_TRY(nn::validate(canonical));
+    if (version > utils::kVersion) {
+        return NN_ERROR() << "";
+    }
+    return {};
+}
+
+template <typename Type>
+bool valid(const Type& halObject) {
+    const auto result = utils::validate(halObject);
+    if (!result.has_value()) {
+        LOG(ERROR) << result.error();
+    }
+    return result.has_value();
+}
+
+template <typename Type>
+decltype(nn::convert(std::declval<Type>())) validatedConvertToCanonical(const Type& halObject) {
+    auto canonical = NN_TRY(nn::convert(halObject));
+    const auto version = NN_TRY(nn::validate(canonical));
+    if (version > utils::kVersion) {
+        return NN_ERROR() << "";
+    }
+    return canonical;
+}
+
+}  // namespace android::hardware::neuralnetworks::V1_2::utils
+
+#endif  // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_2_UTILS_H
diff --git a/neuralnetworks/1.2/utils/src/Assertions.cpp b/neuralnetworks/1.2/utils/src/Assertions.cpp
new file mode 100644
index 0000000..9d9716a
--- /dev/null
+++ b/neuralnetworks/1.2/utils/src/Assertions.cpp
@@ -0,0 +1,188 @@
+/*
+ * 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 <android/hardware/neuralnetworks/1.2/types.h>
+#include <nnapi/OperandTypes.h>
+#include <nnapi/OperationTypes.h>
+#include <nnapi/Types.h>
+#include <type_traits>
+
+namespace {
+
+#define COMPARE_ENUMS_TYPES(type)                                                                  \
+    static_assert(std::is_same_v<                                                                  \
+                          std::underlying_type_t<::android::hardware::neuralnetworks::V1_2::type>, \
+                          std::underlying_type_t<::android::nn::type>>,                            \
+                  "::android::hardware::neuralnetworks::V1_2::" #type                              \
+                  " does not have the same underlying type as ::android::nn::" #type)
+
+COMPARE_ENUMS_TYPES(OperandType);
+COMPARE_ENUMS_TYPES(OperationType);
+COMPARE_ENUMS_TYPES(DeviceType);
+COMPARE_ENUMS_TYPES(MeasureTiming);
+
+#undef COMPARE_ENUMS_TYPES
+
+#define COMPARE_ENUMS_FULL(symbol, type)                                                          \
+    static_assert(                                                                                \
+            static_cast<std::underlying_type_t<::android::hardware::neuralnetworks::V1_2::type>>( \
+                    ::android::hardware::neuralnetworks::V1_2::type::symbol) ==                   \
+                    static_cast<std::underlying_type_t<::android::nn::type>>(                     \
+                            ::android::nn::type::symbol),                                         \
+            "::android::hardware::neuralnetworks::V1_2::" #type "::" #symbol                      \
+            " does not match ::android::nn::" #type "::" #symbol)
+
+#define COMPARE_ENUMS(symbol) COMPARE_ENUMS_FULL(symbol, OperandType)
+
+COMPARE_ENUMS(FLOAT32);
+COMPARE_ENUMS(INT32);
+COMPARE_ENUMS(UINT32);
+COMPARE_ENUMS(TENSOR_FLOAT32);
+COMPARE_ENUMS(TENSOR_INT32);
+COMPARE_ENUMS(TENSOR_QUANT8_ASYMM);
+COMPARE_ENUMS(BOOL);
+COMPARE_ENUMS(TENSOR_QUANT16_SYMM);
+COMPARE_ENUMS(TENSOR_FLOAT16);
+COMPARE_ENUMS(TENSOR_BOOL8);
+COMPARE_ENUMS(FLOAT16);
+COMPARE_ENUMS(TENSOR_QUANT8_SYMM_PER_CHANNEL);
+COMPARE_ENUMS(TENSOR_QUANT16_ASYMM);
+COMPARE_ENUMS(TENSOR_QUANT8_SYMM);
+COMPARE_ENUMS(OEM);
+COMPARE_ENUMS(TENSOR_OEM_BYTE);
+
+#undef COMPARE_ENUMS
+
+#define COMPARE_ENUMS(symbol) COMPARE_ENUMS_FULL(symbol, OperationType)
+
+COMPARE_ENUMS(ADD);
+COMPARE_ENUMS(AVERAGE_POOL_2D);
+COMPARE_ENUMS(CONCATENATION);
+COMPARE_ENUMS(CONV_2D);
+COMPARE_ENUMS(DEPTHWISE_CONV_2D);
+COMPARE_ENUMS(DEPTH_TO_SPACE);
+COMPARE_ENUMS(DEQUANTIZE);
+COMPARE_ENUMS(EMBEDDING_LOOKUP);
+COMPARE_ENUMS(FLOOR);
+COMPARE_ENUMS(FULLY_CONNECTED);
+COMPARE_ENUMS(HASHTABLE_LOOKUP);
+COMPARE_ENUMS(L2_NORMALIZATION);
+COMPARE_ENUMS(L2_POOL_2D);
+COMPARE_ENUMS(LOCAL_RESPONSE_NORMALIZATION);
+COMPARE_ENUMS(LOGISTIC);
+COMPARE_ENUMS(LSH_PROJECTION);
+COMPARE_ENUMS(LSTM);
+COMPARE_ENUMS(MAX_POOL_2D);
+COMPARE_ENUMS(MUL);
+COMPARE_ENUMS(RELU);
+COMPARE_ENUMS(RELU1);
+COMPARE_ENUMS(RELU6);
+COMPARE_ENUMS(RESHAPE);
+COMPARE_ENUMS(RESIZE_BILINEAR);
+COMPARE_ENUMS(RNN);
+COMPARE_ENUMS(SOFTMAX);
+COMPARE_ENUMS(SPACE_TO_DEPTH);
+COMPARE_ENUMS(SVDF);
+COMPARE_ENUMS(TANH);
+COMPARE_ENUMS(BATCH_TO_SPACE_ND);
+COMPARE_ENUMS(DIV);
+COMPARE_ENUMS(MEAN);
+COMPARE_ENUMS(PAD);
+COMPARE_ENUMS(SPACE_TO_BATCH_ND);
+COMPARE_ENUMS(SQUEEZE);
+COMPARE_ENUMS(STRIDED_SLICE);
+COMPARE_ENUMS(SUB);
+COMPARE_ENUMS(TRANSPOSE);
+COMPARE_ENUMS(ABS);
+COMPARE_ENUMS(ARGMAX);
+COMPARE_ENUMS(ARGMIN);
+COMPARE_ENUMS(AXIS_ALIGNED_BBOX_TRANSFORM);
+COMPARE_ENUMS(BIDIRECTIONAL_SEQUENCE_LSTM);
+COMPARE_ENUMS(BIDIRECTIONAL_SEQUENCE_RNN);
+COMPARE_ENUMS(BOX_WITH_NMS_LIMIT);
+COMPARE_ENUMS(CAST);
+COMPARE_ENUMS(CHANNEL_SHUFFLE);
+COMPARE_ENUMS(DETECTION_POSTPROCESSING);
+COMPARE_ENUMS(EQUAL);
+COMPARE_ENUMS(EXP);
+COMPARE_ENUMS(EXPAND_DIMS);
+COMPARE_ENUMS(GATHER);
+COMPARE_ENUMS(GENERATE_PROPOSALS);
+COMPARE_ENUMS(GREATER);
+COMPARE_ENUMS(GREATER_EQUAL);
+COMPARE_ENUMS(GROUPED_CONV_2D);
+COMPARE_ENUMS(HEATMAP_MAX_KEYPOINT);
+COMPARE_ENUMS(INSTANCE_NORMALIZATION);
+COMPARE_ENUMS(LESS);
+COMPARE_ENUMS(LESS_EQUAL);
+COMPARE_ENUMS(LOG);
+COMPARE_ENUMS(LOGICAL_AND);
+COMPARE_ENUMS(LOGICAL_NOT);
+COMPARE_ENUMS(LOGICAL_OR);
+COMPARE_ENUMS(LOG_SOFTMAX);
+COMPARE_ENUMS(MAXIMUM);
+COMPARE_ENUMS(MINIMUM);
+COMPARE_ENUMS(NEG);
+COMPARE_ENUMS(NOT_EQUAL);
+COMPARE_ENUMS(PAD_V2);
+COMPARE_ENUMS(POW);
+COMPARE_ENUMS(PRELU);
+COMPARE_ENUMS(QUANTIZE);
+COMPARE_ENUMS(QUANTIZED_16BIT_LSTM);
+COMPARE_ENUMS(RANDOM_MULTINOMIAL);
+COMPARE_ENUMS(REDUCE_ALL);
+COMPARE_ENUMS(REDUCE_ANY);
+COMPARE_ENUMS(REDUCE_MAX);
+COMPARE_ENUMS(REDUCE_MIN);
+COMPARE_ENUMS(REDUCE_PROD);
+COMPARE_ENUMS(REDUCE_SUM);
+COMPARE_ENUMS(ROI_ALIGN);
+COMPARE_ENUMS(ROI_POOLING);
+COMPARE_ENUMS(RSQRT);
+COMPARE_ENUMS(SELECT);
+COMPARE_ENUMS(SIN);
+COMPARE_ENUMS(SLICE);
+COMPARE_ENUMS(SPLIT);
+COMPARE_ENUMS(SQRT);
+COMPARE_ENUMS(TILE);
+COMPARE_ENUMS(TOPK_V2);
+COMPARE_ENUMS(TRANSPOSE_CONV_2D);
+COMPARE_ENUMS(UNIDIRECTIONAL_SEQUENCE_LSTM);
+COMPARE_ENUMS(UNIDIRECTIONAL_SEQUENCE_RNN);
+COMPARE_ENUMS(RESIZE_NEAREST_NEIGHBOR);
+COMPARE_ENUMS(OEM_OPERATION);
+
+#undef COMPARE_ENUMS
+
+#define COMPARE_ENUMS(symbol) COMPARE_ENUMS_FULL(symbol, DeviceType)
+
+COMPARE_ENUMS(OTHER);
+COMPARE_ENUMS(CPU);
+COMPARE_ENUMS(GPU);
+COMPARE_ENUMS(ACCELERATOR);
+
+#undef COMPARE_ENUMS
+
+#define COMPARE_ENUMS(symbol) COMPARE_ENUMS_FULL(symbol, MeasureTiming)
+
+COMPARE_ENUMS(NO);
+COMPARE_ENUMS(YES);
+
+#undef COMPARE_ENUMS
+
+#undef COMPARE_ENUMS_FULL
+
+}  // anonymous namespace
diff --git a/neuralnetworks/1.2/utils/src/Conversions.cpp b/neuralnetworks/1.2/utils/src/Conversions.cpp
new file mode 100644
index 0000000..fed314b
--- /dev/null
+++ b/neuralnetworks/1.2/utils/src/Conversions.cpp
@@ -0,0 +1,502 @@
+/*
+ * 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 "Conversions.h"
+
+#include <android-base/logging.h>
+#include <android/hardware/neuralnetworks/1.2/types.h>
+#include <nnapi/OperandTypes.h>
+#include <nnapi/OperationTypes.h>
+#include <nnapi/Result.h>
+#include <nnapi/SharedMemory.h>
+#include <nnapi/TypeUtils.h>
+#include <nnapi/Types.h>
+#include <nnapi/hal/1.0/Conversions.h>
+#include <nnapi/hal/CommonUtils.h>
+
+#include <algorithm>
+#include <functional>
+#include <iterator>
+#include <memory>
+#include <type_traits>
+#include <utility>
+
+namespace {
+
+template <typename Type>
+constexpr std::underlying_type_t<Type> underlyingType(Type value) {
+    return static_cast<std::underlying_type_t<Type>>(value);
+}
+
+}  // namespace
+
+namespace android::nn {
+namespace {
+
+constexpr bool validOperandType(OperandType operandType) {
+    switch (operandType) {
+        case OperandType::FLOAT32:
+        case OperandType::INT32:
+        case OperandType::UINT32:
+        case OperandType::TENSOR_FLOAT32:
+        case OperandType::TENSOR_INT32:
+        case OperandType::TENSOR_QUANT8_ASYMM:
+        case OperandType::BOOL:
+        case OperandType::TENSOR_QUANT16_SYMM:
+        case OperandType::TENSOR_FLOAT16:
+        case OperandType::TENSOR_BOOL8:
+        case OperandType::FLOAT16:
+        case OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL:
+        case OperandType::TENSOR_QUANT16_ASYMM:
+        case OperandType::TENSOR_QUANT8_SYMM:
+        case OperandType::OEM:
+        case OperandType::TENSOR_OEM_BYTE:
+            return true;
+        default:
+            break;
+    }
+    return isExtension(operandType);
+}
+
+using hardware::hidl_handle;
+using hardware::hidl_vec;
+
+template <typename Input>
+using ConvertOutput = std::decay_t<decltype(convert(std::declval<Input>()).value())>;
+
+template <typename Type>
+Result<std::vector<ConvertOutput<Type>>> convertVec(const hidl_vec<Type>& arguments) {
+    std::vector<ConvertOutput<Type>> canonical;
+    canonical.reserve(arguments.size());
+    for (const auto& argument : arguments) {
+        canonical.push_back(NN_TRY(nn::convert(argument)));
+    }
+    return canonical;
+}
+
+template <typename Type>
+Result<std::vector<ConvertOutput<Type>>> convert(const hidl_vec<Type>& arguments) {
+    return convertVec(arguments);
+}
+
+}  // anonymous namespace
+
+Result<OperandType> convert(const hal::V1_2::OperandType& operandType) {
+    return static_cast<OperandType>(operandType);
+}
+
+Result<OperationType> convert(const hal::V1_2::OperationType& operationType) {
+    return static_cast<OperationType>(operationType);
+}
+
+Result<DeviceType> convert(const hal::V1_2::DeviceType& deviceType) {
+    return static_cast<DeviceType>(deviceType);
+}
+
+Result<Capabilities> convert(const hal::V1_2::Capabilities& capabilities) {
+    const bool validOperandTypes = std::all_of(
+            capabilities.operandPerformance.begin(), capabilities.operandPerformance.end(),
+            [](const hal::V1_2::Capabilities::OperandPerformance& operandPerformance) {
+                const auto maybeType = convert(operandPerformance.type);
+                return !maybeType.has_value() ? false : validOperandType(maybeType.value());
+            });
+    if (!validOperandTypes) {
+        return NN_ERROR()
+               << "Invalid OperandType when converting OperandPerformance in Capabilities";
+    }
+
+    const auto relaxedFloat32toFloat16PerformanceScalar =
+            NN_TRY(convert(capabilities.relaxedFloat32toFloat16PerformanceScalar));
+    const auto relaxedFloat32toFloat16PerformanceTensor =
+            NN_TRY(convert(capabilities.relaxedFloat32toFloat16PerformanceTensor));
+    auto operandPerformance = NN_TRY(convert(capabilities.operandPerformance));
+
+    auto table =
+            NN_TRY(Capabilities::OperandPerformanceTable::create(std::move(operandPerformance)));
+
+    return Capabilities{
+            .relaxedFloat32toFloat16PerformanceScalar = relaxedFloat32toFloat16PerformanceScalar,
+            .relaxedFloat32toFloat16PerformanceTensor = relaxedFloat32toFloat16PerformanceTensor,
+            .operandPerformance = std::move(table),
+    };
+}
+
+Result<Capabilities::OperandPerformance> convert(
+        const hal::V1_2::Capabilities::OperandPerformance& operandPerformance) {
+    return Capabilities::OperandPerformance{
+            .type = NN_TRY(convert(operandPerformance.type)),
+            .info = NN_TRY(convert(operandPerformance.info)),
+    };
+}
+
+Result<Operation> convert(const hal::V1_2::Operation& operation) {
+    return Operation{
+            .type = NN_TRY(convert(operation.type)),
+            .inputs = operation.inputs,
+            .outputs = operation.outputs,
+    };
+}
+
+Result<Operand::SymmPerChannelQuantParams> convert(
+        const hal::V1_2::SymmPerChannelQuantParams& symmPerChannelQuantParams) {
+    return Operand::SymmPerChannelQuantParams{
+            .scales = symmPerChannelQuantParams.scales,
+            .channelDim = symmPerChannelQuantParams.channelDim,
+    };
+}
+
+Result<Operand> convert(const hal::V1_2::Operand& operand) {
+    return Operand{
+            .type = NN_TRY(convert(operand.type)),
+            .dimensions = operand.dimensions,
+            .scale = operand.scale,
+            .zeroPoint = operand.zeroPoint,
+            .lifetime = NN_TRY(convert(operand.lifetime)),
+            .location = NN_TRY(convert(operand.location)),
+            .extraParams = NN_TRY(convert(operand.extraParams)),
+    };
+}
+
+Result<Operand::ExtraParams> convert(const hal::V1_2::Operand::ExtraParams& extraParams) {
+    using Discriminator = hal::V1_2::Operand::ExtraParams::hidl_discriminator;
+    switch (extraParams.getDiscriminator()) {
+        case Discriminator::none:
+            return Operand::NoParams{};
+        case Discriminator::channelQuant:
+            return convert(extraParams.channelQuant());
+        case Discriminator::extension:
+            return extraParams.extension();
+    }
+    return NN_ERROR() << "Unrecognized Operand::ExtraParams discriminator: "
+                      << underlyingType(extraParams.getDiscriminator());
+}
+
+Result<Model> convert(const hal::V1_2::Model& model) {
+    auto operations = NN_TRY(convert(model.operations));
+
+    // Verify number of consumers.
+    const auto numberOfConsumers =
+            hal::utils::countNumberOfConsumers(model.operands.size(), operations);
+    CHECK(model.operands.size() == numberOfConsumers.size());
+    for (size_t i = 0; i < model.operands.size(); ++i) {
+        if (model.operands[i].numberOfConsumers != numberOfConsumers[i]) {
+            return NN_ERROR() << "Invalid numberOfConsumers for operand " << i << ", expected "
+                              << numberOfConsumers[i] << " but found "
+                              << model.operands[i].numberOfConsumers;
+        }
+    }
+
+    auto main = Model::Subgraph{
+            .operands = NN_TRY(convert(model.operands)),
+            .operations = std::move(operations),
+            .inputIndexes = model.inputIndexes,
+            .outputIndexes = model.outputIndexes,
+    };
+
+    return Model{
+            .main = std::move(main),
+            .operandValues = NN_TRY(convert(model.operandValues)),
+            .pools = NN_TRY(convert(model.pools)),
+            .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16,
+            .extensionNameToPrefix = NN_TRY(convert(model.extensionNameToPrefix)),
+    };
+}
+
+Result<Model::ExtensionNameAndPrefix> convert(
+        const hal::V1_2::Model::ExtensionNameAndPrefix& extensionNameAndPrefix) {
+    return Model::ExtensionNameAndPrefix{
+            .name = extensionNameAndPrefix.name,
+            .prefix = extensionNameAndPrefix.prefix,
+    };
+}
+
+Result<OutputShape> convert(const hal::V1_2::OutputShape& outputShape) {
+    return OutputShape{
+            .dimensions = outputShape.dimensions,
+            .isSufficient = outputShape.isSufficient,
+    };
+}
+
+Result<MeasureTiming> convert(const hal::V1_2::MeasureTiming& measureTiming) {
+    return static_cast<MeasureTiming>(measureTiming);
+}
+
+Result<Timing> convert(const hal::V1_2::Timing& timing) {
+    return Timing{.timeOnDevice = timing.timeOnDevice, .timeInDriver = timing.timeInDriver};
+}
+
+Result<Extension> convert(const hal::V1_2::Extension& extension) {
+    return Extension{
+            .name = extension.name,
+            .operandTypes = NN_TRY(convert(extension.operandTypes)),
+    };
+}
+
+Result<Extension::OperandTypeInformation> convert(
+        const hal::V1_2::Extension::OperandTypeInformation& operandTypeInformation) {
+    return Extension::OperandTypeInformation{
+            .type = operandTypeInformation.type,
+            .isTensor = operandTypeInformation.isTensor,
+            .byteSize = operandTypeInformation.byteSize,
+    };
+}
+
+Result<NativeHandle> convert(const hidl_handle& handle) {
+    auto* cloned = native_handle_clone(handle.getNativeHandle());
+    return ::android::NativeHandle::create(cloned, /*ownsHandle=*/true);
+}
+
+Result<std::vector<Extension>> convert(const hidl_vec<hal::V1_2::Extension>& extensions) {
+    return convertVec(extensions);
+}
+
+Result<std::vector<NativeHandle>> convert(const hidl_vec<hidl_handle>& handles) {
+    return convertVec(handles);
+}
+
+Result<std::vector<OutputShape>> convert(const hidl_vec<hal::V1_2::OutputShape>& outputShapes) {
+    return convertVec(outputShapes);
+}
+
+}  // namespace android::nn
+
+namespace android::hardware::neuralnetworks::V1_2::utils {
+namespace {
+
+using utils::convert;
+
+nn::Result<V1_0::OperandLifeTime> convert(const nn::Operand::LifeTime& lifetime) {
+    return V1_0::utils::convert(lifetime);
+}
+
+nn::Result<V1_0::PerformanceInfo> convert(
+        const nn::Capabilities::PerformanceInfo& performanceInfo) {
+    return V1_0::utils::convert(performanceInfo);
+}
+
+nn::Result<V1_0::DataLocation> convert(const nn::DataLocation& location) {
+    return V1_0::utils::convert(location);
+}
+
+nn::Result<hidl_vec<uint8_t>> convert(const nn::Model::OperandValues& operandValues) {
+    return V1_0::utils::convert(operandValues);
+}
+
+nn::Result<hidl_memory> convert(const nn::Memory& memory) {
+    return V1_0::utils::convert(memory);
+}
+
+template <typename Input>
+using ConvertOutput = std::decay_t<decltype(convert(std::declval<Input>()).value())>;
+
+template <typename Type>
+nn::Result<hidl_vec<ConvertOutput<Type>>> convertVec(const std::vector<Type>& arguments) {
+    hidl_vec<ConvertOutput<Type>> halObject(arguments.size());
+    for (size_t i = 0; i < arguments.size(); ++i) {
+        halObject[i] = NN_TRY(convert(arguments[i]));
+    }
+    return halObject;
+}
+
+template <typename Type>
+nn::Result<hidl_vec<ConvertOutput<Type>>> convert(const std::vector<Type>& arguments) {
+    return convertVec(arguments);
+}
+
+nn::Result<Operand::ExtraParams> makeExtraParams(nn::Operand::NoParams /*noParams*/) {
+    return Operand::ExtraParams{};
+}
+
+nn::Result<Operand::ExtraParams> makeExtraParams(
+        const nn::Operand::SymmPerChannelQuantParams& channelQuant) {
+    Operand::ExtraParams ret;
+    ret.channelQuant(NN_TRY(convert(channelQuant)));
+    return ret;
+}
+
+nn::Result<Operand::ExtraParams> makeExtraParams(const nn::Operand::ExtensionParams& extension) {
+    Operand::ExtraParams ret;
+    ret.extension(extension);
+    return ret;
+}
+
+}  // anonymous namespace
+
+nn::Result<OperandType> convert(const nn::OperandType& operandType) {
+    return static_cast<OperandType>(operandType);
+}
+
+nn::Result<OperationType> convert(const nn::OperationType& operationType) {
+    return static_cast<OperationType>(operationType);
+}
+
+nn::Result<DeviceType> convert(const nn::DeviceType& deviceType) {
+    switch (deviceType) {
+        case nn::DeviceType::UNKNOWN:
+            return NN_ERROR() << "Invalid DeviceType UNKNOWN";
+        case nn::DeviceType::OTHER:
+        case nn::DeviceType::CPU:
+        case nn::DeviceType::GPU:
+        case nn::DeviceType::ACCELERATOR:
+            return static_cast<DeviceType>(deviceType);
+    }
+    return NN_ERROR() << "Invalid DeviceType " << underlyingType(deviceType);
+}
+
+nn::Result<Capabilities> convert(const nn::Capabilities& capabilities) {
+    std::vector<nn::Capabilities::OperandPerformance> operandPerformance;
+    operandPerformance.reserve(capabilities.operandPerformance.asVector().size());
+    std::copy_if(capabilities.operandPerformance.asVector().begin(),
+                 capabilities.operandPerformance.asVector().end(),
+                 std::back_inserter(operandPerformance),
+                 [](const nn::Capabilities::OperandPerformance& operandPerformance) {
+                     return nn::validOperandType(operandPerformance.type);
+                 });
+
+    return Capabilities{
+            .relaxedFloat32toFloat16PerformanceScalar =
+                    NN_TRY(convert(capabilities.relaxedFloat32toFloat16PerformanceScalar)),
+            .relaxedFloat32toFloat16PerformanceTensor =
+                    NN_TRY(convert(capabilities.relaxedFloat32toFloat16PerformanceTensor)),
+            .operandPerformance = NN_TRY(convert(operandPerformance)),
+    };
+}
+
+nn::Result<Capabilities::OperandPerformance> convert(
+        const nn::Capabilities::OperandPerformance& operandPerformance) {
+    return Capabilities::OperandPerformance{
+            .type = NN_TRY(convert(operandPerformance.type)),
+            .info = NN_TRY(convert(operandPerformance.info)),
+    };
+}
+
+nn::Result<Operation> convert(const nn::Operation& operation) {
+    return Operation{
+            .type = NN_TRY(convert(operation.type)),
+            .inputs = operation.inputs,
+            .outputs = operation.outputs,
+    };
+}
+
+nn::Result<SymmPerChannelQuantParams> convert(
+        const nn::Operand::SymmPerChannelQuantParams& symmPerChannelQuantParams) {
+    return SymmPerChannelQuantParams{
+            .scales = symmPerChannelQuantParams.scales,
+            .channelDim = symmPerChannelQuantParams.channelDim,
+    };
+}
+
+nn::Result<Operand> convert(const nn::Operand& operand) {
+    return Operand{
+            .type = NN_TRY(convert(operand.type)),
+            .dimensions = operand.dimensions,
+            .numberOfConsumers = 0,
+            .scale = operand.scale,
+            .zeroPoint = operand.zeroPoint,
+            .lifetime = NN_TRY(convert(operand.lifetime)),
+            .location = NN_TRY(convert(operand.location)),
+            .extraParams = NN_TRY(convert(operand.extraParams)),
+    };
+}
+
+nn::Result<Operand::ExtraParams> convert(const nn::Operand::ExtraParams& extraParams) {
+    return std::visit([](const auto& x) { return makeExtraParams(x); }, extraParams);
+}
+
+nn::Result<Model> convert(const nn::Model& model) {
+    if (!hal::utils::hasNoPointerData(model)) {
+        return NN_ERROR() << "Model cannot be converted because it contains pointer-based memory";
+    }
+
+    auto operands = NN_TRY(convert(model.main.operands));
+
+    // Update number of consumers.
+    const auto numberOfConsumers =
+            hal::utils::countNumberOfConsumers(operands.size(), model.main.operations);
+    CHECK(operands.size() == numberOfConsumers.size());
+    for (size_t i = 0; i < operands.size(); ++i) {
+        operands[i].numberOfConsumers = numberOfConsumers[i];
+    }
+
+    return Model{
+            .operands = std::move(operands),
+            .operations = NN_TRY(convert(model.main.operations)),
+            .inputIndexes = model.main.inputIndexes,
+            .outputIndexes = model.main.outputIndexes,
+            .operandValues = NN_TRY(convert(model.operandValues)),
+            .pools = NN_TRY(convert(model.pools)),
+            .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16,
+            .extensionNameToPrefix = NN_TRY(convert(model.extensionNameToPrefix)),
+    };
+}
+
+nn::Result<Model::ExtensionNameAndPrefix> convert(
+        const nn::Model::ExtensionNameAndPrefix& extensionNameAndPrefix) {
+    return Model::ExtensionNameAndPrefix{
+            .name = extensionNameAndPrefix.name,
+            .prefix = extensionNameAndPrefix.prefix,
+    };
+}
+
+nn::Result<OutputShape> convert(const nn::OutputShape& outputShape) {
+    return OutputShape{.dimensions = outputShape.dimensions,
+                       .isSufficient = outputShape.isSufficient};
+}
+
+nn::Result<MeasureTiming> convert(const nn::MeasureTiming& measureTiming) {
+    return static_cast<MeasureTiming>(measureTiming);
+}
+
+nn::Result<Timing> convert(const nn::Timing& timing) {
+    return Timing{.timeOnDevice = timing.timeOnDevice, .timeInDriver = timing.timeInDriver};
+}
+
+nn::Result<Extension> convert(const nn::Extension& extension) {
+    return Extension{
+            .name = extension.name,
+            .operandTypes = NN_TRY(convert(extension.operandTypes)),
+    };
+}
+
+nn::Result<Extension::OperandTypeInformation> convert(
+        const nn::Extension::OperandTypeInformation& operandTypeInformation) {
+    return Extension::OperandTypeInformation{
+            .type = operandTypeInformation.type,
+            .isTensor = operandTypeInformation.isTensor,
+            .byteSize = operandTypeInformation.byteSize,
+    };
+}
+
+nn::Result<hidl_handle> convert(const nn::NativeHandle& handle) {
+    const auto hidlHandle = hidl_handle(handle->handle());
+    // Copy memory to force the native_handle_t to be copied.
+    auto copiedHandle = hidlHandle;
+    return copiedHandle;
+}
+
+nn::Result<hidl_vec<Extension>> convert(const std::vector<nn::Extension>& extensions) {
+    return convertVec(extensions);
+}
+
+nn::Result<hidl_vec<hidl_handle>> convert(const std::vector<nn::NativeHandle>& handles) {
+    return convertVec(handles);
+}
+
+nn::Result<hidl_vec<OutputShape>> convert(const std::vector<nn::OutputShape>& outputShapes) {
+    return convertVec(outputShapes);
+}
+
+}  // namespace android::hardware::neuralnetworks::V1_2::utils
diff --git a/neuralnetworks/1.3/utils/Android.bp b/neuralnetworks/1.3/utils/Android.bp
new file mode 100644
index 0000000..279b250
--- /dev/null
+++ b/neuralnetworks/1.3/utils/Android.bp
@@ -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.
+//
+
+cc_library_static {
+    name: "neuralnetworks_utils_hal_1_3",
+    defaults: ["neuralnetworks_utils_defaults"],
+    srcs: ["src/*"],
+    local_include_dirs: ["include/nnapi/hal/1.3/"],
+    export_include_dirs: ["include"],
+    static_libs: [
+        "neuralnetworks_types",
+        "neuralnetworks_utils_hal_common",
+        "neuralnetworks_utils_hal_1_0",
+        "neuralnetworks_utils_hal_1_1",
+        "neuralnetworks_utils_hal_1_2",
+    ],
+    shared_libs: [
+        "android.hardware.neuralnetworks@1.0",
+        "android.hardware.neuralnetworks@1.1",
+        "android.hardware.neuralnetworks@1.2",
+        "android.hardware.neuralnetworks@1.3",
+    ],
+    export_static_lib_headers: [
+        "neuralnetworks_utils_hal_common",
+    ],
+}
diff --git a/neuralnetworks/1.3/utils/OWNERS b/neuralnetworks/1.3/utils/OWNERS
new file mode 100644
index 0000000..e4feee3
--- /dev/null
+++ b/neuralnetworks/1.3/utils/OWNERS
@@ -0,0 +1,11 @@
+# Neuralnetworks team
+butlermichael@google.com
+dgross@google.com
+galarragas@google.com
+jeanluc@google.com
+levp@google.com
+miaowang@google.com
+pszczepaniak@google.com
+slavash@google.com
+vddang@google.com
+xusongw@google.com
diff --git a/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Conversions.h b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Conversions.h
new file mode 100644
index 0000000..43987a9
--- /dev/null
+++ b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Conversions.h
@@ -0,0 +1,79 @@
+/*
+ * 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_1_3_CONVERSIONS_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_3_CONVERSIONS_H
+
+#include <android/hardware/neuralnetworks/1.3/IPreparedModel.h>
+#include <android/hardware/neuralnetworks/1.3/types.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+#include <nnapi/hal/CommonUtils.h>
+
+namespace android::nn {
+
+Result<OperandType> convert(const hal::V1_3::OperandType& operandType);
+Result<OperationType> convert(const hal::V1_3::OperationType& operationType);
+Result<Priority> convert(const hal::V1_3::Priority& priority);
+Result<Capabilities> convert(const hal::V1_3::Capabilities& capabilities);
+Result<Capabilities::OperandPerformance> convert(
+        const hal::V1_3::Capabilities::OperandPerformance& operandPerformance);
+Result<Operation> convert(const hal::V1_3::Operation& operation);
+Result<Operand::LifeTime> convert(const hal::V1_3::OperandLifeTime& operandLifeTime);
+Result<Operand> convert(const hal::V1_3::Operand& operand);
+Result<Model> convert(const hal::V1_3::Model& model);
+Result<Model::Subgraph> convert(const hal::V1_3::Subgraph& subgraph);
+Result<BufferDesc> convert(const hal::V1_3::BufferDesc& bufferDesc);
+Result<BufferRole> convert(const hal::V1_3::BufferRole& bufferRole);
+Result<Request> convert(const hal::V1_3::Request& request);
+Result<Request::MemoryPool> convert(const hal::V1_3::Request::MemoryPool& memoryPool);
+Result<OptionalTimePoint> convert(const hal::V1_3::OptionalTimePoint& optionalTimePoint);
+Result<OptionalTimeoutDuration> convert(
+        const hal::V1_3::OptionalTimeoutDuration& optionalTimeoutDuration);
+Result<ErrorStatus> convert(const hal::V1_3::ErrorStatus& errorStatus);
+
+Result<std::vector<BufferRole>> convert(
+        const hardware::hidl_vec<hal::V1_3::BufferRole>& bufferRoles);
+
+}  // namespace android::nn
+
+namespace android::hardware::neuralnetworks::V1_3::utils {
+
+nn::Result<OperandType> convert(const nn::OperandType& operandType);
+nn::Result<OperationType> convert(const nn::OperationType& operationType);
+nn::Result<Priority> convert(const nn::Priority& priority);
+nn::Result<Capabilities> convert(const nn::Capabilities& capabilities);
+nn::Result<Capabilities::OperandPerformance> convert(
+        const nn::Capabilities::OperandPerformance& operandPerformance);
+nn::Result<Operation> convert(const nn::Operation& operation);
+nn::Result<OperandLifeTime> convert(const nn::Operand::LifeTime& operandLifeTime);
+nn::Result<Operand> convert(const nn::Operand& operand);
+nn::Result<Model> convert(const nn::Model& model);
+nn::Result<Subgraph> convert(const nn::Model::Subgraph& subgraph);
+nn::Result<BufferDesc> convert(const nn::BufferDesc& bufferDesc);
+nn::Result<BufferRole> convert(const nn::BufferRole& bufferRole);
+nn::Result<Request> convert(const nn::Request& request);
+nn::Result<Request::MemoryPool> convert(const nn::Request::MemoryPool& memoryPool);
+nn::Result<OptionalTimePoint> convert(const nn::OptionalTimePoint& optionalTimePoint);
+nn::Result<OptionalTimeoutDuration> convert(
+        const nn::OptionalTimeoutDuration& optionalTimeoutDuration);
+nn::Result<ErrorStatus> convert(const nn::ErrorStatus& errorStatus);
+
+nn::Result<hidl_vec<BufferRole>> convert(const std::vector<nn::BufferRole>& bufferRoles);
+
+}  // namespace android::hardware::neuralnetworks::V1_3::utils
+
+#endif  // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_3_CONVERSIONS_H
diff --git a/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Utils.h b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Utils.h
new file mode 100644
index 0000000..f8c975d
--- /dev/null
+++ b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Utils.h
@@ -0,0 +1,67 @@
+/*
+ * 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_1_3_UTILS_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_3_UTILS_H
+
+#include "nnapi/hal/1.3/Conversions.h"
+
+#include <android-base/logging.h>
+#include <android/hardware/neuralnetworks/1.3/types.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+#include <nnapi/Validation.h>
+#include <nnapi/hal/1.0/Conversions.h>
+#include <nnapi/hal/1.1/Conversions.h>
+#include <nnapi/hal/1.2/Conversions.h>
+
+namespace android::hardware::neuralnetworks::V1_3::utils {
+
+constexpr auto kDefaultPriority = Priority::MEDIUM;
+constexpr auto kVersion = nn::Version::ANDROID_R;
+
+template <typename Type>
+nn::Result<void> validate(const Type& halObject) {
+    const auto canonical = NN_TRY(nn::convert(halObject));
+    const auto version = NN_TRY(nn::validate(canonical));
+    if (version > utils::kVersion) {
+        return NN_ERROR() << "";
+    }
+    return {};
+}
+
+template <typename Type>
+bool valid(const Type& halObject) {
+    const auto result = utils::validate(halObject);
+    if (!result.has_value()) {
+        LOG(ERROR) << result.error();
+    }
+    return result.has_value();
+}
+
+template <typename Type>
+decltype(nn::convert(std::declval<Type>())) validatedConvertToCanonical(const Type& halObject) {
+    auto canonical = NN_TRY(nn::convert(halObject));
+    const auto version = NN_TRY(nn::validate(canonical));
+    if (version > utils::kVersion) {
+        return NN_ERROR() << "";
+    }
+    return canonical;
+}
+
+}  // namespace android::hardware::neuralnetworks::V1_3::utils
+
+#endif  // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_3_UTILS_H
diff --git a/neuralnetworks/1.3/utils/src/Assertions.cpp b/neuralnetworks/1.3/utils/src/Assertions.cpp
new file mode 100644
index 0000000..96d647a
--- /dev/null
+++ b/neuralnetworks/1.3/utils/src/Assertions.cpp
@@ -0,0 +1,218 @@
+/*
+ * 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 <android/hardware/neuralnetworks/1.3/types.h>
+#include <nnapi/OperandTypes.h>
+#include <nnapi/OperationTypes.h>
+#include <nnapi/Types.h>
+#include <type_traits>
+
+namespace {
+
+#define COMPARE_ENUMS_TYPES(lhsType, rhsType)                                                   \
+    static_assert(                                                                              \
+            std::is_same_v<                                                                     \
+                    std::underlying_type_t<::android::hardware::neuralnetworks::V1_3::lhsType>, \
+                    std::underlying_type_t<::android::nn::rhsType>>,                            \
+            "::android::hardware::neuralnetworks::V1_3::" #lhsType                              \
+            " does not have the same underlying type as ::android::nn::" #rhsType)
+
+COMPARE_ENUMS_TYPES(OperandType, OperandType);
+COMPARE_ENUMS_TYPES(OperationType, OperationType);
+COMPARE_ENUMS_TYPES(Priority, Priority);
+COMPARE_ENUMS_TYPES(OperandLifeTime, Operand::LifeTime);
+COMPARE_ENUMS_TYPES(ErrorStatus, ErrorStatus);
+
+#undef COMPARE_ENUMS_TYPES
+
+#define COMPARE_ENUMS_FULL(symbol, lhsType, rhsType)                                             \
+    static_assert(                                                                               \
+            static_cast<                                                                         \
+                    std::underlying_type_t<::android::hardware::neuralnetworks::V1_3::lhsType>>( \
+                    ::android::hardware::neuralnetworks::V1_3::lhsType::symbol) ==               \
+                    static_cast<std::underlying_type_t<::android::nn::rhsType>>(                 \
+                            ::android::nn::rhsType::symbol),                                     \
+            "::android::hardware::neuralnetworks::V1_3::" #lhsType "::" #symbol                  \
+            " does not match ::android::nn::" #rhsType "::" #symbol)
+
+#define COMPARE_ENUMS(symbol) COMPARE_ENUMS_FULL(symbol, OperandType, OperandType)
+
+COMPARE_ENUMS(FLOAT32);
+COMPARE_ENUMS(INT32);
+COMPARE_ENUMS(UINT32);
+COMPARE_ENUMS(TENSOR_FLOAT32);
+COMPARE_ENUMS(TENSOR_INT32);
+COMPARE_ENUMS(TENSOR_QUANT8_ASYMM);
+COMPARE_ENUMS(BOOL);
+COMPARE_ENUMS(TENSOR_QUANT16_SYMM);
+COMPARE_ENUMS(TENSOR_FLOAT16);
+COMPARE_ENUMS(TENSOR_BOOL8);
+COMPARE_ENUMS(FLOAT16);
+COMPARE_ENUMS(TENSOR_QUANT8_SYMM_PER_CHANNEL);
+COMPARE_ENUMS(TENSOR_QUANT16_ASYMM);
+COMPARE_ENUMS(TENSOR_QUANT8_SYMM);
+COMPARE_ENUMS(TENSOR_QUANT8_ASYMM_SIGNED);
+COMPARE_ENUMS(SUBGRAPH);
+COMPARE_ENUMS(OEM);
+COMPARE_ENUMS(TENSOR_OEM_BYTE);
+
+#undef COMPARE_ENUMS
+
+#define COMPARE_ENUMS(symbol) COMPARE_ENUMS_FULL(symbol, OperationType, OperationType)
+
+COMPARE_ENUMS(ADD);
+COMPARE_ENUMS(AVERAGE_POOL_2D);
+COMPARE_ENUMS(CONCATENATION);
+COMPARE_ENUMS(CONV_2D);
+COMPARE_ENUMS(DEPTHWISE_CONV_2D);
+COMPARE_ENUMS(DEPTH_TO_SPACE);
+COMPARE_ENUMS(DEQUANTIZE);
+COMPARE_ENUMS(EMBEDDING_LOOKUP);
+COMPARE_ENUMS(FLOOR);
+COMPARE_ENUMS(FULLY_CONNECTED);
+COMPARE_ENUMS(HASHTABLE_LOOKUP);
+COMPARE_ENUMS(L2_NORMALIZATION);
+COMPARE_ENUMS(L2_POOL_2D);
+COMPARE_ENUMS(LOCAL_RESPONSE_NORMALIZATION);
+COMPARE_ENUMS(LOGISTIC);
+COMPARE_ENUMS(LSH_PROJECTION);
+COMPARE_ENUMS(LSTM);
+COMPARE_ENUMS(MAX_POOL_2D);
+COMPARE_ENUMS(MUL);
+COMPARE_ENUMS(RELU);
+COMPARE_ENUMS(RELU1);
+COMPARE_ENUMS(RELU6);
+COMPARE_ENUMS(RESHAPE);
+COMPARE_ENUMS(RESIZE_BILINEAR);
+COMPARE_ENUMS(RNN);
+COMPARE_ENUMS(SOFTMAX);
+COMPARE_ENUMS(SPACE_TO_DEPTH);
+COMPARE_ENUMS(SVDF);
+COMPARE_ENUMS(TANH);
+COMPARE_ENUMS(BATCH_TO_SPACE_ND);
+COMPARE_ENUMS(DIV);
+COMPARE_ENUMS(MEAN);
+COMPARE_ENUMS(PAD);
+COMPARE_ENUMS(SPACE_TO_BATCH_ND);
+COMPARE_ENUMS(SQUEEZE);
+COMPARE_ENUMS(STRIDED_SLICE);
+COMPARE_ENUMS(SUB);
+COMPARE_ENUMS(TRANSPOSE);
+COMPARE_ENUMS(ABS);
+COMPARE_ENUMS(ARGMAX);
+COMPARE_ENUMS(ARGMIN);
+COMPARE_ENUMS(AXIS_ALIGNED_BBOX_TRANSFORM);
+COMPARE_ENUMS(BIDIRECTIONAL_SEQUENCE_LSTM);
+COMPARE_ENUMS(BIDIRECTIONAL_SEQUENCE_RNN);
+COMPARE_ENUMS(BOX_WITH_NMS_LIMIT);
+COMPARE_ENUMS(CAST);
+COMPARE_ENUMS(CHANNEL_SHUFFLE);
+COMPARE_ENUMS(DETECTION_POSTPROCESSING);
+COMPARE_ENUMS(EQUAL);
+COMPARE_ENUMS(EXP);
+COMPARE_ENUMS(EXPAND_DIMS);
+COMPARE_ENUMS(GATHER);
+COMPARE_ENUMS(GENERATE_PROPOSALS);
+COMPARE_ENUMS(GREATER);
+COMPARE_ENUMS(GREATER_EQUAL);
+COMPARE_ENUMS(GROUPED_CONV_2D);
+COMPARE_ENUMS(HEATMAP_MAX_KEYPOINT);
+COMPARE_ENUMS(INSTANCE_NORMALIZATION);
+COMPARE_ENUMS(LESS);
+COMPARE_ENUMS(LESS_EQUAL);
+COMPARE_ENUMS(LOG);
+COMPARE_ENUMS(LOGICAL_AND);
+COMPARE_ENUMS(LOGICAL_NOT);
+COMPARE_ENUMS(LOGICAL_OR);
+COMPARE_ENUMS(LOG_SOFTMAX);
+COMPARE_ENUMS(MAXIMUM);
+COMPARE_ENUMS(MINIMUM);
+COMPARE_ENUMS(NEG);
+COMPARE_ENUMS(NOT_EQUAL);
+COMPARE_ENUMS(PAD_V2);
+COMPARE_ENUMS(POW);
+COMPARE_ENUMS(PRELU);
+COMPARE_ENUMS(QUANTIZE);
+COMPARE_ENUMS(QUANTIZED_16BIT_LSTM);
+COMPARE_ENUMS(RANDOM_MULTINOMIAL);
+COMPARE_ENUMS(REDUCE_ALL);
+COMPARE_ENUMS(REDUCE_ANY);
+COMPARE_ENUMS(REDUCE_MAX);
+COMPARE_ENUMS(REDUCE_MIN);
+COMPARE_ENUMS(REDUCE_PROD);
+COMPARE_ENUMS(REDUCE_SUM);
+COMPARE_ENUMS(ROI_ALIGN);
+COMPARE_ENUMS(ROI_POOLING);
+COMPARE_ENUMS(RSQRT);
+COMPARE_ENUMS(SELECT);
+COMPARE_ENUMS(SIN);
+COMPARE_ENUMS(SLICE);
+COMPARE_ENUMS(SPLIT);
+COMPARE_ENUMS(SQRT);
+COMPARE_ENUMS(TILE);
+COMPARE_ENUMS(TOPK_V2);
+COMPARE_ENUMS(TRANSPOSE_CONV_2D);
+COMPARE_ENUMS(UNIDIRECTIONAL_SEQUENCE_LSTM);
+COMPARE_ENUMS(UNIDIRECTIONAL_SEQUENCE_RNN);
+COMPARE_ENUMS(RESIZE_NEAREST_NEIGHBOR);
+COMPARE_ENUMS(QUANTIZED_LSTM);
+COMPARE_ENUMS(IF);
+COMPARE_ENUMS(WHILE);
+COMPARE_ENUMS(ELU);
+COMPARE_ENUMS(HARD_SWISH);
+COMPARE_ENUMS(FILL);
+COMPARE_ENUMS(RANK);
+COMPARE_ENUMS(OEM_OPERATION);
+
+#undef COMPARE_ENUMS
+
+#define COMPARE_ENUMS(symbol) COMPARE_ENUMS_FULL(symbol, Priority, Priority)
+
+COMPARE_ENUMS(LOW);
+COMPARE_ENUMS(MEDIUM);
+COMPARE_ENUMS(HIGH);
+
+#undef COMPARE_ENUMS
+
+#define COMPARE_ENUMS(symbol) COMPARE_ENUMS_FULL(symbol, OperandLifeTime, Operand::LifeTime)
+
+COMPARE_ENUMS(TEMPORARY_VARIABLE);
+COMPARE_ENUMS(SUBGRAPH_INPUT);
+COMPARE_ENUMS(SUBGRAPH_OUTPUT);
+COMPARE_ENUMS(CONSTANT_COPY);
+COMPARE_ENUMS(CONSTANT_REFERENCE);
+COMPARE_ENUMS(NO_VALUE);
+COMPARE_ENUMS(SUBGRAPH);
+
+#undef COMPARE_ENUMS
+
+#define COMPARE_ENUMS(symbol) COMPARE_ENUMS_FULL(symbol, ErrorStatus, ErrorStatus)
+
+COMPARE_ENUMS(NONE);
+COMPARE_ENUMS(DEVICE_UNAVAILABLE);
+COMPARE_ENUMS(GENERAL_FAILURE);
+COMPARE_ENUMS(OUTPUT_INSUFFICIENT_SIZE);
+COMPARE_ENUMS(INVALID_ARGUMENT);
+COMPARE_ENUMS(MISSED_DEADLINE_TRANSIENT);
+COMPARE_ENUMS(MISSED_DEADLINE_PERSISTENT);
+COMPARE_ENUMS(RESOURCE_EXHAUSTED_TRANSIENT);
+COMPARE_ENUMS(RESOURCE_EXHAUSTED_PERSISTENT);
+
+#undef COMPARE_ENUMS
+
+#undef COMPARE_ENUMS_FULL
+
+}  // anonymous namespace
diff --git a/neuralnetworks/1.3/utils/src/Conversions.cpp b/neuralnetworks/1.3/utils/src/Conversions.cpp
new file mode 100644
index 0000000..4c54e3b
--- /dev/null
+++ b/neuralnetworks/1.3/utils/src/Conversions.cpp
@@ -0,0 +1,552 @@
+/*
+ * 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 "Conversions.h"
+
+#include <android-base/logging.h>
+#include <android/hardware/neuralnetworks/1.3/types.h>
+#include <nnapi/OperandTypes.h>
+#include <nnapi/OperationTypes.h>
+#include <nnapi/Result.h>
+#include <nnapi/SharedMemory.h>
+#include <nnapi/TypeUtils.h>
+#include <nnapi/Types.h>
+#include <nnapi/hal/1.0/Conversions.h>
+#include <nnapi/hal/1.2/Conversions.h>
+#include <nnapi/hal/CommonUtils.h>
+
+#include <algorithm>
+#include <chrono>
+#include <functional>
+#include <iterator>
+#include <limits>
+#include <type_traits>
+#include <utility>
+
+namespace {
+
+template <typename Type>
+constexpr std::underlying_type_t<Type> underlyingType(Type value) {
+    return static_cast<std::underlying_type_t<Type>>(value);
+}
+
+}  // namespace
+
+namespace android::nn {
+namespace {
+
+constexpr auto validOperandType(nn::OperandType operandType) {
+    switch (operandType) {
+        case nn::OperandType::FLOAT32:
+        case nn::OperandType::INT32:
+        case nn::OperandType::UINT32:
+        case nn::OperandType::TENSOR_FLOAT32:
+        case nn::OperandType::TENSOR_INT32:
+        case nn::OperandType::TENSOR_QUANT8_ASYMM:
+        case nn::OperandType::BOOL:
+        case nn::OperandType::TENSOR_QUANT16_SYMM:
+        case nn::OperandType::TENSOR_FLOAT16:
+        case nn::OperandType::TENSOR_BOOL8:
+        case nn::OperandType::FLOAT16:
+        case nn::OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL:
+        case nn::OperandType::TENSOR_QUANT16_ASYMM:
+        case nn::OperandType::TENSOR_QUANT8_SYMM:
+        case nn::OperandType::TENSOR_QUANT8_ASYMM_SIGNED:
+        case nn::OperandType::SUBGRAPH:
+        case nn::OperandType::OEM:
+        case nn::OperandType::TENSOR_OEM_BYTE:
+            return true;
+    }
+    return nn::isExtension(operandType);
+}
+
+using hardware::hidl_vec;
+
+template <typename Input>
+using ConvertOutput = std::decay_t<decltype(convert(std::declval<Input>()).value())>;
+
+template <typename Type>
+Result<std::vector<ConvertOutput<Type>>> convertVec(const hidl_vec<Type>& arguments) {
+    std::vector<ConvertOutput<Type>> canonical;
+    canonical.reserve(arguments.size());
+    for (const auto& argument : arguments) {
+        canonical.push_back(NN_TRY(nn::convert(argument)));
+    }
+    return canonical;
+}
+
+template <typename Type>
+Result<std::vector<ConvertOutput<Type>>> convert(const hidl_vec<Type>& arguments) {
+    return convertVec(arguments);
+}
+
+}  // anonymous namespace
+
+Result<OperandType> convert(const hal::V1_3::OperandType& operandType) {
+    return static_cast<OperandType>(operandType);
+}
+
+Result<OperationType> convert(const hal::V1_3::OperationType& operationType) {
+    return static_cast<OperationType>(operationType);
+}
+
+Result<Priority> convert(const hal::V1_3::Priority& priority) {
+    return static_cast<Priority>(priority);
+}
+
+Result<Capabilities> convert(const hal::V1_3::Capabilities& capabilities) {
+    const bool validOperandTypes = std::all_of(
+            capabilities.operandPerformance.begin(), capabilities.operandPerformance.end(),
+            [](const hal::V1_3::Capabilities::OperandPerformance& operandPerformance) {
+                const auto maybeType = convert(operandPerformance.type);
+                return !maybeType.has_value() ? false : validOperandType(maybeType.value());
+            });
+    if (!validOperandTypes) {
+        return NN_ERROR()
+               << "Invalid OperandType when converting OperandPerformance in Capabilities";
+    }
+
+    auto operandPerformance = NN_TRY(convert(capabilities.operandPerformance));
+    auto table =
+            NN_TRY(Capabilities::OperandPerformanceTable::create(std::move(operandPerformance)));
+
+    return Capabilities{
+            .relaxedFloat32toFloat16PerformanceScalar =
+                    NN_TRY(convert(capabilities.relaxedFloat32toFloat16PerformanceScalar)),
+            .relaxedFloat32toFloat16PerformanceTensor =
+                    NN_TRY(convert(capabilities.relaxedFloat32toFloat16PerformanceTensor)),
+            .operandPerformance = std::move(table),
+            .ifPerformance = NN_TRY(convert(capabilities.ifPerformance)),
+            .whilePerformance = NN_TRY(convert(capabilities.whilePerformance)),
+    };
+}
+
+Result<Capabilities::OperandPerformance> convert(
+        const hal::V1_3::Capabilities::OperandPerformance& operandPerformance) {
+    return Capabilities::OperandPerformance{
+            .type = NN_TRY(convert(operandPerformance.type)),
+            .info = NN_TRY(convert(operandPerformance.info)),
+    };
+}
+
+Result<Operation> convert(const hal::V1_3::Operation& operation) {
+    return Operation{
+            .type = NN_TRY(convert(operation.type)),
+            .inputs = operation.inputs,
+            .outputs = operation.outputs,
+    };
+}
+
+Result<Operand::LifeTime> convert(const hal::V1_3::OperandLifeTime& operandLifeTime) {
+    return static_cast<Operand::LifeTime>(operandLifeTime);
+}
+
+Result<Operand> convert(const hal::V1_3::Operand& operand) {
+    return Operand{
+            .type = NN_TRY(convert(operand.type)),
+            .dimensions = operand.dimensions,
+            .scale = operand.scale,
+            .zeroPoint = operand.zeroPoint,
+            .lifetime = NN_TRY(convert(operand.lifetime)),
+            .location = NN_TRY(convert(operand.location)),
+            .extraParams = NN_TRY(convert(operand.extraParams)),
+    };
+}
+
+Result<Model> convert(const hal::V1_3::Model& model) {
+    return Model{
+            .main = NN_TRY(convert(model.main)),
+            .referenced = NN_TRY(convert(model.referenced)),
+            .operandValues = NN_TRY(convert(model.operandValues)),
+            .pools = NN_TRY(convert(model.pools)),
+            .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16,
+            .extensionNameToPrefix = NN_TRY(convert(model.extensionNameToPrefix)),
+    };
+}
+
+Result<Model::Subgraph> convert(const hal::V1_3::Subgraph& subgraph) {
+    auto operations = NN_TRY(convert(subgraph.operations));
+
+    // Verify number of consumers.
+    const auto numberOfConsumers =
+            hal::utils::countNumberOfConsumers(subgraph.operands.size(), operations);
+    CHECK(subgraph.operands.size() == numberOfConsumers.size());
+    for (size_t i = 0; i < subgraph.operands.size(); ++i) {
+        if (subgraph.operands[i].numberOfConsumers != numberOfConsumers[i]) {
+            return NN_ERROR() << "Invalid numberOfConsumers for operand " << i << ", expected "
+                              << numberOfConsumers[i] << " but found "
+                              << subgraph.operands[i].numberOfConsumers;
+        }
+    }
+
+    return Model::Subgraph{
+            .operands = NN_TRY(convert(subgraph.operands)),
+            .operations = std::move(operations),
+            .inputIndexes = subgraph.inputIndexes,
+            .outputIndexes = subgraph.outputIndexes,
+    };
+}
+
+Result<BufferDesc> convert(const hal::V1_3::BufferDesc& bufferDesc) {
+    return BufferDesc{.dimensions = bufferDesc.dimensions};
+}
+
+Result<BufferRole> convert(const hal::V1_3::BufferRole& bufferRole) {
+    return BufferRole{
+            .modelIndex = bufferRole.modelIndex,
+            .ioIndex = bufferRole.ioIndex,
+            .frequency = bufferRole.frequency,
+    };
+}
+
+Result<Request> convert(const hal::V1_3::Request& request) {
+    return Request{
+            .inputs = NN_TRY(convert(request.inputs)),
+            .outputs = NN_TRY(convert(request.outputs)),
+            .pools = NN_TRY(convert(request.pools)),
+    };
+}
+
+Result<Request::MemoryPool> convert(const hal::V1_3::Request::MemoryPool& memoryPool) {
+    using Discriminator = hal::V1_3::Request::MemoryPool::hidl_discriminator;
+    switch (memoryPool.getDiscriminator()) {
+        case Discriminator::hidlMemory:
+            return createSharedMemoryFromHidlMemory(memoryPool.hidlMemory());
+        case Discriminator::token:
+            return static_cast<Request::MemoryDomainToken>(memoryPool.token());
+    }
+    return NN_ERROR() << "Invalid Request::MemoryPool discriminator "
+                      << underlyingType(memoryPool.getDiscriminator());
+}
+
+Result<OptionalTimePoint> convert(const hal::V1_3::OptionalTimePoint& optionalTimePoint) {
+    constexpr auto kTimePointMaxCount = TimePoint::max().time_since_epoch().count();
+    const auto makeTimePoint = [](uint64_t count) -> Result<OptionalTimePoint> {
+        if (count > kTimePointMaxCount) {
+            return NN_ERROR()
+                   << "Unable to convert OptionalTimePoint because the count exceeds the max";
+        }
+        const auto nanoseconds = std::chrono::nanoseconds{count};
+        return TimePoint{nanoseconds};
+    };
+
+    using Discriminator = hal::V1_3::OptionalTimePoint::hidl_discriminator;
+    switch (optionalTimePoint.getDiscriminator()) {
+        case Discriminator::none:
+            return std::nullopt;
+        case Discriminator::nanosecondsSinceEpoch:
+            return makeTimePoint(optionalTimePoint.nanosecondsSinceEpoch());
+    }
+    return NN_ERROR() << "Invalid OptionalTimePoint discriminator "
+                      << underlyingType(optionalTimePoint.getDiscriminator());
+}
+
+Result<OptionalTimeoutDuration> convert(
+        const hal::V1_3::OptionalTimeoutDuration& optionalTimeoutDuration) {
+    constexpr auto kTimeoutDurationMaxCount = TimeoutDuration::max().count();
+    const auto makeTimeoutDuration = [](uint64_t count) -> Result<OptionalTimeoutDuration> {
+        if (count > kTimeoutDurationMaxCount) {
+            return NN_ERROR()
+                   << "Unable to convert OptionalTimeoutDuration because the count exceeds the max";
+        }
+        return TimeoutDuration{count};
+    };
+
+    using Discriminator = hal::V1_3::OptionalTimeoutDuration::hidl_discriminator;
+    switch (optionalTimeoutDuration.getDiscriminator()) {
+        case Discriminator::none:
+            return std::nullopt;
+        case Discriminator::nanoseconds:
+            return makeTimeoutDuration(optionalTimeoutDuration.nanoseconds());
+    }
+    return NN_ERROR() << "Invalid OptionalTimeoutDuration discriminator "
+                      << underlyingType(optionalTimeoutDuration.getDiscriminator());
+}
+
+Result<ErrorStatus> convert(const hal::V1_3::ErrorStatus& status) {
+    switch (status) {
+        case hal::V1_3::ErrorStatus::NONE:
+        case hal::V1_3::ErrorStatus::DEVICE_UNAVAILABLE:
+        case hal::V1_3::ErrorStatus::GENERAL_FAILURE:
+        case hal::V1_3::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE:
+        case hal::V1_3::ErrorStatus::INVALID_ARGUMENT:
+        case hal::V1_3::ErrorStatus::MISSED_DEADLINE_TRANSIENT:
+        case hal::V1_3::ErrorStatus::MISSED_DEADLINE_PERSISTENT:
+        case hal::V1_3::ErrorStatus::RESOURCE_EXHAUSTED_TRANSIENT:
+        case hal::V1_3::ErrorStatus::RESOURCE_EXHAUSTED_PERSISTENT:
+            return static_cast<ErrorStatus>(status);
+    }
+    return NN_ERROR() << "Invalid ErrorStatus " << underlyingType(status);
+}
+
+Result<std::vector<BufferRole>> convert(
+        const hardware::hidl_vec<hal::V1_3::BufferRole>& bufferRoles) {
+    return convertVec(bufferRoles);
+}
+
+}  // namespace android::nn
+
+namespace android::hardware::neuralnetworks::V1_3::utils {
+namespace {
+
+using utils::convert;
+
+nn::Result<V1_0::PerformanceInfo> convert(
+        const nn::Capabilities::PerformanceInfo& performanceInfo) {
+    return V1_0::utils::convert(performanceInfo);
+}
+
+nn::Result<V1_0::DataLocation> convert(const nn::DataLocation& dataLocation) {
+    return V1_0::utils::convert(dataLocation);
+}
+
+nn::Result<hidl_vec<uint8_t>> convert(const nn::Model::OperandValues& operandValues) {
+    return V1_0::utils::convert(operandValues);
+}
+
+nn::Result<hidl_memory> convert(const nn::Memory& memory) {
+    return V1_0::utils::convert(memory);
+}
+
+nn::Result<V1_0::RequestArgument> convert(const nn::Request::Argument& argument) {
+    return V1_0::utils::convert(argument);
+}
+
+nn::Result<V1_2::Operand::ExtraParams> convert(const nn::Operand::ExtraParams& extraParams) {
+    return V1_2::utils::convert(extraParams);
+}
+
+nn::Result<V1_2::Model::ExtensionNameAndPrefix> convert(
+        const nn::Model::ExtensionNameAndPrefix& extensionNameAndPrefix) {
+    return V1_2::utils::convert(extensionNameAndPrefix);
+}
+
+template <typename Input>
+using ConvertOutput = std::decay_t<decltype(convert(std::declval<Input>()).value())>;
+
+template <typename Type>
+nn::Result<hidl_vec<ConvertOutput<Type>>> convertVec(const std::vector<Type>& arguments) {
+    hidl_vec<ConvertOutput<Type>> halObject(arguments.size());
+    for (size_t i = 0; i < arguments.size(); ++i) {
+        halObject[i] = NN_TRY(convert(arguments[i]));
+    }
+    return halObject;
+}
+
+template <typename Type>
+nn::Result<hidl_vec<ConvertOutput<Type>>> convert(const std::vector<Type>& arguments) {
+    return convertVec(arguments);
+}
+
+nn::Result<Request::MemoryPool> makeMemoryPool(const nn::Memory& memory) {
+    Request::MemoryPool ret;
+    ret.hidlMemory(NN_TRY(convert(memory)));
+    return ret;
+}
+
+nn::Result<Request::MemoryPool> makeMemoryPool(const nn::Request::MemoryDomainToken& token) {
+    Request::MemoryPool ret;
+    ret.token(underlyingType(token));
+    return ret;
+}
+
+nn::Result<Request::MemoryPool> makeMemoryPool(
+        const std::shared_ptr<const nn::IBuffer>& /*buffer*/) {
+    return NN_ERROR() << "Unable to make memory pool from IBuffer";
+}
+
+}  // anonymous namespace
+
+nn::Result<OperandType> convert(const nn::OperandType& operandType) {
+    return static_cast<OperandType>(operandType);
+}
+
+nn::Result<OperationType> convert(const nn::OperationType& operationType) {
+    return static_cast<OperationType>(operationType);
+}
+
+nn::Result<Priority> convert(const nn::Priority& priority) {
+    return static_cast<Priority>(priority);
+}
+
+nn::Result<Capabilities> convert(const nn::Capabilities& capabilities) {
+    std::vector<nn::Capabilities::OperandPerformance> operandPerformance;
+    operandPerformance.reserve(capabilities.operandPerformance.asVector().size());
+    std::copy_if(capabilities.operandPerformance.asVector().begin(),
+                 capabilities.operandPerformance.asVector().end(),
+                 std::back_inserter(operandPerformance),
+                 [](const nn::Capabilities::OperandPerformance& operandPerformance) {
+                     return nn::validOperandType(operandPerformance.type);
+                 });
+
+    return Capabilities{
+            .relaxedFloat32toFloat16PerformanceScalar =
+                    NN_TRY(convert(capabilities.relaxedFloat32toFloat16PerformanceScalar)),
+            .relaxedFloat32toFloat16PerformanceTensor =
+                    NN_TRY(convert(capabilities.relaxedFloat32toFloat16PerformanceTensor)),
+            .operandPerformance = NN_TRY(convert(operandPerformance)),
+            .ifPerformance = NN_TRY(convert(capabilities.ifPerformance)),
+            .whilePerformance = NN_TRY(convert(capabilities.whilePerformance)),
+    };
+}
+
+nn::Result<Capabilities::OperandPerformance> convert(
+        const nn::Capabilities::OperandPerformance& operandPerformance) {
+    return Capabilities::OperandPerformance{
+            .type = NN_TRY(convert(operandPerformance.type)),
+            .info = NN_TRY(convert(operandPerformance.info)),
+    };
+}
+
+nn::Result<Operation> convert(const nn::Operation& operation) {
+    return Operation{
+            .type = NN_TRY(convert(operation.type)),
+            .inputs = operation.inputs,
+            .outputs = operation.outputs,
+    };
+}
+
+nn::Result<OperandLifeTime> convert(const nn::Operand::LifeTime& operandLifeTime) {
+    if (operandLifeTime == nn::Operand::LifeTime::POINTER) {
+        return NN_ERROR() << "Model cannot be converted because it contains pointer-based memory";
+    }
+    return static_cast<OperandLifeTime>(operandLifeTime);
+}
+
+nn::Result<Operand> convert(const nn::Operand& operand) {
+    return Operand{
+            .type = NN_TRY(convert(operand.type)),
+            .dimensions = operand.dimensions,
+            .numberOfConsumers = 0,
+            .scale = operand.scale,
+            .zeroPoint = operand.zeroPoint,
+            .lifetime = NN_TRY(convert(operand.lifetime)),
+            .location = NN_TRY(convert(operand.location)),
+            .extraParams = NN_TRY(convert(operand.extraParams)),
+    };
+}
+
+nn::Result<Model> convert(const nn::Model& model) {
+    if (!hal::utils::hasNoPointerData(model)) {
+        return NN_ERROR() << "Model cannot be converted because it contains pointer-based memory";
+    }
+
+    return Model{
+            .main = NN_TRY(convert(model.main)),
+            .referenced = NN_TRY(convert(model.referenced)),
+            .operandValues = NN_TRY(convert(model.operandValues)),
+            .pools = NN_TRY(convert(model.pools)),
+            .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16,
+            .extensionNameToPrefix = NN_TRY(convert(model.extensionNameToPrefix)),
+    };
+}
+
+nn::Result<Subgraph> convert(const nn::Model::Subgraph& subgraph) {
+    auto operands = NN_TRY(convert(subgraph.operands));
+
+    // Update number of consumers.
+    const auto numberOfConsumers =
+            hal::utils::countNumberOfConsumers(operands.size(), subgraph.operations);
+    CHECK(operands.size() == numberOfConsumers.size());
+    for (size_t i = 0; i < operands.size(); ++i) {
+        operands[i].numberOfConsumers = numberOfConsumers[i];
+    }
+
+    return Subgraph{
+            .operands = std::move(operands),
+            .operations = NN_TRY(convert(subgraph.operations)),
+            .inputIndexes = subgraph.inputIndexes,
+            .outputIndexes = subgraph.outputIndexes,
+    };
+}
+
+nn::Result<BufferDesc> convert(const nn::BufferDesc& bufferDesc) {
+    return BufferDesc{.dimensions = bufferDesc.dimensions};
+}
+
+nn::Result<BufferRole> convert(const nn::BufferRole& bufferRole) {
+    return BufferRole{
+            .modelIndex = bufferRole.modelIndex,
+            .ioIndex = bufferRole.ioIndex,
+            .frequency = bufferRole.frequency,
+    };
+}
+
+nn::Result<Request> convert(const nn::Request& request) {
+    if (!hal::utils::hasNoPointerData(request)) {
+        return NN_ERROR() << "Request cannot be converted because it contains pointer-based memory";
+    }
+
+    return Request{
+            .inputs = NN_TRY(convert(request.inputs)),
+            .outputs = NN_TRY(convert(request.outputs)),
+            .pools = NN_TRY(convert(request.pools)),
+    };
+}
+
+nn::Result<Request::MemoryPool> convert(const nn::Request::MemoryPool& memoryPool) {
+    return std::visit([](const auto& o) { return makeMemoryPool(o); }, memoryPool);
+}
+
+nn::Result<OptionalTimePoint> convert(const nn::OptionalTimePoint& optionalTimePoint) {
+    OptionalTimePoint ret;
+    if (optionalTimePoint.has_value()) {
+        const auto count = optionalTimePoint.value().time_since_epoch().count();
+        if (count < 0) {
+            return NN_ERROR() << "Unable to convert OptionalTimePoint because time since epoch "
+                                 "count is negative";
+        }
+        ret.nanosecondsSinceEpoch(count);
+    }
+    return ret;
+}
+
+nn::Result<OptionalTimeoutDuration> convert(
+        const nn::OptionalTimeoutDuration& optionalTimeoutDuration) {
+    OptionalTimeoutDuration ret;
+    if (optionalTimeoutDuration.has_value()) {
+        const auto count = optionalTimeoutDuration.value().count();
+        if (count < 0) {
+            return NN_ERROR()
+                   << "Unable to convert OptionalTimeoutDuration because count is negative";
+        }
+        ret.nanoseconds(count);
+    }
+    return ret;
+}
+
+nn::Result<ErrorStatus> convert(const nn::ErrorStatus& errorStatus) {
+    switch (errorStatus) {
+        case nn::ErrorStatus::NONE:
+        case nn::ErrorStatus::DEVICE_UNAVAILABLE:
+        case nn::ErrorStatus::GENERAL_FAILURE:
+        case nn::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE:
+        case nn::ErrorStatus::INVALID_ARGUMENT:
+        case nn::ErrorStatus::MISSED_DEADLINE_TRANSIENT:
+        case nn::ErrorStatus::MISSED_DEADLINE_PERSISTENT:
+        case nn::ErrorStatus::RESOURCE_EXHAUSTED_TRANSIENT:
+        case nn::ErrorStatus::RESOURCE_EXHAUSTED_PERSISTENT:
+            return static_cast<ErrorStatus>(errorStatus);
+        default:
+            return ErrorStatus::GENERAL_FAILURE;
+    }
+}
+
+nn::Result<hidl_vec<BufferRole>> convert(const std::vector<nn::BufferRole>& bufferRoles) {
+    return convertVec(bufferRoles);
+}
+
+}  // namespace android::hardware::neuralnetworks::V1_3::utils
diff --git a/neuralnetworks/utils/OWNERS b/neuralnetworks/utils/OWNERS
new file mode 100644
index 0000000..e4feee3
--- /dev/null
+++ b/neuralnetworks/utils/OWNERS
@@ -0,0 +1,11 @@
+# Neuralnetworks team
+butlermichael@google.com
+dgross@google.com
+galarragas@google.com
+jeanluc@google.com
+levp@google.com
+miaowang@google.com
+pszczepaniak@google.com
+slavash@google.com
+vddang@google.com
+xusongw@google.com
diff --git a/powerstats/aidl/vts/Android.bp b/neuralnetworks/utils/common/Android.bp
similarity index 65%
copy from powerstats/aidl/vts/Android.bp
copy to neuralnetworks/utils/common/Android.bp
index c61022e..b61dc97 100644
--- a/powerstats/aidl/vts/Android.bp
+++ b/neuralnetworks/utils/common/Android.bp
@@ -1,3 +1,4 @@
+//
 // Copyright (C) 2020 The Android Open Source Project
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
@@ -11,22 +12,18 @@
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 // See the License for the specific language governing permissions and
 // limitations under the License.
+//
 
-cc_test {
-    name: "VtsHalPowerStatsTargetTest",
-    defaults: [
-        "VtsHalTargetTestDefaults",
-        "use_libaidlvintf_gtest_helper_static",
-    ],
-    srcs: ["VtsHalPowerStatsTargetTest.cpp"],
-    shared_libs: [
-        "libbinder_ndk",
-    ],
+cc_library_static {
+    name: "neuralnetworks_utils_hal_common",
+    defaults: ["neuralnetworks_utils_defaults"],
+    srcs: ["src/*"],
+    local_include_dirs: ["include/nnapi/hal"],
+    export_include_dirs: ["include"],
     static_libs: [
-        "android.hardware.powerstats-ndk_platform",
+        "neuralnetworks_types",
     ],
-    test_suites: [
-        "general-tests",
-        "vts",
+    shared_libs: [
+        "libhidlbase",
     ],
 }
diff --git a/neuralnetworks/utils/common/include/nnapi/hal/CommonUtils.h b/neuralnetworks/utils/common/include/nnapi/hal/CommonUtils.h
new file mode 100644
index 0000000..8c01368
--- /dev/null
+++ b/neuralnetworks/utils/common/include/nnapi/hal/CommonUtils.h
@@ -0,0 +1,59 @@
+/*
+ * 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_COMMON_UTILS_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_COMMON_UTILS_H
+
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+#include <vector>
+
+// Shorthand
+namespace android::hardware::neuralnetworks {
+namespace hal = ::android::hardware::neuralnetworks;
+}  // namespace android::hardware::neuralnetworks
+
+// Shorthand
+namespace android::nn {
+namespace hal = ::android::hardware::neuralnetworks;
+}
+
+namespace android::hardware::neuralnetworks::utils {
+
+nn::Capabilities::OperandPerformanceTable makeQuantized8PerformanceConsistentWithP(
+        const nn::Capabilities::PerformanceInfo& float32Performance,
+        const nn::Capabilities::PerformanceInfo& quantized8Performance);
+
+// Indicates if the object contains no pointer-based data that could be relocated to shared memory.
+bool hasNoPointerData(const nn::Model& model);
+bool hasNoPointerData(const nn::Request& request);
+
+// Relocate pointer-based data to shared memory.
+nn::Result<nn::Model> flushDataFromPointerToShared(const nn::Model& model);
+nn::Result<nn::Request> flushDataFromPointerToShared(const nn::Request& request);
+
+// Undoes `flushDataFromPointerToShared` on a Request object. More specifically,
+// `unflushDataFromSharedToPointer` copies the output shared memory data from the transformed
+// Request object back to the output pointer-based memory in the original Request object.
+nn::Result<void> unflushDataFromSharedToPointer(const nn::Request& request,
+                                                const nn::Request& requestInShared);
+
+std::vector<uint32_t> countNumberOfConsumers(size_t numberOfOperands,
+                                             const std::vector<nn::Operation>& operations);
+
+}  // namespace android::hardware::neuralnetworks::utils
+
+#endif  // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_COMMON_UTILS_H
diff --git a/neuralnetworks/utils/common/src/CommonUtils.cpp b/neuralnetworks/utils/common/src/CommonUtils.cpp
new file mode 100644
index 0000000..667189b
--- /dev/null
+++ b/neuralnetworks/utils/common/src/CommonUtils.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.
+ */
+
+#include "CommonUtils.h"
+
+#include <android-base/logging.h>
+#include <nnapi/Result.h>
+#include <nnapi/SharedMemory.h>
+#include <nnapi/TypeUtils.h>
+#include <nnapi/Types.h>
+#include <nnapi/Validation.h>
+
+#include <algorithm>
+#include <any>
+#include <optional>
+#include <variant>
+#include <vector>
+
+namespace android::hardware::neuralnetworks::utils {
+namespace {
+
+bool hasNoPointerData(const nn::Operand& operand);
+bool hasNoPointerData(const nn::Model::Subgraph& subgraph);
+bool hasNoPointerData(const nn::Request::Argument& argument);
+
+template <typename Type>
+bool hasNoPointerData(const std::vector<Type>& objects) {
+    return std::all_of(objects.begin(), objects.end(),
+                       [](const auto& object) { return hasNoPointerData(object); });
+}
+
+bool hasNoPointerData(const nn::DataLocation& location) {
+    return std::visit([](auto ptr) { return ptr == nullptr; }, location.pointer);
+}
+
+bool hasNoPointerData(const nn::Operand& operand) {
+    return hasNoPointerData(operand.location);
+}
+
+bool hasNoPointerData(const nn::Model::Subgraph& subgraph) {
+    return hasNoPointerData(subgraph.operands);
+}
+
+bool hasNoPointerData(const nn::Request::Argument& argument) {
+    return hasNoPointerData(argument.location);
+}
+
+void copyPointersToSharedMemory(nn::Operand* operand, nn::ConstantMemoryBuilder* memoryBuilder) {
+    CHECK(operand != nullptr);
+    CHECK(memoryBuilder != nullptr);
+
+    if (operand->lifetime != nn::Operand::LifeTime::POINTER) {
+        return;
+    }
+
+    const void* data = std::visit([](auto ptr) { return static_cast<const void*>(ptr); },
+                                  operand->location.pointer);
+    CHECK(data != nullptr);
+    operand->lifetime = nn::Operand::LifeTime::CONSTANT_REFERENCE;
+    operand->location = memoryBuilder->append(data, operand->location.length);
+}
+
+void copyPointersToSharedMemory(nn::Model::Subgraph* subgraph,
+                                nn::ConstantMemoryBuilder* memoryBuilder) {
+    CHECK(subgraph != nullptr);
+    std::for_each(subgraph->operands.begin(), subgraph->operands.end(),
+                  [memoryBuilder](auto& operand) {
+                      copyPointersToSharedMemory(&operand, memoryBuilder);
+                  });
+}
+
+}  // anonymous namespace
+
+nn::Capabilities::OperandPerformanceTable makeQuantized8PerformanceConsistentWithP(
+        const nn::Capabilities::PerformanceInfo& float32Performance,
+        const nn::Capabilities::PerformanceInfo& quantized8Performance) {
+    // In Android P, most data types are treated as having the same performance as
+    // TENSOR_QUANT8_ASYMM. This collection must be in sorted order.
+    std::vector<nn::Capabilities::OperandPerformance> operandPerformances = {
+            {.type = nn::OperandType::FLOAT32, .info = float32Performance},
+            {.type = nn::OperandType::INT32, .info = quantized8Performance},
+            {.type = nn::OperandType::UINT32, .info = quantized8Performance},
+            {.type = nn::OperandType::TENSOR_FLOAT32, .info = float32Performance},
+            {.type = nn::OperandType::TENSOR_INT32, .info = quantized8Performance},
+            {.type = nn::OperandType::TENSOR_QUANT8_ASYMM, .info = quantized8Performance},
+            {.type = nn::OperandType::OEM, .info = quantized8Performance},
+            {.type = nn::OperandType::TENSOR_OEM_BYTE, .info = quantized8Performance},
+    };
+    return nn::Capabilities::OperandPerformanceTable::create(std::move(operandPerformances))
+            .value();
+}
+
+bool hasNoPointerData(const nn::Model& model) {
+    return hasNoPointerData(model.main) && hasNoPointerData(model.referenced);
+}
+
+bool hasNoPointerData(const nn::Request& request) {
+    return hasNoPointerData(request.inputs) && hasNoPointerData(request.outputs);
+}
+
+nn::Result<nn::Model> flushDataFromPointerToShared(const nn::Model& model) {
+    auto modelInShared = model;
+
+    nn::ConstantMemoryBuilder memoryBuilder(modelInShared.pools.size());
+    copyPointersToSharedMemory(&modelInShared.main, &memoryBuilder);
+    std::for_each(modelInShared.referenced.begin(), modelInShared.referenced.end(),
+                  [&memoryBuilder](auto& subgraph) {
+                      copyPointersToSharedMemory(&subgraph, &memoryBuilder);
+                  });
+
+    if (!memoryBuilder.empty()) {
+        auto memory = NN_TRY(memoryBuilder.finish());
+        modelInShared.pools.push_back(std::move(memory));
+    }
+
+    return modelInShared;
+}
+
+nn::Result<nn::Request> flushDataFromPointerToShared(const nn::Request& request) {
+    auto requestInShared = request;
+
+    // Change input pointers to shared memory.
+    nn::ConstantMemoryBuilder inputBuilder(requestInShared.pools.size());
+    for (auto& input : requestInShared.inputs) {
+        const auto& location = input.location;
+        if (input.lifetime != nn::Request::Argument::LifeTime::POINTER) {
+            continue;
+        }
+
+        input.lifetime = nn::Request::Argument::LifeTime::POOL;
+        const void* data = std::visit([](auto ptr) { return static_cast<const void*>(ptr); },
+                                      location.pointer);
+        CHECK(data != nullptr);
+        input.location = inputBuilder.append(data, location.length);
+    }
+
+    // Allocate input memory.
+    if (!inputBuilder.empty()) {
+        auto memory = NN_TRY(inputBuilder.finish());
+        requestInShared.pools.push_back(std::move(memory));
+    }
+
+    // Change output pointers to shared memory.
+    nn::MutableMemoryBuilder outputBuilder(requestInShared.pools.size());
+    for (auto& output : requestInShared.outputs) {
+        const auto& location = output.location;
+        if (output.lifetime != nn::Request::Argument::LifeTime::POINTER) {
+            continue;
+        }
+
+        output.lifetime = nn::Request::Argument::LifeTime::POOL;
+        output.location = outputBuilder.append(location.length);
+    }
+
+    // Allocate output memory.
+    if (!outputBuilder.empty()) {
+        auto memory = NN_TRY(outputBuilder.finish());
+        requestInShared.pools.push_back(std::move(memory));
+    }
+
+    return requestInShared;
+}
+
+nn::Result<void> unflushDataFromSharedToPointer(const nn::Request& request,
+                                                const nn::Request& requestInShared) {
+    if (requestInShared.pools.empty() ||
+        !std::holds_alternative<nn::Memory>(requestInShared.pools.back())) {
+        return {};
+    }
+
+    // Map the memory.
+    const auto& outputMemory = std::get<nn::Memory>(requestInShared.pools.back());
+    const auto [pointer, size, context] = NN_TRY(map(outputMemory));
+    const uint8_t* constantPointer =
+            std::visit([](const auto& o) { return static_cast<const uint8_t*>(o); }, pointer);
+
+    // Flush each output pointer.
+    CHECK_EQ(request.outputs.size(), requestInShared.outputs.size());
+    for (size_t i = 0; i < request.outputs.size(); ++i) {
+        const auto& location = request.outputs[i].location;
+        const auto& locationInShared = requestInShared.outputs[i].location;
+        if (!std::holds_alternative<void*>(location.pointer)) {
+            continue;
+        }
+
+        // Get output pointer and size.
+        void* data = std::get<void*>(location.pointer);
+        CHECK(data != nullptr);
+        const size_t length = location.length;
+
+        // Get output pool location.
+        CHECK(requestInShared.outputs[i].lifetime == nn::Request::Argument::LifeTime::POOL);
+        const size_t index = locationInShared.poolIndex;
+        const size_t offset = locationInShared.offset;
+        const size_t outputPoolIndex = requestInShared.pools.size() - 1;
+        CHECK(locationInShared.length == length);
+        CHECK(index == outputPoolIndex);
+
+        // Flush memory.
+        std::memcpy(data, constantPointer + offset, length);
+    }
+
+    return {};
+}
+
+std::vector<uint32_t> countNumberOfConsumers(size_t numberOfOperands,
+                                             const std::vector<nn::Operation>& operations) {
+    return nn::countNumberOfConsumers(numberOfOperands, operations);
+}
+
+}  // namespace android::hardware::neuralnetworks::utils
diff --git a/powerstats/aidl/Android.bp b/power/stats/aidl/Android.bp
similarity index 91%
rename from powerstats/aidl/Android.bp
rename to power/stats/aidl/Android.bp
index 1aa58cb..1688b12 100644
--- a/powerstats/aidl/Android.bp
+++ b/power/stats/aidl/Android.bp
@@ -13,10 +13,10 @@
 // limitations under the License.
 
 aidl_interface {
-    name: "android.hardware.powerstats",
+    name: "android.hardware.power.stats",
     vendor_available: true,
     srcs: [
-        "android/hardware/powerstats/*.aidl",
+        "android/hardware/power/stats/*.aidl",
     ],
     stability: "vintf",
     backend: {
diff --git a/common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/UnsynchronizedWrite.aidl b/power/stats/aidl/aidl_api/android.hardware.power.stats/current/android/hardware/power/stats/ChannelInfo.aidl
similarity index 89%
copy from common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/UnsynchronizedWrite.aidl
copy to power/stats/aidl/aidl_api/android.hardware.power.stats/current/android/hardware/power/stats/ChannelInfo.aidl
index e390d20..209bec4 100644
--- a/common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/UnsynchronizedWrite.aidl
+++ b/power/stats/aidl/aidl_api/android.hardware.power.stats/current/android/hardware/power/stats/ChannelInfo.aidl
@@ -15,8 +15,9 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.common;
+package android.hardware.power.stats;
 @VintfStability
-enum UnsynchronizedWrite {
-  EMPTY = 0,
+parcelable ChannelInfo {
+  int channelId;
+  @utf8InCpp String channelName;
 }
diff --git a/common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/UnsynchronizedWrite.aidl b/power/stats/aidl/aidl_api/android.hardware.power.stats/current/android/hardware/power/stats/EnergyConsumerId.aidl
similarity index 88%
copy from common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/UnsynchronizedWrite.aidl
copy to power/stats/aidl/aidl_api/android.hardware.power.stats/current/android/hardware/power/stats/EnergyConsumerId.aidl
index e390d20..7ca3b15 100644
--- a/common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/UnsynchronizedWrite.aidl
+++ b/power/stats/aidl/aidl_api/android.hardware.power.stats/current/android/hardware/power/stats/EnergyConsumerId.aidl
@@ -15,8 +15,9 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.common;
-@VintfStability
-enum UnsynchronizedWrite {
-  EMPTY = 0,
+package android.hardware.power.stats;
+@Backing(type="int") @VintfStability
+enum EnergyConsumerId {
+  DISPLAY = 0,
+  GPS = 1,
 }
diff --git a/powerstats/aidl/aidl_api/android.hardware.powerstats/current/android/hardware/powerstats/EnergyData.aidl b/power/stats/aidl/aidl_api/android.hardware.power.stats/current/android/hardware/power/stats/EnergyConsumerResult.aidl
similarity index 88%
copy from powerstats/aidl/aidl_api/android.hardware.powerstats/current/android/hardware/powerstats/EnergyData.aidl
copy to power/stats/aidl/aidl_api/android.hardware.power.stats/current/android/hardware/power/stats/EnergyConsumerResult.aidl
index 2e384da..6289a08 100644
--- a/powerstats/aidl/aidl_api/android.hardware.powerstats/current/android/hardware/powerstats/EnergyData.aidl
+++ b/power/stats/aidl/aidl_api/android.hardware.power.stats/current/android/hardware/power/stats/EnergyConsumerResult.aidl
@@ -15,10 +15,10 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.powerstats;
+package android.hardware.power.stats;
 @VintfStability
-parcelable EnergyData {
-  int railIndex;
+parcelable EnergyConsumerResult {
+  android.hardware.power.stats.EnergyConsumerId energyConsumerId;
   long timestampMs;
   long energyUWs;
 }
diff --git a/powerstats/aidl/aidl_api/android.hardware.powerstats/current/android/hardware/powerstats/EnergyData.aidl b/power/stats/aidl/aidl_api/android.hardware.power.stats/current/android/hardware/power/stats/EnergyMeasurement.aidl
similarity index 91%
rename from powerstats/aidl/aidl_api/android.hardware.powerstats/current/android/hardware/powerstats/EnergyData.aidl
rename to power/stats/aidl/aidl_api/android.hardware.power.stats/current/android/hardware/power/stats/EnergyMeasurement.aidl
index 2e384da..341909e 100644
--- a/powerstats/aidl/aidl_api/android.hardware.powerstats/current/android/hardware/powerstats/EnergyData.aidl
+++ b/power/stats/aidl/aidl_api/android.hardware.power.stats/current/android/hardware/power/stats/EnergyMeasurement.aidl
@@ -15,10 +15,10 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.powerstats;
+package android.hardware.power.stats;
 @VintfStability
-parcelable EnergyData {
-  int railIndex;
+parcelable EnergyMeasurement {
+  int channelId;
   long timestampMs;
   long energyUWs;
 }
diff --git a/powerstats/aidl/aidl_api/android.hardware.powerstats/current/android/hardware/powerstats/IPowerStats.aidl b/power/stats/aidl/aidl_api/android.hardware.power.stats/current/android/hardware/power/stats/IPowerStats.aidl
similarity index 64%
rename from powerstats/aidl/aidl_api/android.hardware.powerstats/current/android/hardware/powerstats/IPowerStats.aidl
rename to power/stats/aidl/aidl_api/android.hardware.power.stats/current/android/hardware/power/stats/IPowerStats.aidl
index 6772f6f..07013b0 100644
--- a/powerstats/aidl/aidl_api/android.hardware.powerstats/current/android/hardware/powerstats/IPowerStats.aidl
+++ b/power/stats/aidl/aidl_api/android.hardware.power.stats/current/android/hardware/power/stats/IPowerStats.aidl
@@ -15,11 +15,13 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.powerstats;
+package android.hardware.power.stats;
 @VintfStability
 interface IPowerStats {
-  android.hardware.powerstats.EnergyData[] getEnergyData(in int[] railIndices);
-  android.hardware.powerstats.PowerEntityInfo[] getPowerEntityInfo();
-  android.hardware.powerstats.PowerEntityStateResidencyResult[] getPowerEntityStateResidencyData(in int[] powerEntityIds);
-  android.hardware.powerstats.RailInfo[] getRailInfo();
+  android.hardware.power.stats.PowerEntityInfo[] getPowerEntityInfo();
+  android.hardware.power.stats.StateResidencyResult[] getStateResidency(in int[] powerEntityIds);
+  android.hardware.power.stats.EnergyConsumerId[] getEnergyConsumerInfo();
+  android.hardware.power.stats.EnergyConsumerResult[] getEnergyConsumed(in android.hardware.power.stats.EnergyConsumerId[] energyConsumerIds);
+  android.hardware.power.stats.ChannelInfo[] getEnergyMeterInfo();
+  android.hardware.power.stats.EnergyMeasurement[] readEnergyMeters(in int[] channelIds);
 }
diff --git a/powerstats/aidl/aidl_api/android.hardware.powerstats/current/android/hardware/powerstats/PowerEntityInfo.aidl b/power/stats/aidl/aidl_api/android.hardware.power.stats/current/android/hardware/power/stats/PowerEntityInfo.aidl
similarity index 89%
rename from powerstats/aidl/aidl_api/android.hardware.powerstats/current/android/hardware/powerstats/PowerEntityInfo.aidl
rename to power/stats/aidl/aidl_api/android.hardware.power.stats/current/android/hardware/power/stats/PowerEntityInfo.aidl
index 016af91..3b16362 100644
--- a/powerstats/aidl/aidl_api/android.hardware.powerstats/current/android/hardware/powerstats/PowerEntityInfo.aidl
+++ b/power/stats/aidl/aidl_api/android.hardware.power.stats/current/android/hardware/power/stats/PowerEntityInfo.aidl
@@ -15,10 +15,10 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.powerstats;
+package android.hardware.power.stats;
 @VintfStability
 parcelable PowerEntityInfo {
   int powerEntityId;
-  String powerEntityName;
-  android.hardware.powerstats.PowerEntityStateInfo[] states;
+  @utf8InCpp String powerEntityName;
+  android.hardware.power.stats.StateInfo[] states;
 }
diff --git a/common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/UnsynchronizedWrite.aidl b/power/stats/aidl/aidl_api/android.hardware.power.stats/current/android/hardware/power/stats/StateInfo.aidl
similarity index 90%
copy from common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/UnsynchronizedWrite.aidl
copy to power/stats/aidl/aidl_api/android.hardware.power.stats/current/android/hardware/power/stats/StateInfo.aidl
index e390d20..0db9ab1 100644
--- a/common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/UnsynchronizedWrite.aidl
+++ b/power/stats/aidl/aidl_api/android.hardware.power.stats/current/android/hardware/power/stats/StateInfo.aidl
@@ -15,8 +15,9 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.common;
+package android.hardware.power.stats;
 @VintfStability
-enum UnsynchronizedWrite {
-  EMPTY = 0,
+parcelable StateInfo {
+  int stateId;
+  @utf8InCpp String stateName;
 }
diff --git a/powerstats/aidl/aidl_api/android.hardware.powerstats/current/android/hardware/powerstats/PowerEntityStateResidencyData.aidl b/power/stats/aidl/aidl_api/android.hardware.power.stats/current/android/hardware/power/stats/StateResidency.aidl
similarity index 90%
rename from powerstats/aidl/aidl_api/android.hardware.powerstats/current/android/hardware/powerstats/PowerEntityStateResidencyData.aidl
rename to power/stats/aidl/aidl_api/android.hardware.power.stats/current/android/hardware/power/stats/StateResidency.aidl
index 8a3b227..206c974 100644
--- a/powerstats/aidl/aidl_api/android.hardware.powerstats/current/android/hardware/powerstats/PowerEntityStateResidencyData.aidl
+++ b/power/stats/aidl/aidl_api/android.hardware.power.stats/current/android/hardware/power/stats/StateResidency.aidl
@@ -15,10 +15,10 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.powerstats;
+package android.hardware.power.stats;
 @VintfStability
-parcelable PowerEntityStateResidencyData {
-  int powerEntityStateId;
+parcelable StateResidency {
+  int stateId;
   long totalTimeInStateMs;
   long totalStateEntryCount;
   long lastEntryTimestampMs;
diff --git a/powerstats/aidl/aidl_api/android.hardware.powerstats/current/android/hardware/powerstats/PowerEntityStateInfo.aidl b/power/stats/aidl/aidl_api/android.hardware.power.stats/current/android/hardware/power/stats/StateResidencyResult.aidl
similarity index 86%
copy from powerstats/aidl/aidl_api/android.hardware.powerstats/current/android/hardware/powerstats/PowerEntityStateInfo.aidl
copy to power/stats/aidl/aidl_api/android.hardware.power.stats/current/android/hardware/power/stats/StateResidencyResult.aidl
index 9de66ba..dc41fef 100644
--- a/powerstats/aidl/aidl_api/android.hardware.powerstats/current/android/hardware/powerstats/PowerEntityStateInfo.aidl
+++ b/power/stats/aidl/aidl_api/android.hardware.power.stats/current/android/hardware/power/stats/StateResidencyResult.aidl
@@ -15,9 +15,9 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.powerstats;
+package android.hardware.power.stats;
 @VintfStability
-parcelable PowerEntityStateInfo {
-  int powerEntityStateId;
-  String powerEntityStateName;
+parcelable StateResidencyResult {
+  int powerEntityId;
+  android.hardware.power.stats.StateResidency[] stateResidencyData;
 }
diff --git a/powerstats/aidl/android/hardware/powerstats/PowerEntityStateInfo.aidl b/power/stats/aidl/android/hardware/power/stats/ChannelInfo.aidl
similarity index 71%
rename from powerstats/aidl/android/hardware/powerstats/PowerEntityStateInfo.aidl
rename to power/stats/aidl/android/hardware/power/stats/ChannelInfo.aidl
index 69fc798..a2ca6a6 100644
--- a/powerstats/aidl/android/hardware/powerstats/PowerEntityStateInfo.aidl
+++ b/power/stats/aidl/android/hardware/power/stats/ChannelInfo.aidl
@@ -14,17 +14,17 @@
  * limitations under the License.
  */
 
-package android.hardware.powerstats;
+package android.hardware.power.stats;
 
 @VintfStability
-parcelable PowerEntityStateInfo {
+parcelable ChannelInfo {
     /**
-     * ID corresponding to the state. Unique for a given PowerEntityStateSpace
+     * Unique ID of this ChannelInfo
      */
-    int powerEntityStateId;
+    int channelId;
     /**
-     * Name of the state (opaque to the framework)
+     * Unique name of the ChannelInfo. Vendor/device specific. Opaque to framework
      */
-    String powerEntityStateName;
+    @utf8InCpp String channelName;
 }
 
diff --git a/tests/safeunion/1.0/IOtherInterface.hal b/power/stats/aidl/android/hardware/power/stats/EnergyConsumerId.aidl
similarity index 73%
rename from tests/safeunion/1.0/IOtherInterface.hal
rename to power/stats/aidl/android/hardware/power/stats/EnergyConsumerId.aidl
index cdaf847..4a6a677 100644
--- a/tests/safeunion/1.0/IOtherInterface.hal
+++ b/power/stats/aidl/android/hardware/power/stats/EnergyConsumerId.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 The Android Open Source Project
+ * 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.
@@ -14,8 +14,11 @@
  * limitations under the License.
  */
 
-package android.hardware.tests.safeunion@1.0;
+package android.hardware.power.stats;
 
-interface IOtherInterface {
-    concatTwoStrings(string a, string b) generates (string result);
-};
+@VintfStability
+@Backing(type="int")
+enum EnergyConsumerId {
+    DISPLAY = 0,
+    GPS = 1,
+}
\ No newline at end of file
diff --git a/powerstats/aidl/android/hardware/powerstats/EnergyData.aidl b/power/stats/aidl/android/hardware/power/stats/EnergyConsumerResult.aidl
similarity index 68%
copy from powerstats/aidl/android/hardware/powerstats/EnergyData.aidl
copy to power/stats/aidl/android/hardware/power/stats/EnergyConsumerResult.aidl
index ec12c5e..d2b902a 100644
--- a/powerstats/aidl/android/hardware/powerstats/EnergyData.aidl
+++ b/power/stats/aidl/android/hardware/power/stats/EnergyConsumerResult.aidl
@@ -14,21 +14,22 @@
  * limitations under the License.
  */
 
-package android.hardware.powerstats;
+package android.hardware.power.stats;
+
+import android.hardware.power.stats.EnergyConsumerId;
 
 @VintfStability
-parcelable EnergyData {
+parcelable EnergyConsumerResult {
     /**
-     * Index corresponding to the rail. This index matches
-     * the index returned in RailInfo
+     * ID of the EnergyConsumer associated with this result
      */
-    int railIndex;
+    EnergyConsumerId energyConsumerId;
     /**
-     * Time since device boot(CLOCK_BOOTTIME) in milli-seconds
+     * Time since boot in milliseconds
      */
     long timestampMs;
     /**
-     * Accumulated energy since device boot in microwatt-seconds (uWs)
+     * Accumulated energy since boot in microwatt-seconds (uWs)
      */
     long energyUWs;
 }
diff --git a/powerstats/aidl/android/hardware/powerstats/EnergyData.aidl b/power/stats/aidl/android/hardware/power/stats/EnergyMeasurement.aidl
similarity index 69%
rename from powerstats/aidl/android/hardware/powerstats/EnergyData.aidl
rename to power/stats/aidl/android/hardware/power/stats/EnergyMeasurement.aidl
index ec12c5e..f873849 100644
--- a/powerstats/aidl/android/hardware/powerstats/EnergyData.aidl
+++ b/power/stats/aidl/android/hardware/power/stats/EnergyMeasurement.aidl
@@ -14,21 +14,20 @@
  * limitations under the License.
  */
 
-package android.hardware.powerstats;
+package android.hardware.power.stats;
 
 @VintfStability
-parcelable EnergyData {
+parcelable EnergyMeasurement {
     /**
-     * Index corresponding to the rail. This index matches
-     * the index returned in RailInfo
+     * ID of the Channel associated with this measurement
      */
-    int railIndex;
+    int channelId;
     /**
-     * Time since device boot(CLOCK_BOOTTIME) in milli-seconds
+     * Time since boot in milliseconds
      */
     long timestampMs;
     /**
-     * Accumulated energy since device boot in microwatt-seconds (uWs)
+     * Accumulated energy since boot in microwatt-seconds (uWs)
      */
     long energyUWs;
 }
diff --git a/power/stats/aidl/android/hardware/power/stats/IPowerStats.aidl b/power/stats/aidl/android/hardware/power/stats/IPowerStats.aidl
new file mode 100644
index 0000000..85a2ce0
--- /dev/null
+++ b/power/stats/aidl/android/hardware/power/stats/IPowerStats.aidl
@@ -0,0 +1,112 @@
+/*
+ * 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.
+ */
+
+package android.hardware.power.stats;
+
+import android.hardware.power.stats.ChannelInfo;
+import android.hardware.power.stats.EnergyConsumerId;
+import android.hardware.power.stats.EnergyConsumerResult;
+import android.hardware.power.stats.EnergyMeasurement;
+import android.hardware.power.stats.PowerEntityInfo;
+import android.hardware.power.stats.StateResidencyResult;
+
+@VintfStability
+interface IPowerStats {
+    /**
+     * Return information related to all supported PowerEntity(s) for which state residency data
+     * is available.
+     *
+     * A PowerEntity is defined as a platform subsystem, peripheral, or power domain that impacts
+     * the total device power consumption.
+     *
+     * @return List of information on each PowerEntity
+     */
+    PowerEntityInfo[] getPowerEntityInfo();
+
+    /**
+     * Reports the accumulated state residency for each requested PowerEntity.
+     *
+     * Each PowerEntity may reside in one of multiple states. It may also
+     * transition from one state to another. StateResidency is defined as
+     * an accumulation of time that a PowerEntity resided in each
+     * of its possible states, the number of times that each state was
+     * entered, and a timestamp corresponding to the last time that state
+     * was entered.
+     *
+     * Data is accumulated starting at device boot.
+     *
+     * @param powerEntityIds List of IDs of PowerEntities for which data is requested.
+     *     Passing an empty list will return state residency for all available PowerEntitys.
+     *     ID of each PowerEntity is contained in PowerEntityInfo.
+     *
+     * @return StateResidency since boot for each requested PowerEntity
+     *
+     * Returns the following service-specific exceptions in order of highest priority:
+     *  - STATUS_BAD_VALUE if an invalid powerEntityId is provided
+     *  - STATUS_FAILED_TRANSACTION if any StateResidencyResult fails to be returned
+     */
+    StateResidencyResult[] getStateResidency(in int[] powerEntityIds);
+
+    /**
+     * Return the list IDs for all supported EnergyConsumers for which energy consumption data is
+     * available.
+     *
+     * An EnergyConsumer is a device subsystem or peripheral that consumes energy. Energy
+     * consumption data may be used by framework for the purpose of power attribution.
+     *
+     * @return List of EnergyConsumersIds that are available.
+     */
+    EnergyConsumerId[] getEnergyConsumerInfo();
+
+    /**
+     * Reports the energy consumed since boot by each requested EnergyConsumer.
+     *
+     * @param energyConsumerIds List of IDs of EnergyConsumers for which data is requested.
+     *     Passing an empty list will return state residency for all available EnergyConsumers.
+     *
+     * @return Energy consumed since boot for each requested EnergyConsumer
+     *
+     * Returns the following service-specific exceptions in order of highest priority:
+     *  - STATUS_BAD_VALUE if an invalid energyConsumerId is provided
+     *  - STATUS_FAILED_TRANSACTION if any EnergyConsumerResult fails to be returned
+     */
+    EnergyConsumerResult[] getEnergyConsumed(in EnergyConsumerId[] energyConsumerIds);
+
+    /**
+     * Return information related to all channels monitored by Energy Meters.
+     *
+     * An Energy Meter is a device that monitors energy and may support monitoring multiple
+     * channels simultaneously. A channel may correspond a bus, sense resistor, or power rail.
+     *
+     * @return Information about channels monitored by Energy Meters.
+     */
+    ChannelInfo[] getEnergyMeterInfo();
+
+    /**
+     * Reports accumulated energy since boot for each specified channel.
+     *
+     * @param channelIds IDs of channels for which data is requested.
+     *     Passing an empty list will return energy measurements for all available channels.
+     *     ID of each channel is contained in ChannelInfo.
+     *
+     * @return Energy measured since boot for each requested channel
+     *
+     * Returns the following service-specific exceptions in order of highest priority:
+     *  - STATUS_BAD_VALUE if an invalid channelId is provided
+     *  - STATUS_FAILED_TRANSACTION if any EnergyMeasurement fails to be returned
+     */
+    EnergyMeasurement[] readEnergyMeters(in int[] channelIds);
+}
\ No newline at end of file
diff --git a/powerstats/aidl/android/hardware/powerstats/PowerEntityInfo.aidl b/power/stats/aidl/android/hardware/power/stats/PowerEntityInfo.aidl
similarity index 68%
rename from powerstats/aidl/android/hardware/powerstats/PowerEntityInfo.aidl
rename to power/stats/aidl/android/hardware/power/stats/PowerEntityInfo.aidl
index 72222a6..002b343 100644
--- a/powerstats/aidl/android/hardware/powerstats/PowerEntityInfo.aidl
+++ b/power/stats/aidl/android/hardware/power/stats/PowerEntityInfo.aidl
@@ -14,26 +14,22 @@
  * limitations under the License.
  */
 
-package android.hardware.powerstats;
+package android.hardware.power.stats;
 
-import android.hardware.powerstats.PowerEntityStateInfo;
+import android.hardware.power.stats.StateInfo;
 
-/**
- * PowerEntityInfo contains information, such as the ID, name, and type of a
- * given PowerEntity.
- */
 @VintfStability
 parcelable PowerEntityInfo {
     /**
-     * Unique ID corresponding to the PowerEntity
+     * Unique ID of this PowerEntityInfo
      */
     int powerEntityId;
     /**
-     * Name of the PowerEntity (opaque to the framework)
+     * Unique name of the PowerEntity. Vendor/device specific. Opaque to framework
      */
-    String powerEntityName;
+    @utf8InCpp String powerEntityName;
     /**
      * List of states that the PowerEntity may reside in
      */
-    PowerEntityStateInfo[] states;
+    StateInfo[] states;
 }
\ No newline at end of file
diff --git a/powerstats/aidl/android/hardware/powerstats/PowerEntityStateInfo.aidl b/power/stats/aidl/android/hardware/power/stats/StateInfo.aidl
similarity index 69%
copy from powerstats/aidl/android/hardware/powerstats/PowerEntityStateInfo.aidl
copy to power/stats/aidl/android/hardware/power/stats/StateInfo.aidl
index 69fc798..5703f1e 100644
--- a/powerstats/aidl/android/hardware/powerstats/PowerEntityStateInfo.aidl
+++ b/power/stats/aidl/android/hardware/power/stats/StateInfo.aidl
@@ -14,17 +14,18 @@
  * limitations under the License.
  */
 
-package android.hardware.powerstats;
+package android.hardware.power.stats;
 
 @VintfStability
-parcelable PowerEntityStateInfo {
+parcelable StateInfo {
     /**
-     * ID corresponding to the state. Unique for a given PowerEntityStateSpace
+     * Unique (for a given PowerEntityInfo) ID of this StateInfo
      */
-    int powerEntityStateId;
+    int stateId;
     /**
-     * Name of the state (opaque to the framework)
+     * Unique (for a given PowerEntityInfo) name of the state. Vendor/device specific.
+     * Opaque to framework
      */
-    String powerEntityStateName;
+    @utf8InCpp String stateName;
 }
 
diff --git a/powerstats/aidl/android/hardware/powerstats/PowerEntityStateResidencyData.aidl b/power/stats/aidl/android/hardware/power/stats/StateResidency.aidl
similarity index 71%
rename from powerstats/aidl/android/hardware/powerstats/PowerEntityStateResidencyData.aidl
rename to power/stats/aidl/android/hardware/power/stats/StateResidency.aidl
index a738457..a85ca33 100644
--- a/powerstats/aidl/android/hardware/powerstats/PowerEntityStateResidencyData.aidl
+++ b/power/stats/aidl/android/hardware/power/stats/StateResidency.aidl
@@ -14,31 +14,28 @@
  * limitations under the License.
  */
 
-package android.hardware.powerstats;
+package android.hardware.power.stats;
 
 /**
  * Contains residency data for a single state
  */
 @VintfStability
-parcelable PowerEntityStateResidencyData {
+parcelable StateResidency {
     /**
-     * Unique ID of the corresponding PowerEntityStateInfo
+     * ID of the state associated with this residency
      */
-    int powerEntityStateId;
+    int stateId;
     /**
      * Total time in milliseconds that the corresponding PowerEntity resided
-     * in this state since the PowerEntity was reset
+     * in this state since boot
      */
     long totalTimeInStateMs;
     /**
-     * Total number of times that the state was entered since the corresponding
-     * PowerEntity was reset
+     * Total number of times that the state was entered since boot
      */
     long totalStateEntryCount;
     /**
-     * Last time this state was entered. Time in milliseconds since the
-     * corresponding PowerEntity was reset
+     * Last time this state was entered. Time in milliseconds since boot
      */
     long lastEntryTimestampMs;
-}
-
+}
\ No newline at end of file
diff --git a/powerstats/aidl/android/hardware/powerstats/PowerEntityStateResidencyResult.aidl b/power/stats/aidl/android/hardware/power/stats/StateResidencyResult.aidl
similarity index 68%
rename from powerstats/aidl/android/hardware/powerstats/PowerEntityStateResidencyResult.aidl
rename to power/stats/aidl/android/hardware/power/stats/StateResidencyResult.aidl
index 555ae4c..3356405 100644
--- a/powerstats/aidl/android/hardware/powerstats/PowerEntityStateResidencyResult.aidl
+++ b/power/stats/aidl/android/hardware/power/stats/StateResidencyResult.aidl
@@ -14,19 +14,19 @@
  * limitations under the License.
  */
 
-package android.hardware.powerstats;
+package android.hardware.power.stats;
 
-import android.hardware.powerstats.PowerEntityStateResidencyData;
+import android.hardware.power.stats.StateResidency;
 
 @VintfStability
-parcelable PowerEntityStateResidencyResult {
+parcelable StateResidencyResult {
     /**
-     * Unique ID of the corresponding PowerEntity
+     * ID of the PowerEntity associated with this result
      */
     int powerEntityId;
     /**
-     * Residency data for each state the PowerEntity's state space
+     * Residency for each state in the PowerEntity's state space
      */
-    PowerEntityStateResidencyData[] stateResidencyData;
+    StateResidency[] stateResidencyData;
 }
 
diff --git a/powerstats/aidl/default/Android.bp b/power/stats/aidl/default/Android.bp
similarity index 80%
rename from powerstats/aidl/default/Android.bp
rename to power/stats/aidl/default/Android.bp
index caecd88..40b9447 100644
--- a/powerstats/aidl/default/Android.bp
+++ b/power/stats/aidl/default/Android.bp
@@ -13,15 +13,15 @@
 // limitations under the License.
 
 cc_binary {
-    name: "android.hardware.powerstats-service.example",
+    name: "android.hardware.power.stats-service.example",
     relative_install_path: "hw",
-    init_rc: ["powerstats-default.rc"],
-    vintf_fragments: ["powerstats-default.xml"],
+    init_rc: ["power.stats-default.rc"],
+    vintf_fragments: ["power.stats-default.xml"],
     vendor: true,
     shared_libs: [
         "libbase",
         "libbinder_ndk",
-        "android.hardware.powerstats-ndk_platform",
+        "android.hardware.power.stats-ndk_platform",
     ],
     srcs: [
         "main.cpp",
diff --git a/power/stats/aidl/default/PowerStats.cpp b/power/stats/aidl/default/PowerStats.cpp
new file mode 100644
index 0000000..367ee95
--- /dev/null
+++ b/power/stats/aidl/default/PowerStats.cpp
@@ -0,0 +1,68 @@
+/*
+ * 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 "PowerStats.h"
+
+#include <android-base/logging.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace power {
+namespace stats {
+
+ndk::ScopedAStatus PowerStats::getPowerEntityInfo(std::vector<PowerEntityInfo>* _aidl_return) {
+    (void)_aidl_return;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus PowerStats::getStateResidency(const std::vector<int32_t>& in_powerEntityIds,
+                                                 std::vector<StateResidencyResult>* _aidl_return) {
+    (void)in_powerEntityIds;
+    (void)_aidl_return;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus PowerStats::getEnergyConsumerInfo(std::vector<EnergyConsumerId>* _aidl_return) {
+    (void)_aidl_return;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus PowerStats::getEnergyConsumed(
+        const std::vector<EnergyConsumerId>& in_energyConsumerIds,
+        std::vector<EnergyConsumerResult>* _aidl_return) {
+    (void)in_energyConsumerIds;
+    (void)_aidl_return;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus PowerStats::getEnergyMeterInfo(std::vector<ChannelInfo>* _aidl_return) {
+    (void)_aidl_return;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus PowerStats::readEnergyMeters(const std::vector<int32_t>& in_channelIds,
+                                                std::vector<EnergyMeasurement>* _aidl_return) {
+    (void)in_channelIds;
+    (void)_aidl_return;
+    return ndk::ScopedAStatus::ok();
+}
+
+}  // namespace stats
+}  // namespace power
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/power/stats/aidl/default/PowerStats.h b/power/stats/aidl/default/PowerStats.h
new file mode 100644
index 0000000..76ab2cb
--- /dev/null
+++ b/power/stats/aidl/default/PowerStats.h
@@ -0,0 +1,46 @@
+/*
+ * 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 <aidl/android/hardware/power/stats/BnPowerStats.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace power {
+namespace stats {
+
+class PowerStats : public BnPowerStats {
+  public:
+    PowerStats() = default;
+    // Methods from aidl::android::hardware::power::stats::IPowerStats
+    ndk::ScopedAStatus getPowerEntityInfo(std::vector<PowerEntityInfo>* _aidl_return) override;
+    ndk::ScopedAStatus getStateResidency(const std::vector<int32_t>& in_powerEntityIds,
+                                         std::vector<StateResidencyResult>* _aidl_return) override;
+    ndk::ScopedAStatus getEnergyConsumerInfo(std::vector<EnergyConsumerId>* _aidl_return) override;
+    ndk::ScopedAStatus getEnergyConsumed(const std::vector<EnergyConsumerId>& in_energyConsumerIds,
+                                         std::vector<EnergyConsumerResult>* _aidl_return) override;
+    ndk::ScopedAStatus getEnergyMeterInfo(std::vector<ChannelInfo>* _aidl_return) override;
+    ndk::ScopedAStatus readEnergyMeters(const std::vector<int32_t>& in_channelIds,
+                                        std::vector<EnergyMeasurement>* _aidl_return) override;
+};
+
+}  // namespace stats
+}  // namespace power
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/powerstats/aidl/default/main.cpp b/power/stats/aidl/default/main.cpp
similarity index 95%
rename from powerstats/aidl/default/main.cpp
rename to power/stats/aidl/default/main.cpp
index 1496805..0469b4c 100644
--- a/powerstats/aidl/default/main.cpp
+++ b/power/stats/aidl/default/main.cpp
@@ -20,7 +20,7 @@
 #include <android/binder_manager.h>
 #include <android/binder_process.h>
 
-using aidl::android::hardware::powerstats::PowerStats;
+using aidl::android::hardware::power::stats::PowerStats;
 
 int main() {
     ABinderProcess_setThreadPoolMaxThreadCount(0);
diff --git a/power/stats/aidl/default/power.stats-default.rc b/power/stats/aidl/default/power.stats-default.rc
new file mode 100644
index 0000000..6ff6754
--- /dev/null
+++ b/power/stats/aidl/default/power.stats-default.rc
@@ -0,0 +1,4 @@
+service vendor.power.stats-default /vendor/bin/hw/android.hardware.power.stats-service.example
+    class hal
+    user system
+    group system
diff --git a/powerstats/aidl/default/powerstats-default.xml b/power/stats/aidl/default/power.stats-default.xml
similarity index 72%
rename from powerstats/aidl/default/powerstats-default.xml
rename to power/stats/aidl/default/power.stats-default.xml
index e07513d..3b1a216 100644
--- a/powerstats/aidl/default/powerstats-default.xml
+++ b/power/stats/aidl/default/power.stats-default.xml
@@ -1,6 +1,6 @@
 <manifest version="1.0" type="device">
     <hal format="aidl">
-        <name>android.hardware.powerstats</name>
+        <name>android.hardware.power.stats</name>
         <fqname>IPowerStats/default</fqname>
     </hal>
 </manifest>
diff --git a/powerstats/aidl/vts/Android.bp b/power/stats/aidl/vts/Android.bp
similarity index 94%
rename from powerstats/aidl/vts/Android.bp
rename to power/stats/aidl/vts/Android.bp
index c61022e..930709f 100644
--- a/powerstats/aidl/vts/Android.bp
+++ b/power/stats/aidl/vts/Android.bp
@@ -23,7 +23,7 @@
         "libbinder_ndk",
     ],
     static_libs: [
-        "android.hardware.powerstats-ndk_platform",
+        "android.hardware.power.stats-ndk_platform",
     ],
     test_suites: [
         "general-tests",
diff --git a/powerstats/aidl/vts/VtsHalPowerStatsTargetTest.cpp b/power/stats/aidl/vts/VtsHalPowerStatsTargetTest.cpp
similarity index 76%
rename from powerstats/aidl/vts/VtsHalPowerStatsTargetTest.cpp
rename to power/stats/aidl/vts/VtsHalPowerStatsTargetTest.cpp
index b3cd233..1d30821 100644
--- a/powerstats/aidl/vts/VtsHalPowerStatsTargetTest.cpp
+++ b/power/stats/aidl/vts/VtsHalPowerStatsTargetTest.cpp
@@ -16,16 +16,17 @@
 #include <aidl/Gtest.h>
 #include <aidl/Vintf.h>
 
-#include <aidl/android/hardware/powerstats/IPowerStats.h>
+#include <aidl/android/hardware/power/stats/IPowerStats.h>
 #include <android-base/properties.h>
 #include <android/binder_manager.h>
 #include <android/binder_process.h>
 
-using aidl::android::hardware::powerstats::EnergyData;
-using aidl::android::hardware::powerstats::IPowerStats;
-using aidl::android::hardware::powerstats::PowerEntityInfo;
-using aidl::android::hardware::powerstats::PowerEntityStateResidencyResult;
-using aidl::android::hardware::powerstats::RailInfo;
+using aidl::android::hardware::power::stats::ChannelInfo;
+using aidl::android::hardware::power::stats::EnergyMeasurement;
+using aidl::android::hardware::power::stats::IPowerStats;
+using aidl::android::hardware::power::stats::PowerEntityInfo;
+using aidl::android::hardware::power::stats::StateResidencyResult;
+
 using ndk::SpAIBinder;
 
 class PowerStatsAidl : public testing::TestWithParam<std::string> {
@@ -39,9 +40,9 @@
     std::shared_ptr<IPowerStats> powerstats;
 };
 
-TEST_P(PowerStatsAidl, TestGetEnergyData) {
-    std::vector<EnergyData> data;
-    ASSERT_TRUE(powerstats->getEnergyData({}, &data).isOk());
+TEST_P(PowerStatsAidl, TestReadEnergyMeter) {
+    std::vector<EnergyMeasurement> data;
+    ASSERT_TRUE(powerstats->readEnergyMeters({}, &data).isOk());
 }
 
 // Each PowerEntity must have a valid name
@@ -83,7 +84,7 @@
 
     for (auto info : infos) {
         for (auto state : info.states) {
-            EXPECT_NE(state.powerEntityStateName, "");
+            EXPECT_NE(state.stateName, "");
         }
     }
 }
@@ -96,7 +97,7 @@
     for (auto info : infos) {
         std::set<std::string> stateNames;
         for (auto state : info.states) {
-            EXPECT_TRUE(stateNames.insert(state.powerEntityStateName).second);
+            EXPECT_TRUE(stateNames.insert(state.stateName).second);
         }
     }
 }
@@ -107,21 +108,21 @@
     ASSERT_TRUE(powerstats->getPowerEntityInfo(&infos).isOk());
 
     for (auto info : infos) {
-        std::set<uint32_t> stateIds;
+        std::set<int32_t> stateIds;
         for (auto state : info.states) {
-            EXPECT_TRUE(stateIds.insert(state.powerEntityStateId).second);
+            EXPECT_TRUE(stateIds.insert(state.stateId).second);
         }
     }
 }
 
-TEST_P(PowerStatsAidl, TestGetPowerEntityStateResidencyData) {
-    std::vector<PowerEntityStateResidencyResult> data;
-    ASSERT_TRUE(powerstats->getPowerEntityStateResidencyData({}, &data).isOk());
+TEST_P(PowerStatsAidl, TestGetStateResidency) {
+    std::vector<StateResidencyResult> results;
+    ASSERT_TRUE(powerstats->getStateResidency({}, &results).isOk());
 }
 
-TEST_P(PowerStatsAidl, TestGetRailInfo) {
-    std::vector<RailInfo> info;
-    ASSERT_TRUE(powerstats->getRailInfo(&info).isOk());
+TEST_P(PowerStatsAidl, TestGetEnergyMeterInfo) {
+    std::vector<ChannelInfo> info;
+    ASSERT_TRUE(powerstats->getEnergyMeterInfo(&info).isOk());
 }
 
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(PowerStatsAidl);
diff --git a/powerstats/aidl/aidl_api/android.hardware.powerstats/current/android/hardware/powerstats/PowerEntityStateResidencyResult.aidl b/powerstats/aidl/aidl_api/android.hardware.powerstats/current/android/hardware/powerstats/PowerEntityStateResidencyResult.aidl
deleted file mode 100644
index fbe567e..0000000
--- a/powerstats/aidl/aidl_api/android.hardware.powerstats/current/android/hardware/powerstats/PowerEntityStateResidencyResult.aidl
+++ /dev/null
@@ -1,23 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
-///////////////////////////////////////////////////////////////////////////////
-
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
-//
-// You must not make a backward incompatible changes to the AIDL files built
-// with the aidl_interface module type with versions property set. The module
-// type is used to build AIDL files in a way that they can be used across
-// independently updatable components of the system. If a device is shipped
-// with such a backward incompatible change, it has a high risk of breaking
-// later when a module using the interface is updated, e.g., Mainline modules.
-
-package android.hardware.powerstats;
-@VintfStability
-parcelable PowerEntityStateResidencyResult {
-  int powerEntityId;
-  android.hardware.powerstats.PowerEntityStateResidencyData[] stateResidencyData;
-}
diff --git a/powerstats/aidl/android/hardware/powerstats/IPowerStats.aidl b/powerstats/aidl/android/hardware/powerstats/IPowerStats.aidl
deleted file mode 100644
index 93d1448..0000000
--- a/powerstats/aidl/android/hardware/powerstats/IPowerStats.aidl
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * 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.
- */
-
-package android.hardware.powerstats;
-
-import android.hardware.powerstats.EnergyData;
-import android.hardware.powerstats.PowerEntityInfo;
-import android.hardware.powerstats.PowerEntityStateResidencyResult;
-import android.hardware.powerstats.RailInfo;
-
-@VintfStability
-interface IPowerStats {
-    /**
-     * Rail level energy measurements for low frequency clients:
-     * Reports accumulated energy since boot on each rail.
-     *
-     * @param railIndices Indices of rails for which data is required.
-     *     To get data for all rails pass an empty vector. Rail name to
-     *     index mapping can be queried from getRailInfo() API.
-     * @return Energy values since boot for all requested rails.
-     */
-    EnergyData[] getEnergyData(in int[] railIndices);
-
-    /**
-     * PowerEntity information:
-     * Reports information related to all supported PowerEntity(s) for which
-     * data is available. A PowerEntity is defined as a platform subsystem,
-     * peripheral, or power domain that impacts the total device power
-     * consumption.
-     *
-     * @return List of information on each PowerEntity
-     */
-    PowerEntityInfo[] getPowerEntityInfo();
-
-    /**
-     * PowerEntity residencies for low frequency clients:
-     * Reports accumulated residency data for each specified PowerEntity.
-     * Each PowerEntity may reside in one of multiple states. It may also
-     * transition to another state. Residency data is an accumulation of time
-     * that a specified PowerEntity resided in each of its possible states,
-     * the number of times that each state was entered, and a timestamp
-     * corresponding to the last time that state was entered. Data is
-     * accumulated starting from the last time the PowerEntity was reset.
-     *
-     * @param powerEntityId collection of IDs of PowerEntity(s) for which
-     *     residency data is requested. PowerEntity name to ID mapping may
-     *     be queried from getPowerEntityInfo(). To get state residency
-     *     data for all PowerEntity(s) pass an empty vector.
-     * @return state residency data for each specified
-     *     PowerEntity that provides state residency data.
-     */
-    PowerEntityStateResidencyResult[] getPowerEntityStateResidencyData(in int[] powerEntityIds);
-
-    /**
-     * Rail information:
-     * Reports information related to the rails being monitored.
-     *
-     * @return Information about monitored rails.
-     */
-    RailInfo[] getRailInfo();
-}
\ No newline at end of file
diff --git a/powerstats/aidl/android/hardware/powerstats/RailInfo.aidl b/powerstats/aidl/android/hardware/powerstats/RailInfo.aidl
deleted file mode 100644
index 4c05bfe..0000000
--- a/powerstats/aidl/android/hardware/powerstats/RailInfo.aidl
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * 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.
- */
-
-package android.hardware.powerstats;
-
-@VintfStability
-parcelable RailInfo {
-    /**
-     * Index corresponding to the rail
-     */
-    int railIndex;
-    /**
-     * Name of the rail (opaque to the framework)
-     */
-    String railName;
-    /**
-     * Name of the subsystem to which this rail belongs (opaque to the framework)
-     */
-    String subsysName;
-    /**
-     * Hardware sampling rate in Hz
-     */
-    int samplingRateHz;
-}
-
diff --git a/powerstats/aidl/default/PowerStats.cpp b/powerstats/aidl/default/PowerStats.cpp
deleted file mode 100644
index 8d6a0ee..0000000
--- a/powerstats/aidl/default/PowerStats.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * 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 "PowerStats.h"
-
-#include <android-base/logging.h>
-
-namespace aidl {
-namespace android {
-namespace hardware {
-namespace powerstats {
-
-ndk::ScopedAStatus PowerStats::getEnergyData(const std::vector<int32_t>& in_railIndices,
-                                             std::vector<EnergyData>* _aidl_return) {
-    (void)in_railIndices;
-    (void)_aidl_return;
-    return ndk::ScopedAStatus::ok();
-}
-
-ndk::ScopedAStatus PowerStats::getPowerEntityInfo(std::vector<PowerEntityInfo>* _aidl_return) {
-    (void)_aidl_return;
-    return ndk::ScopedAStatus::ok();
-}
-
-ndk::ScopedAStatus PowerStats::getPowerEntityStateResidencyData(
-        const std::vector<int32_t>& in_powerEntityIds,
-        std::vector<PowerEntityStateResidencyResult>* _aidl_return) {
-    (void)in_powerEntityIds;
-    (void)_aidl_return;
-    return ndk::ScopedAStatus::ok();
-}
-
-ndk::ScopedAStatus PowerStats::getRailInfo(std::vector<RailInfo>* _aidl_return) {
-    (void)_aidl_return;
-    return ndk::ScopedAStatus::ok();
-}
-
-}  // namespace powerstats
-}  // namespace hardware
-}  // namespace android
-}  // namespace aidl
diff --git a/powerstats/aidl/default/PowerStats.h b/powerstats/aidl/default/PowerStats.h
deleted file mode 100644
index 49240cb..0000000
--- a/powerstats/aidl/default/PowerStats.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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 <aidl/android/hardware/powerstats/BnPowerStats.h>
-
-namespace aidl {
-namespace android {
-namespace hardware {
-namespace powerstats {
-
-class PowerStats : public BnPowerStats {
-  public:
-    PowerStats() = default;
-    ndk::ScopedAStatus getEnergyData(const std::vector<int32_t>& in_railIndices,
-                                     std::vector<EnergyData>* _aidl_return) override;
-    ndk::ScopedAStatus getPowerEntityInfo(std::vector<PowerEntityInfo>* _aidl_return) override;
-    ndk::ScopedAStatus getPowerEntityStateResidencyData(
-            const std::vector<int32_t>& in_powerEntityIds,
-            std::vector<PowerEntityStateResidencyResult>* _aidl_return) override;
-    ndk::ScopedAStatus getRailInfo(std::vector<RailInfo>* _aidl_return) override;
-};
-
-}  // namespace powerstats
-}  // namespace hardware
-}  // namespace android
-}  // namespace aidl
diff --git a/powerstats/aidl/default/powerstats-default.rc b/powerstats/aidl/default/powerstats-default.rc
deleted file mode 100644
index 9b04be3..0000000
--- a/powerstats/aidl/default/powerstats-default.rc
+++ /dev/null
@@ -1,4 +0,0 @@
-service vendor.powerstats-default /vendor/bin/hw/android.hardware.powerstats-service.example
-    class hal
-    user system
-    group system
diff --git a/tests/baz/1.0/IBase.hal b/tests/baz/1.0/IBase.hal
index 0c1b61f..7b60a8a 100644
--- a/tests/baz/1.0/IBase.hal
+++ b/tests/baz/1.0/IBase.hal
@@ -101,6 +101,8 @@
         DoubleThreeDim double3;
     };
 
+    isJava() generates (bool isJava);
+
     someBaseMethod();
 
     someBoolMethod(bool x) generates (bool y);
diff --git a/tests/baz/1.0/IBaz.hal b/tests/baz/1.0/IBaz.hal
index 7855446..8be1d61 100644
--- a/tests/baz/1.0/IBaz.hal
+++ b/tests/baz/1.0/IBaz.hal
@@ -94,7 +94,7 @@
         int8_t[7] array;
         string oneString;
         vec<string> vectorOfStrings;
-        IBase dummy;
+        interface iface;
     };
     oneway doThis(float param);
 
diff --git a/tests/baz/1.0/default/Baz.cpp b/tests/baz/1.0/default/Baz.cpp
index 2ce096c..0c3a59e 100644
--- a/tests/baz/1.0/default/Baz.cpp
+++ b/tests/baz/1.0/default/Baz.cpp
@@ -43,6 +43,12 @@
 }
 
 // Methods from ::android::hardware::tests::baz::V1_0::IBase follow.
+Return<bool> Baz::isJava() {
+    LOG(INFO) << "Baz::isJava";
+
+    return false;
+}
+
 Return<void> Baz::someBaseMethod() {
     LOG(INFO) << "Baz::someBaseMethod";
 
@@ -331,7 +337,7 @@
 Return<IBaz::SomeEnum> Baz::useAnEnum(IBaz::SomeEnum zzz) {
     LOG(INFO) << "useAnEnum " << (int)zzz;
 
-    return SomeEnum::goober;
+    return SomeEnum::quux;
 }
 
 Return<void> Baz::haveSomeStrings(const hidl_array<hidl_string, 3>& array,
diff --git a/tests/baz/1.0/default/Baz.h b/tests/baz/1.0/default/Baz.h
index 1e24d52..38bbcad 100644
--- a/tests/baz/1.0/default/Baz.h
+++ b/tests/baz/1.0/default/Baz.h
@@ -27,6 +27,7 @@
 
 struct Baz : public IBaz {
     // Methods from ::android::hardware::tests::baz::V1_0::IBase follow.
+    Return<bool> isJava() override;
     Return<void> someBaseMethod() override;
     Return<bool> someBoolMethod(bool x) override;
     Return<void> someBoolArrayMethod(const hidl_array<bool, 3>& x,
diff --git a/tests/msgq/1.0/default/Android.bp b/tests/msgq/1.0/default/Android.bp
index a5ba23d..6e7cd44 100644
--- a/tests/msgq/1.0/default/Android.bp
+++ b/tests/msgq/1.0/default/Android.bp
@@ -79,7 +79,11 @@
             suffix: "64",
         },
     },
-    test_suites: ["device-tests"],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
+    auto_gen_config: false,
 
     // Allow dlsym'ing self for statically linked passthrough implementations
     ldflags: ["-rdynamic"],
@@ -89,7 +93,7 @@
     static_libs: [
         "android.hardware.tests.msgq@1.0",
         "android.fmq.test-ndk_platform",
-        "android.hardware.common-unstable-ndk_platform",
+        "android.hardware.common.fmq-unstable-ndk_platform",
     ],
     whole_static_libs: [
         "android.hardware.tests.msgq@1.0-impl",
diff --git a/tests/safeunion/1.0/Android.bp b/tests/safeunion/1.0/Android.bp
index 2937832..f1ec267 100644
--- a/tests/safeunion/1.0/Android.bp
+++ b/tests/safeunion/1.0/Android.bp
@@ -4,7 +4,6 @@
     name: "android.hardware.tests.safeunion@1.0",
     root: "android.hardware",
     srcs: [
-        "IOtherInterface.hal",
         "ISafeUnion.hal",
     ],
     interfaces: [
diff --git a/tests/safeunion/1.0/ISafeUnion.hal b/tests/safeunion/1.0/ISafeUnion.hal
index 58c08c6..01e1727 100644
--- a/tests/safeunion/1.0/ISafeUnion.hal
+++ b/tests/safeunion/1.0/ISafeUnion.hal
@@ -16,8 +16,6 @@
 
 package android.hardware.tests.safeunion@1.0;
 
-import IOtherInterface;
-
 import android.hidl.safe_union@1.0::Monostate;
 
 interface ISafeUnion {
@@ -73,7 +71,7 @@
 
         uint32_t a;
         int8_t[7] b;
-        IOtherInterface c;
+        interface c;
         string d;
         vec<string> e;
         handle f;
@@ -107,7 +105,7 @@
     newInterfaceTypeSafeUnion() generates (InterfaceTypeSafeUnion myUnion);
     setInterfaceA(InterfaceTypeSafeUnion myUnion, uint32_t a) generates (InterfaceTypeSafeUnion myUnion);
     setInterfaceB(InterfaceTypeSafeUnion myUnion, int8_t[7] b) generates (InterfaceTypeSafeUnion myUnion);
-    setInterfaceC(InterfaceTypeSafeUnion myUnion, IOtherInterface c) generates (InterfaceTypeSafeUnion myUnion);
+    setInterfaceC(InterfaceTypeSafeUnion myUnion, interface c) generates (InterfaceTypeSafeUnion myUnion);
     setInterfaceD(InterfaceTypeSafeUnion myUnion, string d) generates (InterfaceTypeSafeUnion myUnion);
     setInterfaceE(InterfaceTypeSafeUnion myUnion, vec<string> e) generates (InterfaceTypeSafeUnion myUnion);
     setInterfaceF(InterfaceTypeSafeUnion myUnion, handle f) generates (InterfaceTypeSafeUnion myUnion);
diff --git a/tests/safeunion/1.0/default/SafeUnion.cpp b/tests/safeunion/1.0/default/SafeUnion.cpp
index 4fb0974..667da6e 100644
--- a/tests/safeunion/1.0/default/SafeUnion.cpp
+++ b/tests/safeunion/1.0/default/SafeUnion.cpp
@@ -202,7 +202,9 @@
     return Void();
 }
 
-Return<void> SafeUnion::setInterfaceC(const InterfaceTypeSafeUnion& myUnion, const sp<::android::hardware::tests::safeunion::V1_0::IOtherInterface>& c, setInterfaceC_cb _hidl_cb) {
+Return<void> SafeUnion::setInterfaceC(const InterfaceTypeSafeUnion& myUnion,
+                                      const sp<::android::hidl::base::V1_0::IBase>& c,
+                                      setInterfaceC_cb _hidl_cb) {
     LOG(INFO) << "SERVER(SafeUnion) setInterfaceC(myUnion, " << toString(c) << ")";
 
     InterfaceTypeSafeUnion myNewUnion = myUnion;
diff --git a/tests/safeunion/1.0/default/SafeUnion.h b/tests/safeunion/1.0/default/SafeUnion.h
index ee3a954..b10575c 100644
--- a/tests/safeunion/1.0/default/SafeUnion.h
+++ b/tests/safeunion/1.0/default/SafeUnion.h
@@ -54,7 +54,9 @@
     Return<void> newInterfaceTypeSafeUnion(newInterfaceTypeSafeUnion_cb _hidl_cb) override;
     Return<void> setInterfaceA(const InterfaceTypeSafeUnion& myUnion, uint32_t a, setInterfaceA_cb _hidl_cb) override;
     Return<void> setInterfaceB(const InterfaceTypeSafeUnion& myUnion, const hidl_array<int8_t, 7>& b, setInterfaceB_cb _hidl_cb) override;
-    Return<void> setInterfaceC(const InterfaceTypeSafeUnion& myUnion, const sp<::android::hardware::tests::safeunion::V1_0::IOtherInterface>& c, setInterfaceC_cb _hidl_cb) override;
+    Return<void> setInterfaceC(const InterfaceTypeSafeUnion& myUnion,
+                               const sp<::android::hidl::base::V1_0::IBase>& c,
+                               setInterfaceC_cb _hidl_cb) override;
     Return<void> setInterfaceD(const InterfaceTypeSafeUnion& myUnion, const hidl_string& d, setInterfaceD_cb _hidl_cb) override;
     Return<void> setInterfaceE(const InterfaceTypeSafeUnion& myUnion, const hidl_vec<hidl_string>& e, setInterfaceE_cb _hidl_cb) override;
     Return<void> setInterfaceF(const InterfaceTypeSafeUnion& myUnion, const hidl_handle& f,
diff --git a/tv/tuner/1.1/Android.bp b/tv/tuner/1.1/Android.bp
index 6cf47f5..daa3683 100644
--- a/tv/tuner/1.1/Android.bp
+++ b/tv/tuner/1.1/Android.bp
@@ -7,6 +7,7 @@
         "IFilter.hal",
         "IFrontend.hal",
         "IFilterCallback.hal",
+        "IFrontendCallback.hal",
         "ITuner.hal",
         "types.hal",
     ],
diff --git a/tv/tuner/1.1/IFilter.hal b/tv/tuner/1.1/IFilter.hal
index 2ba9bb7..3ea4209 100644
--- a/tv/tuner/1.1/IFilter.hal
+++ b/tv/tuner/1.1/IFilter.hal
@@ -70,4 +70,15 @@
      *         memory is not initialized.
      */
     getAvSharedHandle() generates (Result result, handle avMemory, uint64_t avMemSize);
+
+    /**
+     * Configure A/V filter’s stream type. This API only applies to A/V filters.
+     *
+     * @param avStreamType the stream type for A/V.
+     * @return return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         INVALID_STATE if configure can't be applied,
+     *         UNKNOWN_ERROR if failed for other reasons.
+     */
+    configureAvStreamType(AvStreamType avStreamType) generates (Result result);
 };
diff --git a/tv/tuner/1.1/IFrontend.hal b/tv/tuner/1.1/IFrontend.hal
index 9858d4b..63f0655 100644
--- a/tv/tuner/1.1/IFrontend.hal
+++ b/tv/tuner/1.1/IFrontend.hal
@@ -37,7 +37,7 @@
      *
      * @param settings Signal delivery information the frontend uses to
      * search and lock the signal.
-     * @param settingsExt Extended information that would be used in the 1.1 Frontend to
+     * @param settingsExt1_1 v1_1 Extended information that would be used in the 1.1 Frontend to
      * search and lock the signal in a better way.
      *
      * @return result Result status of the operation.
@@ -45,7 +45,7 @@
      *         INVALID_STATE if tuning can't be applied at current stage,
      *         UNKNOWN_ERROR if tuning failed for other reasons.
      */
-    tune_1_1(FrontendSettings settings, FrontendSettingsExt settingsExt)
+    tune_1_1(FrontendSettings settings, FrontendSettingsExt1_1 settingsExt1_1)
         generates (Result result);
 
     /**
@@ -59,15 +59,15 @@
      * @param settings Signal delivery information which the frontend uses to
      * scan the signal.
      * @param type the type which the frontend uses to scan the signal.
-     * @param settingsExt Extended information that would be used in the 1.1 Frontend to
+     * @param settingsExt1_1 v1_1 Extended information that would be used in the 1.1 Frontend to
      * search and lock the signal in a better way.
      * @return result Result status of the operation.
      *         SUCCESS if successful,
      *         INVALID_STATE if tuning can't be applied at current stage,
      *         UNKNOWN_ERROR if tuning failed for other reasons.
      */
-    scan_1_1(FrontendSettings settings, FrontendScanType type, FrontendSettingsExt settingsExt)
-        generates (Result result);
+    scan_1_1(FrontendSettings settings, FrontendScanType type,
+        FrontendSettingsExt1_1 settingsExt1_1) generates (Result result);
 
     /**
      * Link Conditional Access Modules (CAM) to Frontend support Common Interface (CI) bypass mode.
@@ -77,9 +77,36 @@
      * directly from the frontend.
      *
      * @param ciCamId specify CI-CAM Id to link.
+     * @return ltsId Local Transport Stream Id.
      * @return result Result status of the operation.
      *         SUCCESS if successful,
      *         UNKNOWN_ERROR if failed for other reasons.
      */
-    linkCiCam(uint32_t ciCamId) generates (Result result);
+    linkCiCam(uint32_t ciCamId) generates (Result result, uint32_t ltsId);
+
+    /**
+     * Unlink Conditional Access Modules (CAM) to Frontend.
+     *
+     * @param ciCamId specify CI-CAM Id to unlink.
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         UNKNOWN_ERROR if failed for other reasons.
+     */
+    unlinkCiCam(uint32_t ciCamId) generates (Result result);
+
+    /**
+     * Get the v1_1 extended statuses of the frontend.
+     *
+     * This retrieve the extended statuses of the frontend for given extended status types.
+     *
+     * @param statusTypes an array of the extended status types which the caller request.
+     *
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         INVALID_STATE if tuning can't be applied at current stage,
+     *         UNKNOWN_ERROR if tuning failed for other reasons.
+     * @return statuses an array of extended statuses the caller requests for.
+     */
+    getStatusExt1_1(vec<FrontendStatusTypeExt1_1> statusTypes)
+        generates (Result result, vec<FrontendStatusExt1_1> statuses);
 };
diff --git a/tv/tuner/1.1/IFrontendCallback.hal b/tv/tuner/1.1/IFrontendCallback.hal
new file mode 100644
index 0000000..e148b1e
--- /dev/null
+++ b/tv/tuner/1.1/IFrontendCallback.hal
@@ -0,0 +1,32 @@
+/*
+ * Copyright 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.
+ */
+
+package android.hardware.tv.tuner@1.1;
+
+import @1.0::IFrontendCallback;
+import FrontendScanMessageExt1_1;
+import FrontendScanMessageTypeExt1_1;
+
+interface IFrontendCallback extends @1.0::IFrontendCallback {
+    /**
+     * The callback function that must be called by HAL implementation to notify
+     * the client of the v1_1 extended scan messages.
+     *
+     * @param type the type of v1_1 extended scan message.
+     * @param message the v1_1 extended scan message sent by HAL to the client.
+     */
+    onScanMessageExt1_1(FrontendScanMessageTypeExt1_1 type, FrontendScanMessageExt1_1 messageExt);
+};
diff --git a/tv/tuner/1.1/ITuner.hal b/tv/tuner/1.1/ITuner.hal
index 915fb85..d59c425 100644
--- a/tv/tuner/1.1/ITuner.hal
+++ b/tv/tuner/1.1/ITuner.hal
@@ -16,6 +16,7 @@
 
 package android.hardware.tv.tuner@1.1;
 
+import @1.0::FrontendId;
 import @1.0::ITuner;
 import @1.0::Result;
 
@@ -23,4 +24,10 @@
  * Top level interface to manage Frontend, Demux and Decrambler hardware
  * resources which are needed for Android TV.
  */
-interface ITuner extends @1.0::ITuner {};
+interface ITuner extends @1.0::ITuner {
+    /**
+     * Get Dtmb Frontend Capabilities. If no dtmb exists, Result::UNAVAILABLE would be returned.
+     */
+    getFrontendDtmbCapabilities(FrontendId frontendId)
+        generates (Result result, FrontendDtmbCapabilities caps);
+};
diff --git a/tv/tuner/1.1/default/Filter.cpp b/tv/tuner/1.1/default/Filter.cpp
index c69beca..11e323c 100644
--- a/tv/tuner/1.1/default/Filter.cpp
+++ b/tv/tuner/1.1/default/Filter.cpp
@@ -228,6 +228,27 @@
     return Void();
 }
 
+Return<Result> Filter::configureAvStreamType(const V1_1::AvStreamType& avStreamType) {
+    ALOGV("%s", __FUNCTION__);
+
+    if (!mIsMediaFilter) {
+        return Result::UNAVAILABLE;
+    }
+
+    switch (avStreamType.getDiscriminator()) {
+        case V1_1::AvStreamType::hidl_discriminator::audio:
+            mAudioStreamType = static_cast<uint32_t>(avStreamType.audio());
+            break;
+        case V1_1::AvStreamType::hidl_discriminator::video:
+            mVideoStreamType = static_cast<uint32_t>(avStreamType.video());
+            break;
+        default:
+            break;
+    }
+
+    return Result::SUCCESS;
+}
+
 bool Filter::createFilterMQ() {
     ALOGV("%s", __FUNCTION__);
 
diff --git a/tv/tuner/1.1/default/Filter.h b/tv/tuner/1.1/default/Filter.h
index f677666..f8b9a65 100644
--- a/tv/tuner/1.1/default/Filter.h
+++ b/tv/tuner/1.1/default/Filter.h
@@ -82,6 +82,8 @@
 
     virtual Return<void> getAvSharedHandle(getAvSharedHandle_cb _hidl_cb) override;
 
+    virtual Return<Result> configureAvStreamType(const V1_1::AvStreamType& avStreamType) override;
+
     /**
      * To create a FilterMQ and its Event Flag.
      *
@@ -225,6 +227,9 @@
     hidl_handle mSharedAvMemHandle;
     bool mUsingSharedAvMem = true;
     uint32_t mSharedAvMemOffset = 0;
+
+    uint32_t mAudioStreamType;
+    uint32_t mVideoStreamType;
 };
 
 }  // namespace implementation
diff --git a/tv/tuner/1.1/default/Frontend.cpp b/tv/tuner/1.1/default/Frontend.cpp
index 467d547..069456d 100644
--- a/tv/tuner/1.1/default/Frontend.cpp
+++ b/tv/tuner/1.1/default/Frontend.cpp
@@ -17,7 +17,7 @@
 #define LOG_TAG "android.hardware.tv.tuner@1.1-Frontend"
 
 #include "Frontend.h"
-#include <android/hardware/tv/tuner/1.0/IFrontendCallback.h>
+#include <android/hardware/tv/tuner/1.1/IFrontendCallback.h>
 #include <utils/Log.h>
 
 namespace android {
@@ -72,7 +72,7 @@
 }
 
 Return<Result> Frontend::tune_1_1(const FrontendSettings& settings,
-                                  const V1_1::FrontendSettingsExt& /*settingsExt*/) {
+                                  const V1_1::FrontendSettingsExt1_1& /*settingsExt1_1*/) {
     ALOGV("%s", __FUNCTION__);
     return tune(settings);
 }
@@ -118,11 +118,25 @@
     mCallback->onScanMessage(FrontendScanMessageType::LOCKED, msg);
     mIsLocked = true;
 
+    sp<V1_1::IFrontendCallback> frontendCallback_v1_1 =
+            V1_1::IFrontendCallback::castFrom(mCallback);
+    if (frontendCallback_v1_1 != NULL) {
+        V1_1::FrontendScanMessageExt1_1 msg;
+        msg.modulation().dvbc(FrontendDvbcModulation::MOD_16QAM);
+        frontendCallback_v1_1->onScanMessageExt1_1(V1_1::FrontendScanMessageTypeExt1_1::MODULATION,
+                                                   msg);
+        msg.isHighPriority(true);
+        frontendCallback_v1_1->onScanMessageExt1_1(
+                V1_1::FrontendScanMessageTypeExt1_1::HIGH_PRIORITY, msg);
+    } else {
+        ALOGD("[Filter] Couldn't cast to V1_1 IFrontendCallback");
+    }
+
     return Result::SUCCESS;
 }
 
 Return<Result> Frontend::scan_1_1(const FrontendSettings& settings, FrontendScanType type,
-                                  const V1_1::FrontendSettingsExt& /*settingsExt*/) {
+                                  const V1_1::FrontendSettingsExt1_1& /*settingsExt1_1*/) {
     ALOGV("%s", __FUNCTION__);
     return scan(settings, type);
 }
@@ -259,6 +273,83 @@
     return Void();
 }
 
+Return<void> Frontend::getStatusExt1_1(const hidl_vec<V1_1::FrontendStatusTypeExt1_1>& statusTypes,
+                                       V1_1::IFrontend::getStatusExt1_1_cb _hidl_cb) {
+    ALOGV("%s", __FUNCTION__);
+
+    vector<V1_1::FrontendStatusExt1_1> statuses;
+    for (int i = 0; i < statusTypes.size(); i++) {
+        V1_1::FrontendStatusTypeExt1_1 type = statusTypes[i];
+        V1_1::FrontendStatusExt1_1 status;
+        // assign randomly selected values for testing.
+        switch (type) {
+            case V1_1::FrontendStatusTypeExt1_1::MODULATIONS: {
+                vector<V1_1::FrontendModulation> modulations;
+                V1_1::FrontendModulation modulation;
+                modulation.isdbt(FrontendIsdbtModulation::MOD_16QAM);  // value = 1 << 3
+                modulations.push_back(modulation);
+                status.modulations(modulations);
+                break;
+            }
+            case V1_1::FrontendStatusTypeExt1_1::BERS: {
+                vector<uint32_t> bers = {1};
+                status.bers(bers);
+                break;
+            }
+            case V1_1::FrontendStatusTypeExt1_1::CODERATES: {
+                // value = 1 << 39
+                vector<V1_1::FrontendInnerFec> codeRates = {V1_1::FrontendInnerFec::FEC_6_15};
+                status.codeRates(codeRates);
+                break;
+            }
+            case V1_1::FrontendStatusTypeExt1_1::GUARD_INTERVAL: {
+                V1_1::FrontendGuardInterval interval;
+                interval.dvbt(FrontendDvbtGuardInterval::INTERVAL_1_32);  // value = 1 << 1
+                status.interval(interval);
+                break;
+            }
+            case V1_1::FrontendStatusTypeExt1_1::TRANSMISSION_MODE: {
+                V1_1::FrontendTransmissionMode transMode;
+                transMode.dvbt(V1_1::FrontendDvbtTransmissionMode::AUTO);  // value = 1 << 0
+                status.transmissionMode(transMode);
+                break;
+            }
+            case V1_1::FrontendStatusTypeExt1_1::UEC: {
+                status.uec(4);
+                break;
+            }
+            case V1_1::FrontendStatusTypeExt1_1::T2_SYSTEM_ID: {
+                status.systemId(5);
+                break;
+            }
+            case V1_1::FrontendStatusTypeExt1_1::INTERLEAVINGS: {
+                V1_1::FrontendInterleaveMode interleave;
+                interleave.atsc3(FrontendAtsc3TimeInterleaveMode::AUTO);
+                vector<V1_1::FrontendInterleaveMode> interleaving = {interleave};
+                status.interleaving(interleaving);
+                break;
+            }
+            case V1_1::FrontendStatusTypeExt1_1::ISDBT_SEGMENTS: {
+                vector<uint8_t> segments = {2, 3};
+                status.isdbtSegment(segments);
+                break;
+            }
+            case V1_1::FrontendStatusTypeExt1_1::TS_DATA_RATES: {
+                vector<uint32_t> dataRates = {4, 5};
+                status.tsDataRate(dataRates);
+                break;
+            }
+            default: {
+                continue;
+            }
+        }
+        statuses.push_back(status);
+    }
+    _hidl_cb(Result::SUCCESS, statuses);
+
+    return Void();
+}
+
 Return<Result> Frontend::setLna(bool /* bEnable */) {
     ALOGV("%s", __FUNCTION__);
 
@@ -273,10 +364,19 @@
     return Result::SUCCESS;
 }
 
-Return<Result> Frontend::linkCiCam(uint32_t ciCamId) {
+Return<void> Frontend::linkCiCam(uint32_t ciCamId, linkCiCam_cb _hidl_cb) {
     ALOGV("%s", __FUNCTION__);
 
     mCiCamId = ciCamId;
+    _hidl_cb(Result::SUCCESS, 0 /*ltsId*/);
+
+    return Void();
+}
+
+Return<Result> Frontend::unlinkCiCam(uint32_t /*ciCamId*/) {
+    ALOGV("%s", __FUNCTION__);
+
+    mCiCamId = -1;
 
     return Result::SUCCESS;
 }
diff --git a/tv/tuner/1.1/default/Frontend.h b/tv/tuner/1.1/default/Frontend.h
index 6a80232..a28fb64 100644
--- a/tv/tuner/1.1/default/Frontend.h
+++ b/tv/tuner/1.1/default/Frontend.h
@@ -44,25 +44,31 @@
     virtual Return<Result> tune(const FrontendSettings& settings) override;
 
     virtual Return<Result> tune_1_1(const FrontendSettings& settings,
-                                    const V1_1::FrontendSettingsExt& settingsExt) override;
+                                    const V1_1::FrontendSettingsExt1_1& settingsExt1_1) override;
 
     virtual Return<Result> stopTune() override;
 
     virtual Return<Result> scan(const FrontendSettings& settings, FrontendScanType type) override;
 
     virtual Return<Result> scan_1_1(const FrontendSettings& settings, FrontendScanType type,
-                                    const V1_1::FrontendSettingsExt& settingsExt) override;
+                                    const V1_1::FrontendSettingsExt1_1& settingsExt1_1) override;
 
     virtual Return<Result> stopScan() override;
 
     virtual Return<void> getStatus(const hidl_vec<FrontendStatusType>& statusTypes,
                                    getStatus_cb _hidl_cb) override;
 
+    virtual Return<void> getStatusExt1_1(
+            const hidl_vec<V1_1::FrontendStatusTypeExt1_1>& statusTypes,
+            V1_1::IFrontend::getStatusExt1_1_cb _hidl_cb) override;
+
     virtual Return<Result> setLna(bool bEnable) override;
 
     virtual Return<Result> setLnb(uint32_t lnb) override;
 
-    virtual Return<Result> linkCiCam(uint32_t ciCamId) override;
+    virtual Return<void> linkCiCam(uint32_t ciCamId, linkCiCam_cb _hidl_cb) override;
+
+    virtual Return<Result> unlinkCiCam(uint32_t ciCamId) override;
 
     FrontendType getFrontendType();
 
diff --git a/tv/tuner/1.1/default/Tuner.cpp b/tv/tuner/1.1/default/Tuner.cpp
index 87a4d36..c3dcd1d 100644
--- a/tv/tuner/1.1/default/Tuner.cpp
+++ b/tv/tuner/1.1/default/Tuner.cpp
@@ -33,7 +33,7 @@
 Tuner::Tuner() {
     // Static Frontends array to maintain local frontends information
     // Array index matches their FrontendId in the default impl
-    mFrontendSize = 8;
+    mFrontendSize = 9;
     mFrontends[0] = new Frontend(FrontendType::DVBT, 0, this);
     mFrontends[1] = new Frontend(FrontendType::ATSC, 1, this);
     mFrontends[2] = new Frontend(FrontendType::DVBC, 2, this);
@@ -42,6 +42,8 @@
     mFrontends[5] = new Frontend(FrontendType::ISDBT, 5, this);
     mFrontends[6] = new Frontend(FrontendType::ANALOG, 6, this);
     mFrontends[7] = new Frontend(FrontendType::ATSC, 7, this);
+    mFrontends[8] =
+            new Frontend(static_cast<V1_0::FrontendType>(V1_1::FrontendType::DTMB), 8, this);
 
     FrontendInfo::FrontendCapabilities caps;
     caps = FrontendInfo::FrontendCapabilities();
@@ -224,6 +226,20 @@
     return Void();
 }
 
+Return<void> Tuner::getFrontendDtmbCapabilities(uint32_t frontendId,
+                                                getFrontendDtmbCapabilities_cb _hidl_cb) {
+    ALOGV("%s", __FUNCTION__);
+
+    if (mFrontends[frontendId] != nullptr &&
+        (mFrontends[frontendId]->getFrontendType() ==
+         static_cast<V1_0::FrontendType>(V1_1::FrontendType::DTMB))) {
+        _hidl_cb(Result::SUCCESS, mDtmbCaps);
+    } else {
+        _hidl_cb(Result::UNAVAILABLE, mDtmbCaps);
+    }
+    return Void();
+}
+
 void Tuner::setFrontendAsDemuxSource(uint32_t frontendId, uint32_t demuxId) {
     mFrontendToDemux[frontendId] = demuxId;
     if (mFrontends[frontendId] != nullptr && mFrontends[frontendId]->isLocked()) {
diff --git a/tv/tuner/1.1/default/Tuner.h b/tv/tuner/1.1/default/Tuner.h
index 3b1574b..fda3636 100644
--- a/tv/tuner/1.1/default/Tuner.h
+++ b/tv/tuner/1.1/default/Tuner.h
@@ -62,6 +62,9 @@
     virtual Return<void> openLnbByName(const hidl_string& lnbName,
                                        openLnbByName_cb _hidl_cb) override;
 
+    virtual Return<void> getFrontendDtmbCapabilities(
+            uint32_t frontendId, getFrontendDtmbCapabilities_cb _hidl_cb) override;
+
     sp<Frontend> getFrontendById(uint32_t frontendId);
 
     void setFrontendAsDemuxSource(uint32_t frontendId, uint32_t demuxId);
@@ -76,6 +79,7 @@
     // Static mFrontends array to maintain local frontends information
     map<uint32_t, sp<Frontend>> mFrontends;
     map<uint32_t, FrontendInfo::FrontendCapabilities> mFrontendCaps;
+    V1_1::FrontendDtmbCapabilities mDtmbCaps;
     map<uint32_t, uint32_t> mFrontendToDemux;
     map<uint32_t, sp<Demux>> mDemuxes;
     // To maintain how many Frontends we have
diff --git a/tv/tuner/1.1/types.hal b/tv/tuner/1.1/types.hal
index af8d628..1ed6403 100644
--- a/tv/tuner/1.1/types.hal
+++ b/tv/tuner/1.1/types.hal
@@ -19,9 +19,27 @@
 import @1.0::Constant;
 import @1.0::DemuxFilterMmtpRecordEvent;
 import @1.0::DemuxFilterTsRecordEvent;
+import @1.0::FrontendAtsc3Bandwidth;
+import @1.0::FrontendAtsc3Modulation;
+import @1.0::FrontendAtsc3TimeInterleaveMode;
+import @1.0::FrontendAtscModulation;
+import @1.0::FrontendDvbcModulation;
+import @1.0::FrontendDvbtBandwidth;
 import @1.0::FrontendDvbcSpectralInversion;
+import @1.0::FrontendDvbsModulation;
 import @1.0::FrontendDvbtConstellation;
 import @1.0::FrontendDvbtTransmissionMode;
+import @1.0::FrontendDvbtGuardInterval;
+import @1.0::FrontendInnerFec;
+import @1.0::FrontendIsdbs3Modulation;
+import @1.0::FrontendIsdbsModulation;
+import @1.0::FrontendIsdbtBandwidth;
+import @1.0::FrontendIsdbtGuardInterval;
+import @1.0::FrontendIsdbtMode;
+import @1.0::FrontendIsdbtModulation;
+import @1.0::FrontendScanMessageType;
+import @1.0::FrontendStatusType;
+import @1.0::FrontendType;
 import android.hidl.safe_union@1.0;
 import android.hidl.safe_union@1.0::Monostate;
 
@@ -40,6 +58,11 @@
      * be used to reset the configured ip context id.
      */
     INVALID_IP_FILTER_CONTEXT_ID = 0xFFFFFFFF,
+    /**
+     * An invalid local transport stream id used as the return value on a failed operation of
+     * IFrontend.linkCiCam.
+     */
+    INVALID_LTS_ID = 0xFFFFFFFF,
 };
 
 @export
@@ -64,8 +87,7 @@
 struct DemuxFilterRecordEventExt {
     /**
      * The Presentation Time Stamp(PTS) for the audio or video frame. It is based on 90KHz
-     * and has the same format as the PTS in ISO/IEC 13818-1. It is used only for the SC and
-     * the SC_HEVC.
+     * and has the same format as the PTS in ISO/IEC 13818-1.
      */
     uint64_t pts;
 
@@ -122,6 +144,24 @@
 };
 
 /**
+ * Time Interleave Mode for DVBC Frontend.
+ */
+@export
+enum FrontendCableTimeInterleaveMode : uint32_t {
+    UNDEFINED = 0,
+    AUTO = 1 << 0,
+    INTERLEAVING_128_1_0 = 1 << 1,
+    INTERLEAVING_128_1_1 = 1 << 2,
+    INTERLEAVING_64_2 = 1 << 3,
+    INTERLEAVING_32_4 = 1 << 4,
+    INTERLEAVING_16_8 = 1 << 5,
+    INTERLEAVING_8_16 = 1 << 6,
+    INTERLEAVING_128_2 = 1 << 7,
+    INTERLEAVING_128_3 = 1 << 8,
+    INTERLEAVING_128_4 = 1 << 9,
+};
+
+/**
  *  Extended Transmission Mode for DVBT.
  */
 @export
@@ -145,14 +185,16 @@
 /**
  *  Extended Signal Settings for a DVBS Frontend.
  */
-struct FrontendDvbsSettingsExt {
+struct FrontendDvbsSettingsExt1_1 {
     FrontendDvbsScanType scanType;
+
+    bool isDiseqcRxMessage;
 };
 
 /**
  *  Extended Signal Settings for a DVBT Frontend.
  */
-struct FrontendDvbtSettingsExt {
+struct FrontendDvbtSettingsExt1_1 {
     FrontendDvbtConstellation constellation;
 
     FrontendDvbtTransmissionMode transmissionMode;
@@ -161,14 +203,21 @@
 /**
  *  Extended Signal Settings for an Analog Frontend.
  */
-struct FrontendAnalogSettingsExt {
+struct FrontendAnalogSettingsExt1_1 {
     FrontendAnalogAftFlag aftFlag;
 };
 
 /**
+ *  Extended Signal Settings for DVBC Frontend.
+ */
+struct FrontendDvbcSettingsExt1_1 {
+    FrontendCableTimeInterleaveMode interleaveMode;
+};
+
+/**
  *  Extended Signal Settings for Frontend.
  */
-struct FrontendSettingsExt {
+struct FrontendSettingsExt1_1 {
     uint32_t endFrequency;
 
     FrontendSpectralInversion inversion;
@@ -176,10 +225,473 @@
     safe_union SettingsExt {
         Monostate noinit;
 
-        FrontendAnalogSettingsExt analog;
+        FrontendAnalogSettingsExt1_1 analog;
 
-        FrontendDvbsSettingsExt dvbs;
+        FrontendDvbcSettingsExt1_1 dvbc;
 
-        FrontendDvbtSettingsExt dvbt;
+        FrontendDvbsSettingsExt1_1 dvbs;
+
+        FrontendDvbtSettingsExt1_1 dvbt;
+
+        FrontendDtmbSettings dtmb;
     } settingExt;
 };
+
+/**
+ *  Extended Frontend Type.
+ */
+@export
+enum FrontendType : @1.0::FrontendType {
+    /**
+     * DTMB (Digital Terrestrial Multimedia Broadcast) standard.
+     */
+    DTMB,
+};
+
+/**
+ *  Bandwidth Type for DTMB.
+ */
+@export
+enum FrontendDtmbBandwidth : uint32_t {
+    UNDEFINED = 0,
+    /**
+     * hardware is able to detect and set Bandwidth automatically
+     */
+    AUTO = 1 << 0,
+    BANDWIDTH_8MHZ = 1 << 1,
+    BANDWIDTH_6MHZ = 1 << 2,
+};
+
+/**
+ *  TimeInterleaveMode Type for DTMB.
+ */
+@export
+enum FrontendDtmbTimeInterleaveMode : uint32_t {
+    UNDEFINED = 0,
+    /**
+     * hardware is able to detect and set time interleave mode automatically
+     */
+    AUTO = 1 << 0,
+    TIMER_INT_240 = 1 << 1,
+    TIMER_INT_720 = 1 << 2,
+};
+
+/**
+ *  FrontendDtmbModulation Type for DTMB.
+ */
+@export
+enum FrontendDtmbModulation : uint32_t {
+    UNDEFINED = 0,
+    /**
+     * hardware is able to detect and set Constellation automatically
+     */
+    AUTO = 1 << 0,
+    CONSTELLATION_4QAM = 1 << 1,
+    CONSTELLATION_4QAM_NR = 1 << 2,
+    CONSTELLATION_16QAM = 1 << 3,
+    CONSTELLATION_32QAM = 1 << 4,
+    CONSTELLATION_64QAM = 1 << 5,
+};
+
+/**
+ *  CODERATE Type for DTMB.
+ */
+@export
+enum FrontendDtmbCodeRate : uint32_t {
+    UNDEFINED = 0,
+    /**
+     * hardware is able to detect and set code rate automatically
+     */
+    AUTO = 1 << 0,
+    CODERATE_2_5 = 1 << 1,
+    CODERATE_3_5 = 1 << 2,
+    CODERATE_4_5 = 1 << 3,
+};
+
+/**
+ *  Guard Interval Type for DTMB.
+ */
+@export
+enum FrontendDtmbGuardInterval : uint32_t {
+    UNDEFINED = 0,
+    /**
+     * hardware is able to detect and set Guard Interval automatically
+     */
+    AUTO = 1 << 0,
+    PN_420_VARIOUS = 1 << 1,
+    PN_595_CONST = 1 << 2,
+    PN_945_VARIOUS = 1 << 3,
+    PN_420_CONST = 1 << 4,
+    PN_945_CONST = 1 << 5,
+    PN_RESERVED = 1 << 6,
+};
+
+/**
+ *  Transmission Mode for DTMB.
+ */
+@export
+enum FrontendDtmbTransmissionMode : uint32_t {
+    UNDEFINED = 0,
+    /**
+     * hardware is able to detect and set Transmission Mode automatically
+     */
+    AUTO = 1 << 0,
+    C1 = 1 << 1,
+    C3780 = 1 << 2,
+};
+
+/**
+ *  Signal Setting for DTMB Frontend.
+ */
+struct FrontendDtmbSettings {
+    uint32_t frequency;
+
+    FrontendDtmbTransmissionMode transmissionMode;
+
+    FrontendDtmbBandwidth bandwidth;
+
+    FrontendDtmbModulation modulation;
+
+    FrontendDtmbCodeRate codeRate;
+
+    FrontendDtmbGuardInterval guardInterval;
+
+    FrontendDtmbTimeInterleaveMode interleaveMode;
+};
+
+/**
+ *  Capabilities for DTMB Frontend.
+ */
+struct FrontendDtmbCapabilities {
+    bitfield<FrontendDtmbTransmissionMode> transmissionModeCap;
+
+    bitfield<FrontendDtmbBandwidth> bandwidthCap;
+
+    bitfield<FrontendDtmbModulation> modulationCap;
+
+    bitfield<FrontendDtmbCodeRate> codeRateCap;
+
+    bitfield<FrontendDtmbGuardInterval> guardIntervalCap;
+
+    bitfield<FrontendDtmbTimeInterleaveMode> interleaveModeCap;
+};
+
+safe_union FrontendModulation {
+    @1.0::FrontendDvbcModulation dvbc;
+
+    @1.0::FrontendDvbsModulation dvbs;
+
+    FrontendDvbtConstellation dvbt;
+
+    @1.0::FrontendIsdbsModulation isdbs;
+
+    @1.0::FrontendIsdbs3Modulation isdbs3;
+
+    @1.0::FrontendIsdbtModulation isdbt;
+
+    @1.0::FrontendAtscModulation atsc;
+
+    @1.0::FrontendAtsc3Modulation atsc3;
+
+    FrontendDtmbModulation dtmb;
+};
+
+safe_union FrontendInterleaveMode {
+    @1.0::FrontendAtsc3TimeInterleaveMode atsc3;
+
+    FrontendCableTimeInterleaveMode dvbc;
+
+    FrontendDtmbTimeInterleaveMode dtmb;
+};
+
+@export
+enum FrontendInnerFec : @1.0::FrontendInnerFec {
+    FEC_2_15 = 1 << 36,
+    FEC_3_15 = 1 << 37,
+    FEC_5_15 = 1 << 38,
+    FEC_6_15 = 1 << 39,
+    FEC_9_15 = 1 << 40,
+    FEC_10_15 = 1 << 41,
+    FEC_12_15 = 1 << 42,
+    FEC_13_15 = 1 << 43,
+    FEC_18_30 = 1 << 44,
+    FEC_20_30 = 1 << 45,
+    FEC_90_180 = 1 << 46,
+    FEC_96_180 = 1 << 47,
+    FEC_104_180 = 1 << 48,
+    FEC_128_180 = 1 << 49,
+    FEC_132_180 = 1 << 50,
+    FEC_135_180 = 1 << 51,
+    FEC_140_180 = 1 << 52,
+};
+
+safe_union FrontendBandwidth {
+    @1.0::FrontendAtsc3Bandwidth atsc3;
+
+    @1.0::FrontendDvbtBandwidth dvbt;
+
+    @1.0::FrontendIsdbtBandwidth isdbt;
+
+    FrontendDtmbBandwidth dtmb;
+};
+
+safe_union FrontendGuardInterval {
+    @1.0::FrontendDvbtGuardInterval dvbt;
+
+    @1.0::FrontendIsdbtGuardInterval isdbt;
+
+    FrontendDtmbGuardInterval dtmb;
+};
+
+safe_union FrontendTransmissionMode {
+    FrontendDvbtTransmissionMode dvbt;
+
+    @1.0::FrontendIsdbtMode isdbt;
+
+    FrontendDtmbTransmissionMode dtmb;
+};
+
+@export
+enum FrontendStatusTypeExt1_1 : uint32_t {
+    /**
+     * Modulation Types.
+     */
+    MODULATIONS = @1.0::FrontendStatusType:ATSC3_PLP_INFO + 1,
+    /**
+     * Bit Error Ratios.
+     */
+    BERS,
+    /**
+     * Code Rates.
+     */
+    CODERATES,
+    /**
+     * Extended Bandwidth.
+     */
+    BANDWIDTH,
+    /**
+     * Extended Guard Intervals.
+     */
+    GUARD_INTERVAL,
+    /**
+     * Extended Transmission Mode.
+     */
+    TRANSMISSION_MODE,
+    /**
+     * Uncorrectable Error Counts of the frontend's Physical Layer Pipe (PLP)
+     * since the last tune operation.
+     */
+    UEC,
+    /**
+     * DVB-T2 System Id.
+     */
+    T2_SYSTEM_ID,
+    /**
+     * Frontend Interleaving Modes.
+     */
+    INTERLEAVINGS,
+    /**
+     * Segments in ISDB-T Specification of all the channels.
+     */
+    ISDBT_SEGMENTS,
+    /**
+     * Transport Stream Data Rate in BPS of the current channel.
+     */
+    TS_DATA_RATES,
+};
+
+safe_union FrontendStatusExt1_1 {
+    /**
+     * Extended modulation status.
+     */
+    vec<FrontendModulation> modulations;
+
+    /**
+     * Extended bit error ratio status.
+     */
+    vec<uint32_t> bers;
+
+    /**
+     * Extended code rate status.
+     */
+    vec<FrontendInnerFec> codeRates;
+
+    /**
+     * Extended bandwidth status.
+     */
+    FrontendBandwidth bandwidth;
+
+    /**
+     * Extended guard interval status.
+     */
+    FrontendGuardInterval interval;
+
+    /**
+     * Extended transmission mode status.
+     */
+    FrontendTransmissionMode transmissionMode;
+
+    /**
+     * Uncorrectable Error Counts of the frontend's Physical Layer Pipe (PLP)
+     * since the last tune operation.
+     */
+    uint32_t uec;
+
+    /**
+     * The current DVB-T2 system id status.
+     */
+    uint16_t systemId;
+
+    /**
+     * Frontend Interleaving Modes.
+     */
+    vec<FrontendInterleaveMode> interleaving;
+
+    /**
+     * Segments in ISDB-T Specification of all the channels.
+     */
+    vec<uint8_t> isdbtSegment;
+
+    /**
+     * Transport Stream Data Rate in BPS of the current channel.
+     */
+    vec<uint32_t> tsDataRate;
+};
+
+enum FrontendScanMessageTypeExt1_1 : uint32_t {
+    MODULATION = @1.0::FrontendScanMessageType:ATSC3_PLP_INFO + 1,
+    HIGH_PRIORITY,
+};
+
+safe_union FrontendScanMessageExt1_1 {
+    FrontendModulation modulation;
+
+    bool isHighPriority;
+};
+
+@export
+enum VideoStreamType : uint32_t {
+    UNDEFINED,
+    /*
+     * ITU-T | ISO/IEC Reserved
+     */
+    RESERVED,
+    /*
+     * ISO/IEC 11172
+     */
+    MPEG1,
+    /*
+     * ITU-T Rec.H.262 and ISO/IEC 13818-2
+     */
+    MPEG2,
+    /*
+     * ISO/IEC 14496-2 (MPEG-4 H.263 based video)
+     */
+    MPEG4P2,
+    /*
+     * ITU-T Rec.H.264 and ISO/IEC 14496-10
+     */
+    AVC,
+    /*
+     * ITU-T Rec. H.265 and ISO/IEC 23008-2
+     */
+    HEVC,
+    /*
+     * Microsoft VC.1
+     */
+    VC1,
+    /*
+     * Google VP8
+     */
+    VP8,
+    /*
+     * Google VP9
+     */
+    VP9,
+    /*
+     * AOMedia Video 1
+     */
+    AV1,
+    /*
+     * Chinese Standard
+     */
+    AVS,
+    /*
+     * New Chinese Standard
+     */
+    AVS2,
+};
+
+@export
+enum AudioStreamType : uint32_t {
+    UNDEFINED,
+    /*
+     * Uncompressed Audio
+     */
+    PCM,
+    /*
+     * MPEG Audio Layer III versions
+     */
+    MP3,
+    /*
+     * ISO/IEC 11172 Audio
+     */
+    MPEG1,
+    /*
+     * ISO/IEC 13818-3
+     */
+    MPEG2,
+    /*
+     * ISO/IEC 23008-3 (MPEG-H Part 3)
+     */
+    MPEGH,
+    /*
+     * ISO/IEC 14496-3
+     */
+    AAC,
+    /*
+     * Dolby Digital
+     */
+    AC3,
+    /*
+     * Dolby Digital Plus
+     */
+    EAC3,
+    /*
+     * Dolby AC-4
+     */
+    AC4,
+    /*
+     * Basic DTS
+     */
+    DTS,
+    /*
+     * High Resolution DTS
+     */
+    DTS_HD,
+    /*
+     * Windows Media Audio
+     */
+    WMA,
+    /*
+     * Opus Interactive Audio Codec
+     */
+    OPUS,
+    /*
+     * VORBIS Interactive Audio Codec
+     */
+    VORBIS,
+    /*
+     * SJ/T 11368-2006
+     */
+    DRA,
+};
+
+/**
+ *  Stream type for A/V filter.
+ */
+safe_union AvStreamType {
+    VideoStreamType video;
+
+    AudioStreamType audio;
+};
diff --git a/tv/tuner/1.1/vts/functional/FilterTests.cpp b/tv/tuner/1.1/vts/functional/FilterTests.cpp
index 5a8985d..e661735 100644
--- a/tv/tuner/1.1/vts/functional/FilterTests.cpp
+++ b/tv/tuner/1.1/vts/functional/FilterTests.cpp
@@ -164,6 +164,20 @@
     return AssertionResult(status == Result::SUCCESS);
 }
 
+AssertionResult FilterTests::configAvFilterStreamType(AvStreamType type, uint64_t filterId) {
+    Result status;
+    EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
+    sp<android::hardware::tv::tuner::V1_1::IFilter> filter_v1_1 =
+            android::hardware::tv::tuner::V1_1::IFilter::castFrom(mFilters[filterId]);
+    if (filter_v1_1 != NULL) {
+        status = filter_v1_1->configureAvStreamType(type);
+    } else {
+        ALOGW("[vts] Can't cast IFilter into v1_1.");
+        return failure();
+    }
+    return AssertionResult(status == Result::SUCCESS);
+}
+
 AssertionResult FilterTests::configIpFilterCid(uint32_t ipCid, uint64_t filterId) {
     Result status;
     EXPECT_TRUE(mFilters[filterId]) << "Open Ip filter first.";
diff --git a/tv/tuner/1.1/vts/functional/FilterTests.h b/tv/tuner/1.1/vts/functional/FilterTests.h
index bc6db86..3472e4e 100644
--- a/tv/tuner/1.1/vts/functional/FilterTests.h
+++ b/tv/tuner/1.1/vts/functional/FilterTests.h
@@ -54,6 +54,7 @@
 using android::hardware::tv::tuner::V1_0::IDemux;
 using android::hardware::tv::tuner::V1_0::IFilter;
 using android::hardware::tv::tuner::V1_0::Result;
+using android::hardware::tv::tuner::V1_1::AvStreamType;
 using android::hardware::tv::tuner::V1_1::DemuxFilterEventExt;
 using android::hardware::tv::tuner::V1_1::IFilterCallback;
 using android::hardware::tv::tuner::V1_1::ITuner;
@@ -150,6 +151,7 @@
     AssertionResult getSharedAvMemoryHandle(uint64_t filterId);
     AssertionResult releaseShareAvHandle(uint64_t filterId);
     AssertionResult configFilter(DemuxFilterSettings setting, uint64_t filterId);
+    AssertionResult configAvFilterStreamType(AvStreamType type, uint64_t filterId);
     AssertionResult configIpFilterCid(uint32_t ipCid, uint64_t filterId);
     AssertionResult getFilterMQDescriptor(uint64_t filterId);
     AssertionResult startFilter(uint64_t filterId);
diff --git a/tv/tuner/1.1/vts/functional/FrontendTests.cpp b/tv/tuner/1.1/vts/functional/FrontendTests.cpp
index 5e2b288..e5793c1 100644
--- a/tv/tuner/1.1/vts/functional/FrontendTests.cpp
+++ b/tv/tuner/1.1/vts/functional/FrontendTests.cpp
@@ -47,8 +47,56 @@
     return Void();
 }
 
+Return<void> FrontendCallback::onScanMessageExt1_1(FrontendScanMessageTypeExt1_1 type,
+                                                   const FrontendScanMessageExt1_1& message) {
+    android::Mutex::Autolock autoLock(mMsgLock);
+    ALOGD("[vts] frontend ext1_1 scan message. Type: %d", type);
+    switch (message.getDiscriminator()) {
+        case FrontendScanMessageExt1_1::hidl_discriminator::modulation:
+            readFrontendScanMessageExt1_1Modulation(message.modulation());
+            break;
+        case FrontendScanMessageExt1_1::hidl_discriminator::isHighPriority:
+            ALOGD("[vts] frontend ext1_1 scan message high priority: %d", message.isHighPriority());
+            break;
+        default:
+            break;
+    }
+    return Void();
+}
+
+void FrontendCallback::readFrontendScanMessageExt1_1Modulation(FrontendModulation modulation) {
+    switch (modulation.getDiscriminator()) {
+        case FrontendModulation::hidl_discriminator::dvbc:
+            ALOGD("[vts] frontend ext1_1 scan message modulation dvbc: %d", modulation.dvbc());
+            break;
+        case FrontendModulation::hidl_discriminator::dvbs:
+            ALOGD("[vts] frontend ext1_1 scan message modulation dvbs: %d", modulation.dvbs());
+            break;
+        case FrontendModulation::hidl_discriminator::isdbs:
+            ALOGD("[vts] frontend ext1_1 scan message modulation isdbs: %d", modulation.isdbs());
+            break;
+        case FrontendModulation::hidl_discriminator::isdbs3:
+            ALOGD("[vts] frontend ext1_1 scan message modulation isdbs3: %d", modulation.isdbs3());
+            break;
+        case FrontendModulation::hidl_discriminator::isdbt:
+            ALOGD("[vts] frontend ext1_1 scan message modulation isdbt: %d", modulation.isdbt());
+            break;
+        case FrontendModulation::hidl_discriminator::atsc:
+            ALOGD("[vts] frontend ext1_1 scan message modulation atsc: %d", modulation.atsc());
+            break;
+        case FrontendModulation::hidl_discriminator::atsc3:
+            ALOGD("[vts] frontend ext1_1 scan message modulation atsc3: %d", modulation.atsc3());
+            break;
+        case FrontendModulation::hidl_discriminator::dvbt:
+            ALOGD("[vts] frontend ext1_1 scan message modulation dvbt: %d", modulation.dvbt());
+            break;
+        default:
+            break;
+    }
+}
+
 void FrontendCallback::tuneTestOnLock(sp<IFrontend>& frontend, FrontendSettings settings,
-                                      FrontendSettingsExt settingsExt) {
+                                      FrontendSettingsExt1_1 settingsExt1_1) {
     sp<android::hardware::tv::tuner::V1_1::IFrontend> frontend_1_1;
     frontend_1_1 = android::hardware::tv::tuner::V1_1::IFrontend::castFrom(frontend);
     if (frontend_1_1 == nullptr) {
@@ -56,7 +104,7 @@
         return;
     }
 
-    Result result = frontend_1_1->tune_1_1(settings, settingsExt);
+    Result result = frontend_1_1->tune_1_1(settings, settingsExt1_1);
     EXPECT_TRUE(result == Result::SUCCESS);
 
     android::Mutex::Autolock autoLock(mMsgLock);
@@ -88,7 +136,7 @@
         resetBlindScanStartingFrequency(config, targetFrequency - 100);
     }
 
-    Result result = frontend_1_1->scan_1_1(config.settings, type, config.settingsExt);
+    Result result = frontend_1_1->scan_1_1(config.settings, type, config.settingsExt1_1);
     EXPECT_TRUE(result == Result::SUCCESS);
 
     bool scanMsgLockedReceived = false;
@@ -108,7 +156,7 @@
     if (mScanMessageType != FrontendScanMessageType::END) {
         if (mScanMessageType == FrontendScanMessageType::LOCKED) {
             scanMsgLockedReceived = true;
-            Result result = frontend_1_1->scan_1_1(config.settings, type, config.settingsExt);
+            Result result = frontend_1_1->scan_1_1(config.settings, type, config.settingsExt1_1);
             EXPECT_TRUE(result == Result::SUCCESS);
         }
 
@@ -243,118 +291,92 @@
     EXPECT_TRUE(mFrontend) << "Test with openFrontendById first.";
     Result status;
     status = mFrontend->stopScan();
+
     return AssertionResult(status == Result::SUCCESS);
 }
 
-void FrontendTests::verifyFrontendStatus(vector<FrontendStatusType> statusTypes,
-                                         vector<FrontendStatus> expectStatuses) {
+AssertionResult FrontendTests::getFrontendDtmbCaps(uint32_t id) {
+    Result status;
+    mService->getFrontendDtmbCapabilities(
+            id, [&](Result result, const FrontendDtmbCapabilities& /*caps*/) { status = result; });
+    return AssertionResult(status == Result::SUCCESS);
+}
+
+void FrontendTests::verifyFrontendStatusExt1_1(vector<FrontendStatusTypeExt1_1> statusTypes,
+                                               vector<FrontendStatusExt1_1> expectStatuses) {
     ASSERT_TRUE(mFrontend) << "Frontend is not opened yet.";
     Result status;
-    vector<FrontendStatus> realStatuses;
+    vector<FrontendStatusExt1_1> realStatuses;
 
-    mFrontend->getStatus(statusTypes, [&](Result result, const hidl_vec<FrontendStatus>& statuses) {
-        status = result;
-        realStatuses = statuses;
-    });
+    sp<android::hardware::tv::tuner::V1_1::IFrontend> frontend_1_1;
+    frontend_1_1 = android::hardware::tv::tuner::V1_1::IFrontend::castFrom(mFrontend);
+    if (frontend_1_1 == nullptr) {
+        EXPECT_TRUE(false) << "Couldn't get 1.1 IFrontend from the Hal implementation.";
+        return;
+    }
+
+    frontend_1_1->getStatusExt1_1(
+            statusTypes, [&](Result result, const hidl_vec<FrontendStatusExt1_1>& statuses) {
+                status = result;
+                realStatuses = statuses;
+            });
 
     ASSERT_TRUE(realStatuses.size() == statusTypes.size());
     for (int i = 0; i < statusTypes.size(); i++) {
-        FrontendStatusType type = statusTypes[i];
+        FrontendStatusTypeExt1_1 type = statusTypes[i];
         switch (type) {
-            case FrontendStatusType::DEMOD_LOCK: {
-                ASSERT_TRUE(realStatuses[i].isDemodLocked() == expectStatuses[i].isDemodLocked());
+            case FrontendStatusTypeExt1_1::MODULATIONS: {
+                // TODO: verify modulations
                 break;
             }
-            case FrontendStatusType::SNR: {
-                ASSERT_TRUE(realStatuses[i].snr() == expectStatuses[i].snr());
+            case FrontendStatusTypeExt1_1::BERS: {
+                ASSERT_TRUE(std::equal(realStatuses[i].bers().begin(), realStatuses[i].bers().end(),
+                                       expectStatuses[i].bers().begin()));
                 break;
             }
-            case FrontendStatusType::BER: {
-                ASSERT_TRUE(realStatuses[i].ber() == expectStatuses[i].ber());
+            case FrontendStatusTypeExt1_1::CODERATES: {
+                ASSERT_TRUE(std::equal(realStatuses[i].codeRates().begin(),
+                                       realStatuses[i].codeRates().end(),
+                                       expectStatuses[i].codeRates().begin()));
                 break;
             }
-            case FrontendStatusType::PER: {
-                ASSERT_TRUE(realStatuses[i].per() == expectStatuses[i].per());
+            case FrontendStatusTypeExt1_1::GUARD_INTERVAL: {
+                // TODO: verify interval
                 break;
             }
-            case FrontendStatusType::PRE_BER: {
-                ASSERT_TRUE(realStatuses[i].preBer() == expectStatuses[i].preBer());
+            case FrontendStatusTypeExt1_1::TRANSMISSION_MODE: {
+                // TODO: verify tranmission mode
                 break;
             }
-            case FrontendStatusType::SIGNAL_QUALITY: {
-                ASSERT_TRUE(realStatuses[i].signalQuality() == expectStatuses[i].signalQuality());
+            case FrontendStatusTypeExt1_1::UEC: {
+                ASSERT_TRUE(realStatuses[i].uec() == expectStatuses[i].uec());
                 break;
             }
-            case FrontendStatusType::SIGNAL_STRENGTH: {
-                ASSERT_TRUE(realStatuses[i].signalStrength() == expectStatuses[i].signalStrength());
+            case FrontendStatusTypeExt1_1::T2_SYSTEM_ID: {
+                ASSERT_TRUE(realStatuses[i].systemId() == expectStatuses[i].systemId());
                 break;
             }
-            case FrontendStatusType::SYMBOL_RATE: {
-                ASSERT_TRUE(realStatuses[i].symbolRate() == expectStatuses[i].symbolRate());
+            case FrontendStatusTypeExt1_1::INTERLEAVINGS: {
+                ASSERT_TRUE(std::equal(realStatuses[i].interleaving().begin(),
+                                       realStatuses[i].interleaving().end(),
+                                       expectStatuses[i].interleaving().begin()));
                 break;
             }
-            case FrontendStatusType::FEC: {
-                ASSERT_TRUE(realStatuses[i].innerFec() == expectStatuses[i].innerFec());
+            case FrontendStatusTypeExt1_1::ISDBT_SEGMENTS: {
+                ASSERT_TRUE(std::equal(realStatuses[i].isdbtSegment().begin(),
+                                       realStatuses[i].isdbtSegment().end(),
+                                       expectStatuses[i].isdbtSegment().begin()));
                 break;
             }
-            case FrontendStatusType::MODULATION: {
-                // TODO: check modulation status
+            case FrontendStatusTypeExt1_1::TS_DATA_RATES: {
+                ASSERT_TRUE(std::equal(realStatuses[i].tsDataRate().begin(),
+                                       realStatuses[i].tsDataRate().end(),
+                                       expectStatuses[i].tsDataRate().begin()));
                 break;
             }
-            case FrontendStatusType::SPECTRAL: {
-                ASSERT_TRUE(realStatuses[i].inversion() == expectStatuses[i].inversion());
-                break;
-            }
-            case FrontendStatusType::LNB_VOLTAGE: {
-                ASSERT_TRUE(realStatuses[i].lnbVoltage() == expectStatuses[i].lnbVoltage());
-                break;
-            }
-            case FrontendStatusType::PLP_ID: {
-                ASSERT_TRUE(realStatuses[i].plpId() == expectStatuses[i].plpId());
-                break;
-            }
-            case FrontendStatusType::EWBS: {
-                ASSERT_TRUE(realStatuses[i].isEWBS() == expectStatuses[i].isEWBS());
-                break;
-            }
-            case FrontendStatusType::AGC: {
-                ASSERT_TRUE(realStatuses[i].agc() == expectStatuses[i].agc());
-                break;
-            }
-            case FrontendStatusType::LNA: {
-                ASSERT_TRUE(realStatuses[i].isLnaOn() == expectStatuses[i].isLnaOn());
-                break;
-            }
-            case FrontendStatusType::LAYER_ERROR: {
-                vector<bool> realLayberError = realStatuses[i].isLayerError();
-                vector<bool> expectLayerError = expectStatuses[i].isLayerError();
-                ASSERT_TRUE(realLayberError.size() == expectLayerError.size());
-                for (int i = 0; i < realLayberError.size(); i++) {
-                    ASSERT_TRUE(realLayberError[i] == expectLayerError[i]);
-                }
-                break;
-            }
-            case FrontendStatusType::MER: {
-                ASSERT_TRUE(realStatuses[i].mer() == expectStatuses[i].mer());
-                break;
-            }
-            case FrontendStatusType::FREQ_OFFSET: {
-                ASSERT_TRUE(realStatuses[i].freqOffset() == expectStatuses[i].freqOffset());
-                break;
-            }
-            case FrontendStatusType::HIERARCHY: {
-                ASSERT_TRUE(realStatuses[i].hierarchy() == expectStatuses[i].hierarchy());
-                break;
-            }
-            case FrontendStatusType::RF_LOCK: {
-                ASSERT_TRUE(realStatuses[i].isRfLocked() == expectStatuses[i].isRfLocked());
-                break;
-            }
-            case FrontendStatusType::ATSC3_PLP_INFO:
-                // TODO: verify plpinfo
-                break;
-            default:
+            default: {
                 continue;
+            }
         }
     }
     ASSERT_TRUE(status == Result::SUCCESS);
@@ -380,7 +402,7 @@
             return failure();
         }
     }
-    mFrontendCallback->tuneTestOnLock(mFrontend, config.settings, config.settingsExt);
+    mFrontendCallback->tuneTestOnLock(mFrontend, config.settings, config.settingsExt1_1);
     return AssertionResult(true);
 }
 
@@ -425,7 +447,7 @@
     ASSERT_TRUE(openFrontendById(feId));
     ASSERT_TRUE(setFrontendCallback());
     ASSERT_TRUE(tuneFrontend(frontendConf, false /*testWithDemux*/));
-    verifyFrontendStatus(frontendConf.tuneStatusTypes, frontendConf.expectTuneStatuses);
+    verifyFrontendStatusExt1_1(frontendConf.tuneStatusTypes, frontendConf.expectTuneStatuses);
     ASSERT_TRUE(stopTuneFrontend(false /*testWithDemux*/));
     ASSERT_TRUE(closeFrontend());
 }
@@ -440,3 +462,14 @@
     ASSERT_TRUE(stopScanFrontend());
     ASSERT_TRUE(closeFrontend());
 }
+
+void FrontendTests::getFrontendDtmbCapsTest() {
+    uint32_t feId;
+    getFrontendIdByType(
+            static_cast<FrontendType>(android::hardware::tv::tuner::V1_1::FrontendType::DTMB),
+            feId);
+    if (feId != INVALID_ID) {
+        ALOGD("[vts] Found DTMB Frontend");
+        ASSERT_TRUE(getFrontendDtmbCaps(feId));
+    }
+}
diff --git a/tv/tuner/1.1/vts/functional/FrontendTests.h b/tv/tuner/1.1/vts/functional/FrontendTests.h
index 8986d81..243d9de 100644
--- a/tv/tuner/1.1/vts/functional/FrontendTests.h
+++ b/tv/tuner/1.1/vts/functional/FrontendTests.h
@@ -15,9 +15,9 @@
  */
 
 #include <android-base/logging.h>
-#include <android/hardware/tv/tuner/1.0/IFrontendCallback.h>
 #include <android/hardware/tv/tuner/1.0/types.h>
 #include <android/hardware/tv/tuner/1.1/IFrontend.h>
+#include <android/hardware/tv/tuner/1.1/IFrontendCallback.h>
 #include <android/hardware/tv/tuner/1.1/ITuner.h>
 #include <binder/MemoryDealer.h>
 #include <gtest/gtest.h>
@@ -54,8 +54,12 @@
 using android::hardware::tv::tuner::V1_0::FrontendScanMessageType;
 using android::hardware::tv::tuner::V1_0::FrontendScanType;
 using android::hardware::tv::tuner::V1_0::IFrontend;
-using android::hardware::tv::tuner::V1_0::IFrontendCallback;
 using android::hardware::tv::tuner::V1_0::Result;
+using android::hardware::tv::tuner::V1_1::FrontendDtmbCapabilities;
+using android::hardware::tv::tuner::V1_1::FrontendModulation;
+using android::hardware::tv::tuner::V1_1::FrontendScanMessageExt1_1;
+using android::hardware::tv::tuner::V1_1::FrontendScanMessageTypeExt1_1;
+using android::hardware::tv::tuner::V1_1::IFrontendCallback;
 using android::hardware::tv::tuner::V1_1::ITuner;
 
 using ::testing::AssertionResult;
@@ -70,9 +74,11 @@
     virtual Return<void> onEvent(FrontendEventType frontendEventType) override;
     virtual Return<void> onScanMessage(FrontendScanMessageType type,
                                        const FrontendScanMessage& message) override;
+    virtual Return<void> onScanMessageExt1_1(FrontendScanMessageTypeExt1_1 type,
+                                             const FrontendScanMessageExt1_1& message) override;
 
     void tuneTestOnLock(sp<IFrontend>& frontend, FrontendSettings settings,
-                        FrontendSettingsExt settingsExt);
+                        FrontendSettingsExt1_1 settingsExt1_1);
     void scanTest(sp<IFrontend>& frontend, FrontendConfig config, FrontendScanType type);
 
     // Helper methods
@@ -80,6 +86,8 @@
     void resetBlindScanStartingFrequency(FrontendConfig& config, uint32_t resetingFreq);
 
   private:
+    void readFrontendScanMessageExt1_1Modulation(FrontendModulation modulation);
+
     bool mEventReceived = false;
     bool mScanMessageReceived = false;
     bool mLockMsgReceived = false;
@@ -109,14 +117,16 @@
     AssertionResult scanFrontend(FrontendConfig config, FrontendScanType type);
     AssertionResult stopScanFrontend();
     AssertionResult tuneFrontend(FrontendConfig config, bool testWithDemux);
-    void verifyFrontendStatus(vector<FrontendStatusType> statusTypes,
-                              vector<FrontendStatus> expectStatuses);
+    void verifyFrontendStatusExt1_1(vector<FrontendStatusTypeExt1_1> statusTypes,
+                                    vector<FrontendStatusExt1_1> expectStatuses);
     AssertionResult stopTuneFrontend(bool testWithDemux);
     AssertionResult closeFrontend();
+    AssertionResult getFrontendDtmbCaps(uint32_t);
 
     void getFrontendIdByType(FrontendType feType, uint32_t& feId);
     void tuneTest(FrontendConfig frontendConf);
     void scanTest(FrontendConfig frontend, FrontendScanType type);
+    void getFrontendDtmbCapsTest();
 
     void setDvrTests(DvrTests dvrTests) { mDvrTests = dvrTests; }
     void setDemux(sp<IDemux> demux) { mDvrTests.setDemux(demux); }
diff --git a/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.cpp b/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.cpp
index f87fa3c..db2ac1b 100644
--- a/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.cpp
+++ b/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.cpp
@@ -69,6 +69,7 @@
     ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId_64bit(filterId));
     ASSERT_TRUE(mFilterTests.getSharedAvMemoryHandle(filterId));
     ASSERT_TRUE(mFilterTests.configFilter(filterConf.settings, filterId));
+    ASSERT_TRUE(mFilterTests.configAvFilterStreamType(filterConf.streamType, filterId));
     ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId));
     ASSERT_TRUE(mFilterTests.startFilter(filterId));
     // tune test
@@ -142,13 +143,13 @@
     recordSingleFilterTest(filterArray[TS_RECORD0], frontendArray[DVBT], dvrArray[DVR_RECORD0]);
 }
 
-TEST_P(TunerFrontendHidlTest, TuneFrontendWithFrontendSettingsExt) {
-    description("Tune one Frontend with specific setting and check Lock event");
+TEST_P(TunerFrontendHidlTest, TuneFrontendWithFrontendSettingsExt1_1) {
+    description("Tune one Frontend with v1_1 extended setting and check Lock event");
     mFrontendTests.tuneTest(frontendArray[DVBT]);
 }
 
 TEST_P(TunerFrontendHidlTest, BlindScanFrontendWithEndFrequency) {
-    description("Run an blind frontend scan with specific setting and check lock scanMessage");
+    description("Run an blind frontend scan with v1_1 extended setting and check lock scanMessage");
     mFrontendTests.scanTest(frontendScanArray[SCAN_DVBT], FrontendScanType::SCAN_BLIND);
 }
 
@@ -157,6 +158,11 @@
     mediaFilterUsingSharedMemoryTest(filterArray[TS_VIDEO0], frontendArray[DVBT]);
 }
 
+TEST_P(TunerFrontendHidlTest, GetFrontendDtmbCaps) {
+    description("Test to query Dtmb frontend caps if exists");
+    mFrontendTests.getFrontendDtmbCapsTest();
+}
+
 INSTANTIATE_TEST_SUITE_P(
         PerInstance, TunerBroadcastHidlTest,
         testing::ValuesIn(android::hardware::getAllHalInstanceNames(ITuner::descriptor)),
diff --git a/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TestConfigurations.h b/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TestConfigurations.h
index 36b4bd2..cb86ce8 100644
--- a/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TestConfigurations.h
+++ b/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TestConfigurations.h
@@ -43,12 +43,15 @@
 using android::hardware::tv::tuner::V1_0::FrontendDvbtStandard;
 using android::hardware::tv::tuner::V1_0::FrontendDvbtTransmissionMode;
 using android::hardware::tv::tuner::V1_0::FrontendSettings;
-using android::hardware::tv::tuner::V1_0::FrontendStatus;
-using android::hardware::tv::tuner::V1_0::FrontendStatusType;
 using android::hardware::tv::tuner::V1_0::FrontendType;
 using android::hardware::tv::tuner::V1_0::PlaybackSettings;
 using android::hardware::tv::tuner::V1_0::RecordSettings;
-using android::hardware::tv::tuner::V1_1::FrontendSettingsExt;
+using android::hardware::tv::tuner::V1_1::AudioStreamType;
+using android::hardware::tv::tuner::V1_1::AvStreamType;
+using android::hardware::tv::tuner::V1_1::FrontendSettingsExt1_1;
+using android::hardware::tv::tuner::V1_1::FrontendStatusExt1_1;
+using android::hardware::tv::tuner::V1_1::FrontendStatusTypeExt1_1;
+using android::hardware::tv::tuner::V1_1::VideoStreamType;
 
 using namespace std;
 
@@ -91,6 +94,7 @@
     uint32_t bufferSize;
     DemuxFilterType type;
     DemuxFilterSettings settings;
+    AvStreamType streamType;
     uint32_t ipCid;
 
     bool operator<(const FilterConfig& /*c*/) const { return false; }
@@ -100,9 +104,9 @@
     bool isSoftwareFe;
     FrontendType type;
     FrontendSettings settings;
-    FrontendSettingsExt settingsExt;
-    vector<FrontendStatusType> tuneStatusTypes;
-    vector<FrontendStatus> expectTuneStatuses;
+    FrontendSettingsExt1_1 settingsExt1_1;
+    vector<FrontendStatusTypeExt1_1> tuneStatusTypes;
+    vector<FrontendStatusExt1_1> expectTuneStatuses;
 };
 
 struct DvrConfig {
@@ -132,16 +136,16 @@
             .standard = FrontendDvbtStandard::T,
     };
     frontendArray[DVBT].type = FrontendType::DVBT, frontendArray[DVBT].settings.dvbt(dvbtSettings);
-    vector<FrontendStatusType> types;
-    types.push_back(FrontendStatusType::DEMOD_LOCK);
-    FrontendStatus status;
-    status.isDemodLocked(true);
-    vector<FrontendStatus> statuses;
+    vector<FrontendStatusTypeExt1_1> types;
+    types.push_back(FrontendStatusTypeExt1_1::UEC);
+    FrontendStatusExt1_1 status;
+    status.uec(4);
+    vector<FrontendStatusExt1_1> statuses;
     statuses.push_back(status);
     frontendArray[DVBT].tuneStatusTypes = types;
     frontendArray[DVBT].expectTuneStatuses = statuses;
     frontendArray[DVBT].isSoftwareFe = true;
-    frontendArray[DVBT].settingsExt.settingExt.dvbt({
+    frontendArray[DVBT].settingsExt1_1.settingExt.dvbt({
             .transmissionMode =
                     android::hardware::tv::tuner::V1_1::FrontendDvbtTransmissionMode::MODE_8K_E,
     });
@@ -164,8 +168,8 @@
             .isHighPriority = true,
             .standard = FrontendDvbtStandard::T,
     });
-    frontendScanArray[SCAN_DVBT].settingsExt.endFrequency = 800000;
-    frontendScanArray[SCAN_DVBT].settingsExt.settingExt.dvbt({
+    frontendScanArray[SCAN_DVBT].settingsExt1_1.endFrequency = 800000;
+    frontendScanArray[SCAN_DVBT].settingsExt1_1.settingExt.dvbt({
             .transmissionMode =
                     android::hardware::tv::tuner::V1_1::FrontendDvbtTransmissionMode::MODE_8K_E,
     });
@@ -184,6 +188,7 @@
     filterArray[TS_VIDEO1].bufferSize = FMQ_SIZE_16M;
     filterArray[TS_VIDEO1].settings.ts().tpid = 256;
     filterArray[TS_VIDEO1].settings.ts().filterSettings.av({.isPassthrough = false});
+    filterArray[TS_VIDEO1].streamType.video(VideoStreamType::MPEG1);
     // TS AUDIO filter setting
     filterArray[TS_AUDIO0].type.mainType = DemuxFilterMainType::TS;
     filterArray[TS_AUDIO0].type.subType.tsFilterType(DemuxTsFilterType::AUDIO);
@@ -195,6 +200,7 @@
     filterArray[TS_AUDIO1].bufferSize = FMQ_SIZE_16M;
     filterArray[TS_AUDIO1].settings.ts().tpid = 257;
     filterArray[TS_AUDIO1].settings.ts().filterSettings.av({.isPassthrough = false});
+    filterArray[TS_VIDEO1].streamType.audio(AudioStreamType::MP3);
     // TS PES filter setting
     filterArray[TS_PES0].type.mainType = DemuxFilterMainType::TS;
     filterArray[TS_PES0].type.subType.tsFilterType(DemuxTsFilterType::PES);
diff --git a/tv/tuner/README.md b/tv/tuner/README.md
index aa1f62d..2a358f5 100644
--- a/tv/tuner/README.md
+++ b/tv/tuner/README.md
@@ -5,8 +5,3 @@
 TV specific tuners.
 
 See 1.0/ITuner.hal for an overview.
-
-*** note
-**Warning:** The HALs are not (yet) frozen, as the HAL definition is
-expected to evolve between Android releases.
-***
diff --git a/wifi/hostapd/1.2/vts/functional/Android.bp b/wifi/hostapd/1.2/vts/functional/Android.bp
index cec1782..577174b 100644
--- a/wifi/hostapd/1.2/vts/functional/Android.bp
+++ b/wifi/hostapd/1.2/vts/functional/Android.bp
@@ -25,12 +25,15 @@
         "VtsHalWifiHostapdV1_0TargetTestUtil",
         "android.hardware.wifi.hostapd@1.0",
         "android.hardware.wifi.hostapd@1.1",
-	"android.hardware.wifi.hostapd@1.2",
+        "android.hardware.wifi.hostapd@1.2",
+        "android.hardware.wifi.hostapd@1.3",
         "android.hardware.wifi@1.0",
         "libgmock",
         "libwifi-system",
         "libwifi-system-iface",
     ],
-    test_suites: ["general-tests", "vts"],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
 }
-
diff --git a/wifi/hostapd/1.2/vts/functional/hostapd_hidl_test.cpp b/wifi/hostapd/1.2/vts/functional/hostapd_hidl_test.cpp
index 99784a4..c40c582 100644
--- a/wifi/hostapd/1.2/vts/functional/hostapd_hidl_test.cpp
+++ b/wifi/hostapd/1.2/vts/functional/hostapd_hidl_test.cpp
@@ -25,6 +25,7 @@
 
 #include <android/hardware/wifi/1.0/IWifi.h>
 #include <android/hardware/wifi/hostapd/1.2/IHostapd.h>
+#include <android/hardware/wifi/hostapd/1.3/IHostapd.h>
 
 #include "hostapd_hidl_call_util.h"
 #include "hostapd_hidl_test_utils.h"
@@ -216,12 +217,20 @@
     std::string hostapd_instance_name_;
 };
 
+bool is_1_3(const sp<IHostapd>& hostapd) {
+    sp<::android::hardware::wifi::hostapd::V1_3::IHostapd> hostapd_1_3 =
+        ::android::hardware::wifi::hostapd::V1_3::IHostapd::castFrom(hostapd);
+    return hostapd_1_3.get() != nullptr;
+}
+
 /**
  * Adds an access point with PSK network config & ACS enabled.
  * Access point creation should pass.
  */
 TEST_P(HostapdHidlTest, AddPskAccessPointWithAcs) {
     if (!isAcsSupport_) GTEST_SKIP() << "Missing ACS support";
+    if (is_1_3(hostapd_))
+        GTEST_SKIP() << "Ignore addAccessPoint_1_2 on hostapd 1_3";
     auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_2,
                               getIfaceParamsWithAcs(), getPskNwParams());
     EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
@@ -233,6 +242,8 @@
  */
 TEST_P(HostapdHidlTest, AddPskAccessPointWithAcsAndFreqRange) {
     if (!isAcsSupport_) GTEST_SKIP() << "Missing ACS support";
+    if (is_1_3(hostapd_))
+        GTEST_SKIP() << "Ignore addAccessPoint_1_2 on hostapd 1_3";
     auto status =
         HIDL_INVOKE(hostapd_, addAccessPoint_1_2,
                     getIfaceParamsWithAcsAndFreqRange(), getPskNwParams());
@@ -245,6 +256,8 @@
  */
 TEST_P(HostapdHidlTest, AddPskAccessPointWithAcsAndInvalidFreqRange) {
     if (!isAcsSupport_) GTEST_SKIP() << "Missing ACS support";
+    if (is_1_3(hostapd_))
+        GTEST_SKIP() << "Ignore addAccessPoint_1_2 on hostapd 1_3";
     auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_2,
                               getIfaceParamsWithAcsAndInvalidFreqRange(),
                               getPskNwParams());
@@ -257,6 +270,8 @@
  */
 TEST_P(HostapdHidlTest, AddOpenAccessPointWithAcs) {
     if (!isAcsSupport_) GTEST_SKIP() << "Missing ACS support";
+    if (is_1_3(hostapd_))
+        GTEST_SKIP() << "Ignore addAccessPoint_1_2 on hostapd 1_3";
     auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_2,
                               getIfaceParamsWithAcs(), getOpenNwParams());
     EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
@@ -267,6 +282,8 @@
  * Access point creation should pass.
  */
 TEST_P(HostapdHidlTest, AddPskAccessPointWithoutAcs) {
+    if (is_1_3(hostapd_))
+        GTEST_SKIP() << "Ignore addAccessPoint_1_2 on hostapd 1_3";
     auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_2,
                               getIfaceParamsWithoutAcs(), getPskNwParams());
     EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
@@ -277,6 +294,8 @@
  * Access point creation should pass.
  */
 TEST_P(HostapdHidlTest, AddOpenAccessPointWithoutAcs) {
+    if (is_1_3(hostapd_))
+        GTEST_SKIP() << "Ignore addAccessPoint_1_2 on hostapd 1_3";
     auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_2,
                               getIfaceParamsWithoutAcs(), getOpenNwParams());
     EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
@@ -288,6 +307,8 @@
  */
 TEST_P(HostapdHidlTest, AddSaeTransitionAccessPointWithoutAcs) {
     if (!isWpa3SaeSupport_) GTEST_SKIP() << "Missing SAE support";
+    if (is_1_3(hostapd_))
+        GTEST_SKIP() << "Ignore addAccessPoint_1_2 on hostapd 1_3";
     auto status =
         HIDL_INVOKE(hostapd_, addAccessPoint_1_2, getIfaceParamsWithoutAcs(),
                     getSaeTransitionNwParams());
@@ -300,6 +321,8 @@
  */
 TEST_P(HostapdHidlTest, AddSAEAccessPointWithoutAcs) {
     if (!isWpa3SaeSupport_) GTEST_SKIP() << "Missing SAE support";
+    if (is_1_3(hostapd_))
+        GTEST_SKIP() << "Ignore addAccessPoint_1_2 on hostapd 1_3";
     auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_2,
                               getIfaceParamsWithoutAcs(), getSaeNwParams());
     EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
@@ -311,6 +334,8 @@
  */
 TEST_P(HostapdHidlTest, RemoveAccessPointWithAcs) {
     if (!isAcsSupport_) GTEST_SKIP() << "Missing ACS support";
+    if (is_1_3(hostapd_))
+        GTEST_SKIP() << "Ignore addAccessPoint_1_2 on hostapd 1_3";
     auto status_1_2 = HIDL_INVOKE(hostapd_, addAccessPoint_1_2,
                                   getIfaceParamsWithAcs(), getPskNwParams());
     EXPECT_EQ(HostapdStatusCode::SUCCESS, status_1_2.code);
@@ -326,6 +351,8 @@
  * Access point creation & removal should pass.
  */
 TEST_P(HostapdHidlTest, RemoveAccessPointWithoutAcs) {
+    if (is_1_3(hostapd_))
+        GTEST_SKIP() << "Ignore addAccessPoint_1_2 on hostapd 1_3";
     auto status_1_2 = HIDL_INVOKE(hostapd_, addAccessPoint_1_2,
                                   getIfaceParamsWithoutAcs(), getPskNwParams());
     EXPECT_EQ(HostapdStatusCode::SUCCESS, status_1_2.code);
@@ -341,6 +368,8 @@
  * Access point creation should fail.
  */
 TEST_P(HostapdHidlTest, AddPskAccessPointWithInvalidChannel) {
+    if (is_1_3(hostapd_))
+        GTEST_SKIP() << "Ignore addAccessPoint_1_2 on hostapd 1_3";
     auto status =
         HIDL_INVOKE(hostapd_, addAccessPoint_1_2,
                     getIfaceParamsWithInvalidChannel(), getPskNwParams());
@@ -352,6 +381,8 @@
  * Access point creation should fail.
  */
 TEST_P(HostapdHidlTest, AddInvalidPskAccessPointWithoutAcs) {
+    if (is_1_3(hostapd_))
+        GTEST_SKIP() << "Ignore addAccessPoint_1_2 on hostapd 1_3";
     auto status =
         HIDL_INVOKE(hostapd_, addAccessPoint_1_2, getIfaceParamsWithoutAcs(),
                     getInvalidPskNwParams());
@@ -364,6 +395,8 @@
  */
 TEST_P(HostapdHidlTest, AddInvalidSaeTransitionAccessPointWithoutAcs) {
     if (!isWpa3SaeSupport_) GTEST_SKIP() << "Missing SAE support";
+    if (is_1_3(hostapd_))
+        GTEST_SKIP() << "Ignore addAccessPoint_1_2 on hostapd 1_3";
     auto status =
         HIDL_INVOKE(hostapd_, addAccessPoint_1_2, getIfaceParamsWithoutAcs(),
                     getInvalidSaeTransitionNwParams());
@@ -376,6 +409,8 @@
  */
 TEST_P(HostapdHidlTest, AddInvalidSaeAccessPointWithoutAcs) {
     if (!isWpa3SaeSupport_) GTEST_SKIP() << "Missing SAE support";
+    if (is_1_3(hostapd_))
+        GTEST_SKIP() << "Ignore addAccessPoint_1_2 on hostapd 1_3";
     auto status =
         HIDL_INVOKE(hostapd_, addAccessPoint_1_2, getIfaceParamsWithoutAcs(),
                     getInvalidSaeNwParams());
@@ -398,6 +433,8 @@
  * when hotspot interface available.
  */
 TEST_P(HostapdHidlTest, DisconnectClientWhenIfacAvailable) {
+    if (is_1_3(hostapd_))
+        GTEST_SKIP() << "Ignore addAccessPoint_1_2 on hostapd 1_3";
     auto status_1_2 =
         HIDL_INVOKE(hostapd_, addAccessPoint_1_2, getIfaceParamsWithoutAcs(),
                     getOpenNwParams());
diff --git a/wifi/hostapd/1.3/vts/OWNERS b/wifi/hostapd/1.3/vts/OWNERS
new file mode 100644
index 0000000..8bfb148
--- /dev/null
+++ b/wifi/hostapd/1.3/vts/OWNERS
@@ -0,0 +1,2 @@
+rpius@google.com
+etancohen@google.com
diff --git a/wifi/hostapd/1.3/vts/functional/Android.bp b/wifi/hostapd/1.3/vts/functional/Android.bp
new file mode 100644
index 0000000..07cebb0
--- /dev/null
+++ b/wifi/hostapd/1.3/vts/functional/Android.bp
@@ -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.
+//
+
+cc_test {
+    name: "VtsHalWifiHostapdV1_3TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: [
+        "hostapd_hidl_test.cpp",
+    ],
+    static_libs: [
+        "VtsHalWifiV1_0TargetTestUtil",
+        "VtsHalWifiHostapdV1_0TargetTestUtil",
+        "android.hardware.wifi.hostapd@1.0",
+        "android.hardware.wifi.hostapd@1.1",
+        "android.hardware.wifi.hostapd@1.2",
+        "android.hardware.wifi.hostapd@1.3",
+        "android.hardware.wifi@1.0",
+        "libgmock",
+        "libwifi-system",
+        "libwifi-system-iface",
+    ],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
+}
diff --git a/wifi/hostapd/1.3/vts/functional/hostapd_hidl_test.cpp b/wifi/hostapd/1.3/vts/functional/hostapd_hidl_test.cpp
new file mode 100644
index 0000000..d6c750f
--- /dev/null
+++ b/wifi/hostapd/1.3/vts/functional/hostapd_hidl_test.cpp
@@ -0,0 +1,433 @@
+/*
+ * 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 <VtsCoreUtil.h>
+
+#include <android-base/logging.h>
+#include <cutils/properties.h>
+
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
+
+#include <android/hardware/wifi/1.0/IWifi.h>
+#include <android/hardware/wifi/hostapd/1.3/IHostapd.h>
+
+#include "hostapd_hidl_call_util.h"
+#include "hostapd_hidl_test_utils.h"
+
+using ::android::sp;
+using ::android::hardware::hidl_string;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::wifi::hostapd::V1_2::DebugLevel;
+using ::android::hardware::wifi::hostapd::V1_2::HostapdStatusCode;
+using ::android::hardware::wifi::hostapd::V1_2::Ieee80211ReasonCode;
+using ::android::hardware::wifi::hostapd::V1_3::IHostapd;
+using ::android::hardware::wifi::V1_0::IWifi;
+
+namespace {
+constexpr unsigned char kNwSsid[] = {'t', 'e', 's', 't', '1',
+                                     '2', '3', '4', '5'};
+constexpr char kNwPassphrase[] = "test12345";
+constexpr char kInvalidMaxPskNwPassphrase[] =
+    "0123456789012345678901234567890123456789012345678901234567890123456789";
+constexpr char kInvalidMinPskNwPassphrase[] = "test";
+constexpr int kIfaceChannel = 6;
+constexpr int kIfaceInvalidChannel = 567;
+constexpr uint8_t kTestZeroMacAddr[] = {[0 ... 5] = 0x0};
+constexpr Ieee80211ReasonCode kTestDisconnectReasonCode =
+    Ieee80211ReasonCode::WLAN_REASON_UNSPECIFIED;
+}  // namespace
+
+class HostapdHidlTest
+    : public ::testing::TestWithParam<std::tuple<std::string, std::string>> {
+   public:
+    virtual void SetUp() override {
+        wifi_instance_name_ = std::get<0>(GetParam());
+        hostapd_instance_name_ = std::get<1>(GetParam());
+        stopSupplicantIfNeeded(wifi_instance_name_);
+        startHostapdAndWaitForHidlService(wifi_instance_name_,
+                                          hostapd_instance_name_);
+        hostapd_ = IHostapd::getService(hostapd_instance_name_);
+        ASSERT_NE(hostapd_.get(), nullptr);
+        HIDL_INVOKE(hostapd_, setDebugParams, DebugLevel::EXCESSIVE);
+        isAcsSupport_ = testing::checkSubstringInCommandOutput(
+            "/system/bin/cmd wifi get-softap-supported-features",
+            "wifi_softap_acs_supported");
+        isWpa3SaeSupport_ = testing::checkSubstringInCommandOutput(
+            "/system/bin/cmd wifi get-softap-supported-features",
+            "wifi_softap_wpa3_sae_supported");
+    }
+
+    virtual void TearDown() override {
+        HIDL_INVOKE_VOID_WITHOUT_ARGUMENTS(hostapd_, terminate);
+        stopHostapd(wifi_instance_name_);
+    }
+
+   protected:
+    bool isWpa3SaeSupport_ = false;
+    bool isAcsSupport_ = false;
+    std::string getPrimaryWlanIfaceName() {
+        std::array<char, PROPERTY_VALUE_MAX> buffer;
+        auto res = property_get("ro.vendor.wifi.sap.interface", buffer.data(),
+                                nullptr);
+        if (res > 0) return buffer.data();
+        property_get("wifi.interface", buffer.data(), "wlan0");
+        return buffer.data();
+    }
+
+    IHostapd::IfaceParams getIfaceParamsWithoutAcs() {
+        ::android::hardware::wifi::hostapd::V1_0::IHostapd::IfaceParams
+            iface_params;
+        ::android::hardware::wifi::hostapd::V1_1::IHostapd::IfaceParams
+            iface_params_1_1;
+        IHostapd::IfaceParams iface_params_1_2;
+
+        iface_params.ifaceName = getPrimaryWlanIfaceName();
+        iface_params.hwModeParams.enable80211N = true;
+        iface_params.hwModeParams.enable80211AC = false;
+        iface_params.channelParams.enableAcs = false;
+        iface_params.channelParams.acsShouldExcludeDfs = false;
+        iface_params.channelParams.channel = kIfaceChannel;
+        iface_params_1_1.V1_0 = iface_params;
+        iface_params_1_2.V1_1 = iface_params_1_1;
+        // Newly added attributes in V1_2
+        iface_params_1_2.hwModeParams.enable80211AX = false;
+        iface_params_1_2.hwModeParams.enable6GhzBand = false;
+        iface_params_1_2.channelParams.bandMask = 0;
+        iface_params_1_2.channelParams.bandMask |=
+            IHostapd::BandMask::BAND_2_GHZ;
+        return iface_params_1_2;
+    }
+
+    IHostapd::IfaceParams getIfaceParamsWithAcs() {
+        // First get the settings for WithoutAcs and then make changes
+        IHostapd::IfaceParams iface_params_1_2 = getIfaceParamsWithoutAcs();
+        iface_params_1_2.V1_1.V1_0.channelParams.enableAcs = true;
+        iface_params_1_2.V1_1.V1_0.channelParams.acsShouldExcludeDfs = true;
+        iface_params_1_2.V1_1.V1_0.channelParams.channel = 0;
+        iface_params_1_2.channelParams.bandMask |=
+            IHostapd::BandMask::BAND_5_GHZ;
+
+        return iface_params_1_2;
+    }
+
+    IHostapd::IfaceParams getIfaceParamsWithAcsAndFreqRange() {
+        IHostapd::IfaceParams iface_params_1_2 = getIfaceParamsWithAcs();
+        ::android::hardware::wifi::hostapd::V1_2::IHostapd::AcsFrequencyRange
+            acsFrequencyRange;
+        acsFrequencyRange.start = 2412;
+        acsFrequencyRange.end = 2462;
+        std::vector<::android::hardware::wifi::hostapd::V1_2::IHostapd::
+                        AcsFrequencyRange>
+            vec_acsFrequencyRange;
+        vec_acsFrequencyRange.push_back(acsFrequencyRange);
+        iface_params_1_2.channelParams.acsChannelFreqRangesMhz =
+            vec_acsFrequencyRange;
+        return iface_params_1_2;
+    }
+
+    IHostapd::IfaceParams getIfaceParamsWithAcsAndInvalidFreqRange() {
+        IHostapd::IfaceParams iface_params_1_2 =
+            getIfaceParamsWithAcsAndFreqRange();
+        iface_params_1_2.channelParams.acsChannelFreqRangesMhz[0].start = 222;
+        iface_params_1_2.channelParams.acsChannelFreqRangesMhz[0].end = 999;
+        return iface_params_1_2;
+    }
+
+    IHostapd::NetworkParams getOpenNwParams() {
+        IHostapd::NetworkParams nw_params_1_3;
+        ::android::hardware::wifi::hostapd::V1_2::IHostapd::NetworkParams
+            nw_params_1_2;
+        ::android::hardware::wifi::hostapd::V1_0::IHostapd::NetworkParams
+            nw_params_1_0;
+        nw_params_1_0.ssid =
+            std::vector<uint8_t>(kNwSsid, kNwSsid + sizeof(kNwSsid));
+        nw_params_1_0.isHidden = false;
+        nw_params_1_2.V1_0 = nw_params_1_0;
+        nw_params_1_2.encryptionType = IHostapd::EncryptionType::NONE;
+        nw_params_1_3.V1_2 = nw_params_1_2;
+        nw_params_1_3.isMetered = true;
+        return nw_params_1_3;
+    }
+
+    IHostapd::NetworkParams getPskNwParamsWithNonMetered() {
+        IHostapd::NetworkParams nw_params_1_3 = getOpenNwParams();
+        nw_params_1_3.V1_2.encryptionType = IHostapd::EncryptionType::WPA2;
+        nw_params_1_3.V1_2.passphrase = kNwPassphrase;
+        nw_params_1_3.isMetered = false;
+        return nw_params_1_3;
+    }
+
+    IHostapd::NetworkParams getPskNwParams() {
+        IHostapd::NetworkParams nw_params_1_3 = getOpenNwParams();
+        nw_params_1_3.V1_2.encryptionType = IHostapd::EncryptionType::WPA2;
+        nw_params_1_3.V1_2.passphrase = kNwPassphrase;
+        return nw_params_1_3;
+    }
+
+    IHostapd::NetworkParams getInvalidPskNwParams() {
+        IHostapd::NetworkParams nw_params_1_3 = getOpenNwParams();
+        nw_params_1_3.V1_2.encryptionType = IHostapd::EncryptionType::WPA2;
+        nw_params_1_3.V1_2.passphrase = kInvalidMaxPskNwPassphrase;
+
+        return nw_params_1_3;
+    }
+
+    IHostapd::NetworkParams getSaeTransitionNwParams() {
+        IHostapd::NetworkParams nw_params_1_3 = getOpenNwParams();
+        nw_params_1_3.V1_2.encryptionType =
+            IHostapd::EncryptionType::WPA3_SAE_TRANSITION;
+        nw_params_1_3.V1_2.passphrase = kNwPassphrase;
+        return nw_params_1_3;
+    }
+
+    IHostapd::NetworkParams getInvalidSaeTransitionNwParams() {
+        IHostapd::NetworkParams nw_params_1_3 = getOpenNwParams();
+        nw_params_1_3.V1_2.encryptionType = IHostapd::EncryptionType::WPA2;
+        nw_params_1_3.V1_2.passphrase = kInvalidMinPskNwPassphrase;
+        return nw_params_1_3;
+    }
+
+    IHostapd::NetworkParams getSaeNwParams() {
+        IHostapd::NetworkParams nw_params_1_3 = getOpenNwParams();
+        nw_params_1_3.V1_2.encryptionType = IHostapd::EncryptionType::WPA3_SAE;
+        nw_params_1_3.V1_2.passphrase = kNwPassphrase;
+        return nw_params_1_3;
+    }
+
+    IHostapd::NetworkParams getInvalidSaeNwParams() {
+        IHostapd::NetworkParams nw_params_1_3 = getOpenNwParams();
+        nw_params_1_3.V1_2.encryptionType = IHostapd::EncryptionType::WPA3_SAE;
+        nw_params_1_3.V1_2.passphrase = "";
+        return nw_params_1_3;
+    }
+
+    IHostapd::IfaceParams getIfaceParamsWithInvalidChannel() {
+        IHostapd::IfaceParams iface_params_1_2 = getIfaceParamsWithoutAcs();
+        iface_params_1_2.V1_1.V1_0.channelParams.channel = kIfaceInvalidChannel;
+        return iface_params_1_2;
+    }
+
+    // IHostapd object used for all tests in this fixture.
+    sp<IHostapd> hostapd_;
+    std::string wifi_instance_name_;
+    std::string hostapd_instance_name_;
+};
+
+/**
+ * Adds an access point with PSK network config & ACS enabled.
+ * Access point creation should pass.
+ */
+TEST_P(HostapdHidlTest, AddPskAccessPointWithAcs) {
+    if (!isAcsSupport_) GTEST_SKIP() << "Missing ACS support";
+    auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_3,
+                              getIfaceParamsWithAcs(), getPskNwParams());
+    EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
+}
+
+/**
+ * Adds an access point with PSK network config, ACS enabled & frequency Range.
+ * Access point creation should pass.
+ */
+TEST_P(HostapdHidlTest, AddPskAccessPointWithAcsAndFreqRange) {
+    if (!isAcsSupport_) GTEST_SKIP() << "Missing ACS support";
+    auto status =
+        HIDL_INVOKE(hostapd_, addAccessPoint_1_3,
+                    getIfaceParamsWithAcsAndFreqRange(), getPskNwParams());
+    EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
+}
+
+/**
+ * Adds an access point with invalid channel range.
+ * Access point creation should fail.
+ */
+TEST_P(HostapdHidlTest, AddPskAccessPointWithAcsAndInvalidFreqRange) {
+    if (!isAcsSupport_) GTEST_SKIP() << "Missing ACS support";
+    auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_3,
+                              getIfaceParamsWithAcsAndInvalidFreqRange(),
+                              getPskNwParams());
+    EXPECT_NE(HostapdStatusCode::SUCCESS, status.code);
+}
+
+/**
+ * Adds an access point with Open network config & ACS enabled.
+ * Access point creation should pass.
+ */
+TEST_P(HostapdHidlTest, AddOpenAccessPointWithAcs) {
+    if (!isAcsSupport_) GTEST_SKIP() << "Missing ACS support";
+    auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_3,
+                              getIfaceParamsWithAcs(), getOpenNwParams());
+    EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
+}
+
+/**
+ * Adds an access point with PSK network config & ACS disabled.
+ * Access point creation should pass.
+ */
+TEST_P(HostapdHidlTest, AddPskAccessPointWithoutAcs) {
+    auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_3,
+                              getIfaceParamsWithoutAcs(), getPskNwParams());
+    EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
+}
+
+/**
+ * Adds an access point with PSK network config, ACS disabled & Non metered.
+ * Access point creation should pass.
+ */
+TEST_P(HostapdHidlTest, AddPskAccessPointWithoutAcsAndNonMetered) {
+    auto status =
+        HIDL_INVOKE(hostapd_, addAccessPoint_1_3, getIfaceParamsWithoutAcs(),
+                    getPskNwParamsWithNonMetered());
+    EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
+}
+
+/**
+ * Adds an access point with Open network config & ACS disabled.
+ * Access point creation should pass.
+ */
+TEST_P(HostapdHidlTest, AddOpenAccessPointWithoutAcs) {
+    auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_3,
+                              getIfaceParamsWithoutAcs(), getOpenNwParams());
+    EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
+}
+
+/**
+ * Adds an access point with SAE Transition network config & ACS disabled.
+ * Access point creation should pass.
+ */
+TEST_P(HostapdHidlTest, AddSaeTransitionAccessPointWithoutAcs) {
+    if (!isWpa3SaeSupport_) GTEST_SKIP() << "Missing SAE support";
+    auto status =
+        HIDL_INVOKE(hostapd_, addAccessPoint_1_3, getIfaceParamsWithoutAcs(),
+                    getSaeTransitionNwParams());
+    EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
+}
+
+/**
+ * Adds an access point with SAE network config & ACS disabled.
+ * Access point creation should pass.
+ */
+TEST_P(HostapdHidlTest, AddSAEAccessPointWithoutAcs) {
+    if (!isWpa3SaeSupport_) GTEST_SKIP() << "Missing SAE support";
+    auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_3,
+                              getIfaceParamsWithoutAcs(), getSaeNwParams());
+    EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
+}
+
+/**
+ * Adds & then removes an access point with PSK network config & ACS enabled.
+ * Access point creation & removal should pass.
+ */
+TEST_P(HostapdHidlTest, RemoveAccessPointWithAcs) {
+    if (!isAcsSupport_) GTEST_SKIP() << "Missing ACS support";
+    auto status_1_2 = HIDL_INVOKE(hostapd_, addAccessPoint_1_3,
+                                  getIfaceParamsWithAcs(), getPskNwParams());
+    EXPECT_EQ(HostapdStatusCode::SUCCESS, status_1_2.code);
+    auto status =
+        HIDL_INVOKE(hostapd_, removeAccessPoint, getPrimaryWlanIfaceName());
+    EXPECT_EQ(
+        android::hardware::wifi::hostapd::V1_0::HostapdStatusCode::SUCCESS,
+        status.code);
+}
+
+/**
+ * Adds & then removes an access point with PSK network config & ACS disabled.
+ * Access point creation & removal should pass.
+ */
+TEST_P(HostapdHidlTest, RemoveAccessPointWithoutAcs) {
+    auto status_1_2 = HIDL_INVOKE(hostapd_, addAccessPoint_1_3,
+                                  getIfaceParamsWithoutAcs(), getPskNwParams());
+    EXPECT_EQ(HostapdStatusCode::SUCCESS, status_1_2.code);
+    auto status =
+        HIDL_INVOKE(hostapd_, removeAccessPoint, getPrimaryWlanIfaceName());
+    EXPECT_EQ(
+        android::hardware::wifi::hostapd::V1_0::HostapdStatusCode::SUCCESS,
+        status.code);
+}
+
+/**
+ * Adds an access point with invalid channel.
+ * Access point creation should fail.
+ */
+TEST_P(HostapdHidlTest, AddPskAccessPointWithInvalidChannel) {
+    auto status =
+        HIDL_INVOKE(hostapd_, addAccessPoint_1_3,
+                    getIfaceParamsWithInvalidChannel(), getPskNwParams());
+    EXPECT_NE(HostapdStatusCode::SUCCESS, status.code);
+}
+
+/**
+ * Adds an access point with invalid PSK network config.
+ * Access point creation should fail.
+ */
+TEST_P(HostapdHidlTest, AddInvalidPskAccessPointWithoutAcs) {
+    auto status =
+        HIDL_INVOKE(hostapd_, addAccessPoint_1_3, getIfaceParamsWithoutAcs(),
+                    getInvalidPskNwParams());
+    EXPECT_NE(HostapdStatusCode::SUCCESS, status.code);
+}
+
+/**
+ * Adds an access point with invalid SAE transition network config.
+ * Access point creation should fail.
+ */
+TEST_P(HostapdHidlTest, AddInvalidSaeTransitionAccessPointWithoutAcs) {
+    if (!isWpa3SaeSupport_) GTEST_SKIP() << "Missing SAE support";
+    auto status =
+        HIDL_INVOKE(hostapd_, addAccessPoint_1_3, getIfaceParamsWithoutAcs(),
+                    getInvalidSaeTransitionNwParams());
+    EXPECT_NE(HostapdStatusCode::SUCCESS, status.code);
+}
+
+/**
+ * Adds an access point with invalid SAE network config.
+ * Access point creation should fail.
+ */
+TEST_P(HostapdHidlTest, AddInvalidSaeAccessPointWithoutAcs) {
+    if (!isWpa3SaeSupport_) GTEST_SKIP() << "Missing SAE support";
+    auto status =
+        HIDL_INVOKE(hostapd_, addAccessPoint_1_3, getIfaceParamsWithoutAcs(),
+                    getInvalidSaeNwParams());
+    EXPECT_NE(HostapdStatusCode::SUCCESS, status.code);
+}
+
+/**
+ * forceClientDisconnect should return FAILURE_CLIENT_UNKNOWN
+ * when hotspot interface available.
+ */
+TEST_P(HostapdHidlTest, DisconnectClientWhenIfacAvailable) {
+    auto status_1_2 =
+        HIDL_INVOKE(hostapd_, addAccessPoint_1_3, getIfaceParamsWithoutAcs(),
+                    getOpenNwParams());
+    EXPECT_EQ(HostapdStatusCode::SUCCESS, status_1_2.code);
+
+    status_1_2 =
+        HIDL_INVOKE(hostapd_, forceClientDisconnect, getPrimaryWlanIfaceName(),
+                    kTestZeroMacAddr, kTestDisconnectReasonCode);
+    EXPECT_EQ(HostapdStatusCode::FAILURE_CLIENT_UNKNOWN, status_1_2.code);
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(HostapdHidlTest);
+INSTANTIATE_TEST_CASE_P(
+    PerInstance, HostapdHidlTest,
+    testing::Combine(
+        testing::ValuesIn(
+            android::hardware::getAllHalInstanceNames(IWifi::descriptor)),
+        testing::ValuesIn(android::hardware::getAllHalInstanceNames(
+            android::hardware::wifi::hostapd::V1_2::IHostapd::descriptor))),
+    android::hardware::PrintInstanceTupleNameToString<>);
diff --git a/wifi/supplicant/1.0/vts/functional/VtsHalWifiSupplicantP2pV1_0TargetTest.cpp b/wifi/supplicant/1.0/vts/functional/VtsHalWifiSupplicantP2pV1_0TargetTest.cpp
index 01840e2..b2bdaf1 100644
--- a/wifi/supplicant/1.0/vts/functional/VtsHalWifiSupplicantP2pV1_0TargetTest.cpp
+++ b/wifi/supplicant/1.0/vts/functional/VtsHalWifiSupplicantP2pV1_0TargetTest.cpp
@@ -18,9 +18,6 @@
 #include "supplicant_hidl_test_utils.h"
 
 int main(int argc, char** argv) {
-    if (!::testing::deviceSupportsFeature("android.hardware.wifi.direct"))
-        return 0;
-
     ::testing::InitGoogleTest(&argc, argv);
     return RUN_ALL_TESTS();
 }
diff --git a/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp
index da3996b..be6aad9 100644
--- a/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp
+++ b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp
@@ -52,6 +52,10 @@
 // Helper function to initialize the driver and firmware to STA mode
 // using the vendor HAL HIDL interface.
 void initilializeDriverAndFirmware(const std::string& wifi_instance_name) {
+    // Skip if wifi instance is not set.
+    if (wifi_instance_name == "") {
+        return;
+    }
     if (getWifi(wifi_instance_name) != nullptr) {
         sp<IWifiChip> wifi_chip = getWifiChip(wifi_instance_name);
         ChipModeId mode_id;
@@ -65,6 +69,10 @@
 // Helper function to deinitialize the driver and firmware
 // using the vendor HAL HIDL interface.
 void deInitilializeDriverAndFirmware(const std::string& wifi_instance_name) {
+    // Skip if wifi instance is not set.
+    if (wifi_instance_name == "") {
+        return;
+    }
     if (getWifi(wifi_instance_name) != nullptr) {
         stopWifi(wifi_instance_name);
     } else {
diff --git a/wifi/supplicant/1.0/vts/functional/supplicant_p2p_iface_hidl_test.cpp b/wifi/supplicant/1.0/vts/functional/supplicant_p2p_iface_hidl_test.cpp
index e74fd59..325f355 100644
--- a/wifi/supplicant/1.0/vts/functional/supplicant_p2p_iface_hidl_test.cpp
+++ b/wifi/supplicant/1.0/vts/functional/supplicant_p2p_iface_hidl_test.cpp
@@ -282,8 +282,17 @@
         mac_addr_, ISupplicantP2pIface::WpsProvisionMethod::PBC,
         kTestConnectPin, false, false, kTestConnectGoIntent,
         [](const SupplicantStatus& status, const hidl_string& /* pin */) {
-            // After enabling auto-join, it will succeed always.
-            EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
+            /*
+             * Before R, auto-join is not enabled and it is not going to work
+             * with fake values. After enabling auto-join, it will succeed
+             * always.
+             */
+            LOG(INFO) << "ISupplicantP2pIface::connect() ret: "
+                      << toString(status);
+            if (SupplicantStatusCode::FAILURE_UNKNOWN != status.code &&
+                SupplicantStatusCode::SUCCESS != status.code) {
+                FAIL();
+            }
         });
 }
 
@@ -295,12 +304,26 @@
         mac_addr_, ISupplicantP2pIface::WpsProvisionMethod::PBC,
         kTestConnectPin, false, false, kTestConnectGoIntent,
         [](const SupplicantStatus& status, const hidl_string& /* pin */) {
-            // After enabling auto-join, it will succeed always.
-            EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
+            /*
+             * Before R, auto-join is not enabled and it is not going to work
+             * with fake values. After enabling auto-join, it will succeed
+             * always.
+             */
+            LOG(INFO) << "ISupplicantP2pIface::connect() ret: "
+                      << toString(status);
+            if (SupplicantStatusCode::FAILURE_UNKNOWN != status.code &&
+                SupplicantStatusCode::SUCCESS != status.code) {
+                FAIL();
+            }
         });
 
     p2p_iface_->cancelConnect([](const SupplicantStatus& status) {
-        EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
+        LOG(INFO) << "ISupplicantP2pIface::cancelConnect() ret: "
+                  << toString(status);
+        if (SupplicantStatusCode::FAILURE_UNKNOWN != status.code &&
+            SupplicantStatusCode::SUCCESS != status.code) {
+            FAIL();
+        }
     });
 }
 
diff --git a/wifi/supplicant/1.1/vts/functional/supplicant_hidl_test.cpp b/wifi/supplicant/1.1/vts/functional/supplicant_hidl_test.cpp
index 3c4d06b..8d7ea54 100644
--- a/wifi/supplicant/1.1/vts/functional/supplicant_hidl_test.cpp
+++ b/wifi/supplicant/1.1/vts/functional/supplicant_hidl_test.cpp
@@ -33,6 +33,7 @@
 using ::android::hardware::wifi::supplicant::V1_0::SupplicantStatusCode;
 using ::android::hardware::wifi::supplicant::V1_0::IfaceType;
 using ::android::hardware::wifi::supplicant::V1_1::ISupplicant;
+using ::android::hardware::wifi::V1_0::IWifi;
 using ::android::sp;
 
 class SupplicantHidlTest : public SupplicantHidlTestBaseV1_1 {
@@ -139,21 +140,12 @@
  */
 TEST_P(SupplicantHidlTest, Terminate) { supplicant_->terminate(); }
 
-static std::vector<std::string> get_wifi_instances() {
-    std::vector<std::string> instances =
-        android::hardware::getAllHalInstanceNames(
-            android::hardware::wifi::V1_0::IWifi::descriptor);
-    // Also test when wifi instance is not set.
-    instances.push_back("");
-
-    return instances;
-}
-
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SupplicantHidlTest);
 INSTANTIATE_TEST_CASE_P(
     PerInstance, SupplicantHidlTest,
     testing::Combine(
-        testing::ValuesIn(get_wifi_instances()),
+        testing::ValuesIn(
+            android::hardware::getAllHalInstanceNames(IWifi::descriptor)),
         testing::ValuesIn(android::hardware::getAllHalInstanceNames(
             android::hardware::wifi::supplicant::V1_1::ISupplicant::
                 descriptor))),