Merge "Add VTS for measurement type UTRAN ECNO"
diff --git a/audio/aidl/Android.bp b/audio/aidl/Android.bp
index c3647b0..7d474b2 100644
--- a/audio/aidl/Android.bp
+++ b/audio/aidl/Android.bp
@@ -132,6 +132,7 @@
         "android.hardware.common-V2",
         "android.hardware.common.fmq-V1",
         "android.hardware.audio.common-V1",
+        "android.hardware.audio.effect-V1",
         "android.media.audio.common.types-V2",
     ],
     backend: {
@@ -169,6 +170,53 @@
     ],
 }
 
+// Used for the standalone sounddose HAL
+aidl_interface {
+    name: "android.hardware.audio.core.sounddose",
+    defaults: [
+        "android.hardware.audio_defaults",
+    ],
+    srcs: [
+        "android/hardware/audio/core/ISoundDose.aidl",
+    ],
+    imports: [
+        "android.media.audio.common.types-V2",
+    ],
+    backend: {
+        // The C++ backend is disabled transitively due to use of FMQ by the core HAL.
+        cpp: {
+            enabled: false,
+        },
+        java: {
+            sdk_version: "module_current",
+        },
+    },
+    versions_with_info: [
+        // IMPORTANT: Update latest_android_hardware_audio_core_sounddose every time you
+        // add the latest frozen version to versions_with_info
+    ],
+}
+
+// Note: This should always be one version ahead of the last frozen version
+latest_android_hardware_audio_core_sounddose = "android.hardware.audio.core.sounddose-V1"
+
+// Modules that depend on android.hardware.audio.core.sounddose directly can include
+// the following cc_defaults to avoid explicitly managing dependency versions
+// across many scattered files.
+cc_defaults {
+    name: "latest_android_hardware_audio_core_sounddose_ndk_shared",
+    shared_libs: [
+        latest_android_hardware_audio_core_sounddose + "-ndk",
+    ],
+}
+
+cc_defaults {
+    name: "latest_android_hardware_audio_core_sounddose_ndk_static",
+    static_libs: [
+        latest_android_hardware_audio_core_sounddose + "-ndk",
+    ],
+}
+
 aidl_interface {
     name: "android.hardware.audio.effect",
     defaults: [
diff --git a/audio/aidl/TEST_MAPPING b/audio/aidl/TEST_MAPPING
index b4607f9..dfd82c3 100644
--- a/audio/aidl/TEST_MAPPING
+++ b/audio/aidl/TEST_MAPPING
@@ -10,6 +10,9 @@
       "name": "VtsHalAudioEffectTargetTest"
     },
     {
+      "name": "VtsHalDownmixTargetTest"
+    },
+    {
       "name": "VtsHalEqualizerTargetTest"
     },
     {
diff --git a/audio/aidl/aidl_api/android.hardware.audio.core.sounddose/current/android/hardware/audio/core/ISoundDose.aidl b/audio/aidl/aidl_api/android.hardware.audio.core.sounddose/current/android/hardware/audio/core/ISoundDose.aidl
new file mode 100644
index 0000000..bc010ca
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.core.sounddose/current/android/hardware/audio/core/ISoundDose.aidl
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file 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.audio.core;
+@VintfStability
+interface ISoundDose {
+  void setOutputRs2(float rs2ValueDbA);
+  float getOutputRs2();
+  void registerSoundDoseCallback(in android.hardware.audio.core.ISoundDose.IHalSoundDoseCallback callback);
+  const int DEFAULT_MAX_RS2 = 100;
+  const int MIN_RS2 = 80;
+  @VintfStability
+  interface IHalSoundDoseCallback {
+    oneway void onMomentaryExposureWarning(float currentDbA, in android.media.audio.common.AudioDevice audioDevice);
+    oneway void onNewMelValues(in android.hardware.audio.core.ISoundDose.IHalSoundDoseCallback.MelRecord melRecord, in android.media.audio.common.AudioDevice audioDevice);
+    @VintfStability
+    parcelable MelRecord {
+      float[] melValues;
+      long timestamp;
+    }
+  }
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IModule.aidl b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IModule.aidl
index ebfa94b..dd2279d 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IModule.aidl
+++ b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IModule.aidl
@@ -64,6 +64,8 @@
   int generateHwAvSyncId();
   android.hardware.audio.core.VendorParameter[] getVendorParameters(in @utf8InCpp String[] ids);
   void setVendorParameters(in android.hardware.audio.core.VendorParameter[] parameters, boolean async);
+  void addDeviceEffect(int portConfigId, in android.hardware.audio.effect.IEffect effect);
+  void removeDeviceEffect(int portConfigId, in android.hardware.audio.effect.IEffect effect);
   @VintfStability
   parcelable OpenInputStreamArguments {
     int portConfigId;
diff --git a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IStreamCommon.aidl b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IStreamCommon.aidl
index 8471c79..f0bf100 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IStreamCommon.aidl
+++ b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IStreamCommon.aidl
@@ -38,4 +38,6 @@
   void updateHwAvSyncId(int hwAvSyncId);
   android.hardware.audio.core.VendorParameter[] getVendorParameters(in @utf8InCpp String[] ids);
   void setVendorParameters(in android.hardware.audio.core.VendorParameter[] parameters, boolean async);
+  void addEffect(in android.hardware.audio.effect.IEffect effect);
+  void removeEffect(in android.hardware.audio.effect.IEffect effect);
 }
diff --git a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IStreamIn.aidl b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IStreamIn.aidl
index 98acf5f..68f1ff3 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IStreamIn.aidl
+++ b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IStreamIn.aidl
@@ -41,9 +41,13 @@
   float getMicrophoneFieldDimension();
   void setMicrophoneFieldDimension(float zoom);
   void updateMetadata(in android.hardware.audio.common.SinkMetadata sinkMetadata);
+  float[] getHwGain();
+  void setHwGain(in float[] channelGains);
   const int MIC_FIELD_DIMENSION_WIDE_ANGLE = -1;
   const int MIC_FIELD_DIMENSION_NO_ZOOM = 0;
   const int MIC_FIELD_DIMENSION_MAX_ZOOM = 1;
+  const int HW_GAIN_MIN = 0;
+  const int HW_GAIN_MAX = 1;
   @Backing(type="int") @VintfStability
   enum MicrophoneDirection {
     UNSPECIFIED = 0,
diff --git a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IStreamOut.aidl b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IStreamOut.aidl
index 5ea2a12..092b801 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IStreamOut.aidl
+++ b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IStreamOut.aidl
@@ -36,4 +36,8 @@
 interface IStreamOut {
   android.hardware.audio.core.IStreamCommon getStreamCommon();
   void updateMetadata(in android.hardware.audio.common.SourceMetadata sourceMetadata);
+  float[] getHwVolume();
+  void setHwVolume(in float[] channelVolumes);
+  const int HW_VOLUME_MIN = 0;
+  const int HW_VOLUME_MAX = 1;
 }
diff --git a/audio/aidl/android/hardware/audio/core/IModule.aidl b/audio/aidl/android/hardware/audio/core/IModule.aidl
index 7facc6c..b278ac4 100644
--- a/audio/aidl/android/hardware/audio/core/IModule.aidl
+++ b/audio/aidl/android/hardware/audio/core/IModule.aidl
@@ -30,6 +30,7 @@
 import android.hardware.audio.core.ModuleDebug;
 import android.hardware.audio.core.StreamDescriptor;
 import android.hardware.audio.core.VendorParameter;
+import android.hardware.audio.effect.IEffect;
 import android.media.audio.common.AudioOffloadInfo;
 import android.media.audio.common.AudioPort;
 import android.media.audio.common.AudioPortConfig;
@@ -515,7 +516,8 @@
      * @throws EX_ILLEGAL_ARGUMENT If the port config can not be found by the ID.
      * @throws EX_ILLEGAL_STATE In the following cases:
      *                          - If the port config has a stream opened on it;
-     *                          - If the port config is used by a patch.
+     *                          - If the port config is used by a patch;
+     *                          - If the port config has an audio effect on it.
      */
     void resetAudioPortConfig(int portConfigId);
 
@@ -728,4 +730,34 @@
      * @throws EX_UNSUPPORTED_OPERATION If the module does not support vendor parameters.
      */
     void setVendorParameters(in VendorParameter[] parameters, boolean async);
+
+    /**
+     * Apply an audio effect to a device port.
+     *
+     * The audio effect applies to all audio input or output on the specific
+     * configuration of the device audio port. The effect is inserted according
+     * to its insertion preference specified by the 'flags.insert' field of the
+     * EffectDescriptor.
+     *
+     * @param portConfigId The ID of the audio port config.
+     * @param effect The effect instance.
+     * @throws EX_ILLEGAL_ARGUMENT If the device port config can not be found by the ID,
+     *                             or the effect reference is invalid.
+     * @throws EX_UNSUPPORTED_OPERATION If the module does not support device port effects.
+     */
+    void addDeviceEffect(int portConfigId, in IEffect effect);
+
+    /**
+     * Stop applying an audio effect to a device port.
+     *
+     * Undo the action of the 'addDeviceEffect' method.
+     *
+     * @param portConfigId The ID of the audio port config.
+     * @param effect The effect instance.
+     * @throws EX_ILLEGAL_ARGUMENT If the device port config can not be found by the ID,
+     *                             or the effect reference is invalid, or the effect is
+     *                             not currently applied to the port config.
+     * @throws EX_UNSUPPORTED_OPERATION If the module does not support device port effects.
+     */
+    void removeDeviceEffect(int portConfigId, in IEffect effect);
 }
diff --git a/audio/aidl/android/hardware/audio/core/IStreamCommon.aidl b/audio/aidl/android/hardware/audio/core/IStreamCommon.aidl
index 84f7309..533ef67 100644
--- a/audio/aidl/android/hardware/audio/core/IStreamCommon.aidl
+++ b/audio/aidl/android/hardware/audio/core/IStreamCommon.aidl
@@ -17,6 +17,7 @@
 package android.hardware.audio.core;
 
 import android.hardware.audio.core.VendorParameter;
+import android.hardware.audio.effect.IEffect;
 
 /**
  * This interface contains operations that are common to input and output
@@ -86,4 +87,30 @@
      * @throws EX_UNSUPPORTED_OPERATION If the stream does not support vendor parameters.
      */
     void setVendorParameters(in VendorParameter[] parameters, boolean async);
+
+    /**
+     * Apply an audio effect to the stream.
+     *
+     * This method is intended for the cases when the effect has an offload
+     * implementation, since software effects can be applied at the client side.
+     *
+     * @param effect The effect instance.
+     * @throws EX_ILLEGAL_ARGUMENT If the effect reference is invalid.
+     * @throws EX_ILLEGAL_STATE If the stream is closed.
+     * @throws EX_UNSUPPORTED_OPERATION If the module does not support audio effects.
+     */
+    void addEffect(in IEffect effect);
+
+    /**
+     * Stop applying an audio effect to the stream.
+     *
+     * Undo the action of the 'addEffect' method.
+     *
+     * @param effect The effect instance.
+     * @throws EX_ILLEGAL_ARGUMENT If the effect reference is invalid, or the effect is
+     *                             not currently applied to the stream.
+     * @throws EX_ILLEGAL_STATE If the stream is closed.
+     * @throws EX_UNSUPPORTED_OPERATION If the module does not support audio effects.
+     */
+    void removeEffect(in IEffect effect);
 }
diff --git a/audio/aidl/android/hardware/audio/core/IStreamIn.aidl b/audio/aidl/android/hardware/audio/core/IStreamIn.aidl
index 92788a6..c2b3633 100644
--- a/audio/aidl/android/hardware/audio/core/IStreamIn.aidl
+++ b/audio/aidl/android/hardware/audio/core/IStreamIn.aidl
@@ -131,4 +131,38 @@
      * @throws EX_ILLEGAL_STATE If the stream is closed.
      */
     void updateMetadata(in SinkMetadata sinkMetadata);
+
+    const int HW_GAIN_MIN = 0;
+    const int HW_GAIN_MAX = 1;
+    /**
+     * Retrieve current gain applied in hardware.
+     *
+     * In case when the HAL module has a gain controller, this method returns
+     * the current value of its gain for each input channel.
+     *
+     * The valid range for gain is [0.0f, 1.0f], where 1.0f corresponds to unity
+     * gain, 0.0f corresponds to full mute (see HW_GAIN_* constants).
+     *
+     * @return Current gain values for each input channel.
+     * @throws EX_ILLEGAL_STATE If the stream is closed.
+     * @throws EX_UNSUPPORTED_OPERATION If hardware gain control is not supported.
+     */
+    float[] getHwGain();
+    /**
+     * Set gain applied in hardware.
+     *
+     * In case when the HAL module has a gain controller, this method sets the
+     * current value of its gain for each input channel.
+     *
+     * The valid range for gain is [0.0f, 1.0f], where 1.0f corresponds to unity
+     * gain, 0.0f corresponds to full mute (see HW_GAIN_* constants).
+     *
+     * @param gain Gain values for each input channel.
+     * @throws EX_ILLEGAL_ARGUMENT If the number of elements in the provided
+     *                             array does not match the channel count, or
+     *                             gain values are out of range.
+     * @throws EX_ILLEGAL_STATE If the stream is closed.
+     * @throws EX_UNSUPPORTED_OPERATION If hardware gain control is not supported.
+     */
+    void setHwGain(in float[] channelGains);
 }
diff --git a/audio/aidl/android/hardware/audio/core/IStreamOut.aidl b/audio/aidl/android/hardware/audio/core/IStreamOut.aidl
index f7fc77a..85da00d 100644
--- a/audio/aidl/android/hardware/audio/core/IStreamOut.aidl
+++ b/audio/aidl/android/hardware/audio/core/IStreamOut.aidl
@@ -44,4 +44,46 @@
      * @throws EX_ILLEGAL_STATE If the stream is closed.
      */
     void updateMetadata(in SourceMetadata sourceMetadata);
+
+    const int HW_VOLUME_MIN = 0;
+    const int HW_VOLUME_MAX = 1;
+    /**
+     * Retrieve current attenuation applied in hardware.
+     *
+     * Hardware attenuation can be used in cases when the client can not, or is
+     * not allowed to modify the audio stream, for example because the stream is
+     * encoded.
+     *
+     * The valid range for attenuation is [0.0f, 1.0f], where 1.0f corresponds
+     * to unity gain, 0.0f corresponds to full mute (see HW_VOLUME_*
+     * constants). The returned array specifies attenuation for each output
+     * channel of the stream.
+     *
+     * Support of hardware volume control is optional.
+     *
+     * @return Current attenuation values for each output channel.
+     * @throws EX_ILLEGAL_STATE If the stream is closed.
+     * @throws EX_UNSUPPORTED_OPERATION If hardware volume control is not supported.
+     */
+    float[] getHwVolume();
+    /**
+     * Set attenuation applied in hardware.
+     *
+     * Hardware attenuation can be used in cases when the client can not, or is
+     * not allowed to modify the audio stream, for example because the stream is
+     * encoded.
+     *
+     * The valid range for attenuation is [0.0f, 1.0f], where 1.0f corresponds
+     * to unity gain, 0.0f corresponds to full mute (see HW_VOLUME_* constants).
+     *
+     * Support of hardware volume control is optional.
+     *
+     * @param channelVolumes Attenuation values for each output channel.
+     * @throws EX_ILLEGAL_ARGUMENT If the number of elements in the provided
+     *                             array does not match the channel count, or
+     *                             attenuation values are out of range.
+     * @throws EX_ILLEGAL_STATE If the stream is closed.
+     * @throws EX_UNSUPPORTED_OPERATION If hardware volume control is not supported.
+     */
+    void setHwVolume(in float[] channelVolumes);
 }
diff --git a/audio/aidl/default/Android.bp b/audio/aidl/default/Android.bp
index b9b8cd8..a938551 100644
--- a/audio/aidl/default/Android.bp
+++ b/audio/aidl/default/Android.bp
@@ -29,6 +29,29 @@
     ],
 }
 
+cc_library {
+    name: "libaudioservicesounddoseimpl",
+    vendor: true,
+    defaults: [
+        "latest_android_media_audio_common_types_ndk_shared",
+        "latest_android_hardware_audio_core_sounddose_ndk_shared",
+        "latest_android_hardware_audio_sounddose_ndk_shared",
+    ],
+    export_include_dirs: ["include"],
+    srcs: [
+        "SoundDose.cpp",
+    ],
+    shared_libs: [
+        "libbase",
+        "libbinder_ndk",
+        "libcutils",
+        "libutils",
+    ],
+    visibility: [
+        "//hardware/interfaces/audio/aidl/sounddose/default",
+    ],
+}
+
 cc_library_static {
     name: "libaudioserviceexampleimpl",
     defaults: [
@@ -128,11 +151,12 @@
     shared_libs: [
         "libbassboostsw",
         "libbundleaidl",
+        "libdownmixaidl",
         "libdynamicsprocessingsw",
         "libenvreverbsw",
         "libequalizersw",
         "libhapticgeneratorsw",
-        "libloudnessenhancersw",
+        "libloudnessenhanceraidl",
         "libpresetreverbsw",
         "libtinyxml2",
         "libvirtualizersw",
diff --git a/audio/aidl/default/Module.cpp b/audio/aidl/default/Module.cpp
index d52e328..4a424bd 100644
--- a/audio/aidl/default/Module.cpp
+++ b/audio/aidl/default/Module.cpp
@@ -969,4 +969,28 @@
     return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
 }
 
+ndk::ScopedAStatus Module::addDeviceEffect(
+        int32_t in_portConfigId,
+        const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>& in_effect) {
+    if (in_effect == nullptr) {
+        LOG(DEBUG) << __func__ << ": port id " << in_portConfigId << ", null effect";
+    } else {
+        LOG(DEBUG) << __func__ << ": port id " << in_portConfigId << ", effect Binder "
+                   << in_effect->asBinder().get();
+    }
+    return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+ndk::ScopedAStatus Module::removeDeviceEffect(
+        int32_t in_portConfigId,
+        const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>& in_effect) {
+    if (in_effect == nullptr) {
+        LOG(DEBUG) << __func__ << ": port id " << in_portConfigId << ", null effect";
+    } else {
+        LOG(DEBUG) << __func__ << ": port id " << in_portConfigId << ", effect Binder "
+                   << in_effect->asBinder().get();
+    }
+    return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
 }  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/Stream.cpp b/audio/aidl/default/Stream.cpp
index 424c3e4..bb123a2 100644
--- a/audio/aidl/default/Stream.cpp
+++ b/audio/aidl/default/Stream.cpp
@@ -541,6 +541,28 @@
 }
 
 template <class Metadata, class StreamWorker>
+ndk::ScopedAStatus StreamCommonImpl<Metadata, StreamWorker>::addEffect(
+        const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>& in_effect) {
+    if (in_effect == nullptr) {
+        LOG(DEBUG) << __func__ << ": null effect";
+    } else {
+        LOG(DEBUG) << __func__ << ": effect Binder" << in_effect->asBinder().get();
+    }
+    return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+template <class Metadata, class StreamWorker>
+ndk::ScopedAStatus StreamCommonImpl<Metadata, StreamWorker>::removeEffect(
+        const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>& in_effect) {
+    if (in_effect == nullptr) {
+        LOG(DEBUG) << __func__ << ": null effect";
+    } else {
+        LOG(DEBUG) << __func__ << ": effect Binder" << in_effect->asBinder().get();
+    }
+    return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+template <class Metadata, class StreamWorker>
 ndk::ScopedAStatus StreamCommonImpl<Metadata, StreamWorker>::close() {
     LOG(DEBUG) << __func__;
     if (!isClosed()) {
@@ -658,6 +680,17 @@
     return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
 }
 
+ndk::ScopedAStatus StreamIn::getHwGain(std::vector<float>* _aidl_return) {
+    LOG(DEBUG) << __func__;
+    (void)_aidl_return;
+    return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+ndk::ScopedAStatus StreamIn::setHwGain(const std::vector<float>& in_channelGains) {
+    LOG(DEBUG) << __func__ << ": gains " << ::android::internal::ToString(in_channelGains);
+    return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
 // static
 ndk::ScopedAStatus StreamOut::createInstance(const SourceMetadata& sourceMetadata,
                                              StreamContext context,
@@ -680,4 +713,15 @@
     LOG(DEBUG) << __func__;
 }
 
+ndk::ScopedAStatus StreamOut::getHwVolume(std::vector<float>* _aidl_return) {
+    LOG(DEBUG) << __func__;
+    (void)_aidl_return;
+    return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+ndk::ScopedAStatus StreamOut::setHwVolume(const std::vector<float>& in_channelVolumes) {
+    LOG(DEBUG) << __func__ << ": gains " << ::android::internal::ToString(in_channelVolumes);
+    return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
 }  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/audio_effects_config.xml b/audio/aidl/default/audio_effects_config.xml
index d22c349..9491bc3 100644
--- a/audio/aidl/default/audio_effects_config.xml
+++ b/audio/aidl/default/audio_effects_config.xml
@@ -30,10 +30,11 @@
     <libraries>
         <library name="bassboostsw" path="libbassboostsw.so"/>
         <library name="bundle" path="libbundleaidl.so"/>
+        <library name="downmix" path="libdownmixaidl.so"/>
         <library name="dynamics_processingsw" path="libdynamicsprocessingsw.so"/>
         <library name="equalizersw" path="libequalizersw.so"/>
         <library name="haptic_generatorsw" path="libhapticgeneratorsw.so"/>
-        <library name="loudness_enhancersw" path="libloudnessenhancersw.so"/>
+        <library name="loudness_enhancer" path="libloudnessenhanceraidl.so"/>
         <library name="env_reverbsw" path="libenvreverbsw.so"/>
         <library name="preset_reverbsw" path="libpresetreverbsw.so"/>
         <library name="virtualizersw" path="libvirtualizersw.so"/>
@@ -65,9 +66,10 @@
             <libsw library="bassboostsw" uuid="fa8181f2-588b-11ed-9b6a-0242ac120002"/>
             <libsw library="bundle" uuid="8631f300-72e2-11df-b57e-0002a5d5c51b"/>
         </effectProxy>
+        <effect name="downmix" library="downmix" uuid="93f04452-e4fe-41cc-91f9-e475b6d1d69f"/>
         <effect name="dynamics_processing" library="dynamics_processingsw" uuid="fa818d78-588b-11ed-9b6a-0242ac120002"/>
         <effect name="haptic_generator" library="haptic_generatorsw" uuid="fa819110-588b-11ed-9b6a-0242ac120002"/>
-        <effect name="loudness_enhancer" library="loudness_enhancersw" uuid="fa819610-588b-11ed-9b6a-0242ac120002"/>
+        <effect name="loudness_enhancer" library="loudness_enhancer" uuid="fa415329-2034-4bea-b5dc-5b381c8d1e2c"/>
         <effect name="env_reverb" library="env_reverbsw" uuid="fa819886-588b-11ed-9b6a-0242ac120002"/>
         <effect name="preset_reverb" library="preset_reverbsw" uuid="fa8199c6-588b-11ed-9b6a-0242ac120002"/>
         <effect name="virtualizer" library="virtualizersw" uuid="fa819d86-588b-11ed-9b6a-0242ac120002"/>
diff --git a/audio/aidl/default/downmix/Android.bp b/audio/aidl/default/downmix/Android.bp
new file mode 100644
index 0000000..230b2d8
--- /dev/null
+++ b/audio/aidl/default/downmix/Android.bp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_interfaces_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_library_shared {
+    name: "libdownmixsw",
+    defaults: [
+        "aidlaudioeffectservice_defaults",
+        "latest_android_media_audio_common_types_ndk_shared",
+        "latest_android_hardware_audio_effect_ndk_shared",
+    ],
+    srcs: [
+        "DownmixSw.cpp",
+        ":effectCommonFile",
+    ],
+    visibility: [
+        "//hardware/interfaces/audio/aidl/default",
+    ],
+}
diff --git a/audio/aidl/default/downmix/DownmixSw.cpp b/audio/aidl/default/downmix/DownmixSw.cpp
new file mode 100644
index 0000000..7bb958d
--- /dev/null
+++ b/audio/aidl/default/downmix/DownmixSw.cpp
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <cstddef>
+#define LOG_TAG "AHAL_DownmixSw"
+#include <Utils.h>
+#include <algorithm>
+#include <unordered_set>
+
+#include <android-base/logging.h>
+#include <fmq/AidlMessageQueue.h>
+
+#include "DownmixSw.h"
+
+using aidl::android::hardware::audio::effect::Descriptor;
+using aidl::android::hardware::audio::effect::DownmixSw;
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::kDownmixSwImplUUID;
+using aidl::android::hardware::audio::effect::State;
+using aidl::android::media::audio::common::AudioUuid;
+
+extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
+                                           std::shared_ptr<IEffect>* instanceSpp) {
+    if (!in_impl_uuid || *in_impl_uuid != kDownmixSwImplUUID) {
+        LOG(ERROR) << __func__ << "uuid not supported";
+        return EX_ILLEGAL_ARGUMENT;
+    }
+    if (instanceSpp) {
+        *instanceSpp = ndk::SharedRefBase::make<DownmixSw>();
+        LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
+        return EX_NONE;
+    } else {
+        LOG(ERROR) << __func__ << " invalid input parameter!";
+        return EX_ILLEGAL_ARGUMENT;
+    }
+}
+
+extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
+    if (!in_impl_uuid || *in_impl_uuid != kDownmixSwImplUUID) {
+        LOG(ERROR) << __func__ << "uuid not supported";
+        return EX_ILLEGAL_ARGUMENT;
+    }
+    *_aidl_return = DownmixSw::kDescriptor;
+    return EX_NONE;
+}
+
+namespace aidl::android::hardware::audio::effect {
+
+const std::string DownmixSw::kEffectName = "DownmixSw";
+const Downmix::Capability DownmixSw::kCapability;
+const Descriptor DownmixSw::kDescriptor = {
+        .common = {.id = {.type = kDownmixTypeUUID,
+                          .uuid = kDownmixSwImplUUID,
+                          .proxy = std::nullopt},
+                   .flags = {.type = Flags::Type::INSERT,
+                             .insert = Flags::Insert::FIRST,
+                             .volume = Flags::Volume::CTRL},
+                   .name = kEffectName,
+                   .implementor = "The Android Open Source Project"},
+        .capability = Capability::make<Capability::downmix>(kCapability)};
+
+ndk::ScopedAStatus DownmixSw::getDescriptor(Descriptor* _aidl_return) {
+    LOG(DEBUG) << __func__ << kDescriptor.toString();
+    *_aidl_return = kDescriptor;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus DownmixSw::setParameterSpecific(const Parameter::Specific& specific) {
+    RETURN_IF(Parameter::Specific::downmix != specific.getTag(), EX_ILLEGAL_ARGUMENT,
+              "EffectNotSupported");
+    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+    auto& dmParam = specific.get<Parameter::Specific::downmix>();
+    auto tag = dmParam.getTag();
+
+    switch (tag) {
+        case Downmix::type: {
+            RETURN_IF(mContext->setDmType(dmParam.get<Downmix::type>()) != RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setTypeFailed");
+            return ndk::ScopedAStatus::ok();
+        }
+        default: {
+            LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                    "DownmixTagNotSupported");
+        }
+    }
+}
+
+ndk::ScopedAStatus DownmixSw::getParameterSpecific(const Parameter::Id& id,
+                                                   Parameter::Specific* specific) {
+    auto tag = id.getTag();
+    RETURN_IF(Parameter::Id::downmixTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
+    auto dmId = id.get<Parameter::Id::downmixTag>();
+    auto dmIdTag = dmId.getTag();
+    switch (dmIdTag) {
+        case Downmix::Id::commonTag:
+            return getParameterDownmix(dmId.get<Downmix::Id::commonTag>(), specific);
+        default:
+            LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                    "DownmixTagNotSupported");
+    }
+}
+
+ndk::ScopedAStatus DownmixSw::getParameterDownmix(const Downmix::Tag& tag,
+                                                  Parameter::Specific* specific) {
+    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+    Downmix dmParam;
+    switch (tag) {
+        case Downmix::type: {
+            dmParam.set<Downmix::type>(mContext->getDmType());
+            break;
+        }
+        default: {
+            LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                    "DownmixTagNotSupported");
+        }
+    }
+
+    specific->set<Parameter::Specific::downmix>(dmParam);
+    return ndk::ScopedAStatus::ok();
+}
+
+std::shared_ptr<EffectContext> DownmixSw::createContext(const Parameter::Common& common) {
+    if (mContext) {
+        LOG(DEBUG) << __func__ << " context already exist";
+    } else {
+        mContext = std::make_shared<DownmixSwContext>(1 /* statusFmqDepth */, common);
+    }
+
+    return mContext;
+}
+
+std::shared_ptr<EffectContext> DownmixSw::getContext() {
+    return mContext;
+}
+
+RetCode DownmixSw::releaseContext() {
+    if (mContext) {
+        mContext.reset();
+    }
+    return RetCode::SUCCESS;
+}
+
+// Processing method running in EffectWorker thread.
+IEffect::Status DownmixSw::effectProcessImpl(float* in, float* out, int samples) {
+    // TODO: get data buffer and process.
+    LOG(DEBUG) << __func__ << " in " << in << " out " << out << " samples " << samples;
+    for (int i = 0; i < samples; i++) {
+        *out++ = *in++;
+    }
+    return {STATUS_OK, samples, samples};
+}
+
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/downmix/DownmixSw.h b/audio/aidl/default/downmix/DownmixSw.h
new file mode 100644
index 0000000..51546c1
--- /dev/null
+++ b/audio/aidl/default/downmix/DownmixSw.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/audio/effect/BnEffect.h>
+#include <fmq/AidlMessageQueue.h>
+#include <cstdlib>
+#include <memory>
+
+#include "effect-impl/EffectImpl.h"
+#include "effect-impl/EffectUUID.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+class DownmixSwContext final : public EffectContext {
+  public:
+    DownmixSwContext(int statusDepth, const Parameter::Common& common)
+        : EffectContext(statusDepth, common) {
+        LOG(DEBUG) << __func__;
+    }
+
+    RetCode setDmType(Downmix::Type type) {
+        // TODO : Add implementation to apply new type
+        mType = type;
+        return RetCode::SUCCESS;
+    }
+    Downmix::Type getDmType() const { return mType; }
+
+  private:
+    Downmix::Type mType = Downmix::Type::STRIP;
+};
+
+class DownmixSw final : public EffectImpl {
+  public:
+    static const std::string kEffectName;
+    static const Downmix::Capability kCapability;
+    static const Descriptor kDescriptor;
+    DownmixSw() { LOG(DEBUG) << __func__; }
+    ~DownmixSw() {
+        cleanUp();
+        LOG(DEBUG) << __func__;
+    }
+
+    ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
+    ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override;
+    ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
+                                            Parameter::Specific* specific) override;
+
+    std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
+    std::shared_ptr<EffectContext> getContext() override;
+    RetCode releaseContext() override;
+
+    std::string getEffectName() override { return kEffectName; };
+    IEffect::Status effectProcessImpl(float* in, float* out, int sample) override;
+
+  private:
+    std::shared_ptr<DownmixSwContext> mContext;
+
+    ndk::ScopedAStatus getParameterDownmix(const Downmix::Tag& tag, Parameter::Specific* specific);
+};
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/include/core-impl/Module.h b/audio/aidl/default/include/core-impl/Module.h
index 6baaa76..aa05d2a 100644
--- a/audio/aidl/default/include/core-impl/Module.h
+++ b/audio/aidl/default/include/core-impl/Module.h
@@ -92,6 +92,14 @@
                                            std::vector<VendorParameter>* _aidl_return) override;
     ndk::ScopedAStatus setVendorParameters(const std::vector<VendorParameter>& in_parameters,
                                            bool in_async) override;
+    ndk::ScopedAStatus addDeviceEffect(
+            int32_t in_portConfigId,
+            const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>& in_effect)
+            override;
+    ndk::ScopedAStatus removeDeviceEffect(
+            int32_t in_portConfigId,
+            const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>& in_effect)
+            override;
 
     void cleanUpPatch(int32_t patchId);
     ndk::ScopedAStatus createStreamContext(
diff --git a/audio/aidl/default/include/core-impl/Stream.h b/audio/aidl/default/include/core-impl/Stream.h
index 5746f9d..a5d240f 100644
--- a/audio/aidl/default/include/core-impl/Stream.h
+++ b/audio/aidl/default/include/core-impl/Stream.h
@@ -212,6 +212,12 @@
                                                    std::vector<VendorParameter>* _aidl_return) = 0;
     virtual ndk::ScopedAStatus setVendorParameters(
             const std::vector<VendorParameter>& in_parameters, bool in_async) = 0;
+    virtual ndk::ScopedAStatus addEffect(
+            const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>&
+                    in_effect) = 0;
+    virtual ndk::ScopedAStatus removeEffect(
+            const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>&
+                    in_effect) = 0;
 };
 
 class StreamCommon : public BnStreamCommon {
@@ -242,6 +248,20 @@
         return delegate != nullptr ? delegate->setVendorParameters(in_parameters, in_async)
                                    : ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
     }
+    ndk::ScopedAStatus addEffect(
+            const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>& in_effect)
+            override {
+        auto delegate = mDelegate.lock();
+        return delegate != nullptr ? delegate->addEffect(in_effect)
+                                   : ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+    }
+    ndk::ScopedAStatus removeEffect(
+            const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>& in_effect)
+            override {
+        auto delegate = mDelegate.lock();
+        return delegate != nullptr ? delegate->removeEffect(in_effect)
+                                   : ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+    }
     // It is possible that on the client side the proxy for IStreamCommon will outlive
     // the IStream* instance, and the server side IStream* instance will get destroyed
     // while this IStreamCommon instance is still alive.
@@ -257,6 +277,12 @@
                                            std::vector<VendorParameter>* _aidl_return) override;
     ndk::ScopedAStatus setVendorParameters(const std::vector<VendorParameter>& in_parameters,
                                            bool in_async) override;
+    ndk::ScopedAStatus addEffect(
+            const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>& in_effect)
+            override;
+    ndk::ScopedAStatus removeEffect(
+            const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>& in_effect)
+            override;
 
     ndk::ScopedAStatus getStreamCommon(std::shared_ptr<IStreamCommon>* _aidl_return);
     ndk::ScopedAStatus init() {
@@ -305,6 +331,8 @@
         return StreamCommonImpl<::aidl::android::hardware::audio::common::SinkMetadata,
                                 StreamInWorker>::updateMetadata(in_sinkMetadata);
     }
+    ndk::ScopedAStatus getHwGain(std::vector<float>* _aidl_return) override;
+    ndk::ScopedAStatus setHwGain(const std::vector<float>& in_channelGains) override;
 
   public:
     static ndk::ScopedAStatus createInstance(
@@ -337,6 +365,8 @@
         return StreamCommonImpl<::aidl::android::hardware::audio::common::SourceMetadata,
                                 StreamOutWorker>::updateMetadata(in_sourceMetadata);
     }
+    ndk::ScopedAStatus getHwVolume(std::vector<float>* _aidl_return) override;
+    ndk::ScopedAStatus setHwVolume(const std::vector<float>& in_channelVolumes) override;
 
   public:
     static ndk::ScopedAStatus createInstance(
diff --git a/audio/aidl/default/include/effect-impl/EffectUUID.h b/audio/aidl/default/include/effect-impl/EffectUUID.h
index d3c7666..c9bb1f4 100644
--- a/audio/aidl/default/include/effect-impl/EffectUUID.h
+++ b/audio/aidl/default/include/effect-impl/EffectUUID.h
@@ -69,6 +69,12 @@
                                              0x11ed,
                                              0x9b6a,
                                              {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
+// 93f04452-e4fe-41cc-91f9-e475b6d1d69f
+static const AudioUuid kDownmixImplUUID = {static_cast<int32_t>(0x93f04452),
+                                           0xe4fe,
+                                           0x41cc,
+                                           0x91f9,
+                                           {0xe4, 0x75, 0xb6, 0xd1, 0xd6, 0x9f}};
 // 0bed4300-ddd6-11db-8f34-0002a5d5c51b.
 static const AudioUuid kEqualizerTypeUUID = {static_cast<int32_t>(0x0bed4300),
                                              0xddd6,
@@ -129,6 +135,12 @@
                                                       0x11ed,
                                                       0x9b6a,
                                                       {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
+// fa415329-2034-4bea-b5dc-5b381c8d1e2c
+static const AudioUuid kLoudnessEnhancerImplUUID = {static_cast<int32_t>(0xfa415329),
+                                                    0x2034,
+                                                    0x4bea,
+                                                    0xb5dc,
+                                                    {0x5b, 0x38, 0x1c, 0x8d, 0x1e, 0x2c}};
 // c2e5d5f0-94bd-4763-9cac-4e234d06839e
 static const AudioUuid kEnvReverbTypeUUID = {static_cast<int32_t>(0xc2e5d5f0),
                                              0x94bd,
diff --git a/audio/aidl/sounddose/Android.bp b/audio/aidl/sounddose/Android.bp
new file mode 100644
index 0000000..85d6e21
--- /dev/null
+++ b/audio/aidl/sounddose/Android.bp
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_interfaces_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+aidl_interface {
+    name: "android.hardware.audio.sounddose",
+    host_supported: true,
+    vendor_available: true,
+    stability: "vintf",
+    srcs: [
+        "android/hardware/audio/sounddose/ISoundDoseFactory.aidl",
+    ],
+    imports: [
+        latest_android_hardware_audio_core_sounddose,
+    ],
+    backend: {
+        // The C++ backend is disabled transitively due to use by core audio HAL.
+        cpp: {
+            enabled: false,
+        },
+        java: {
+            sdk_version: "module_current",
+        },
+    },
+    versions_with_info: [
+        // IMPORTANT: Update latest_android_hardware_audio_sounddose every time you
+        // add the latest frozen version to versions_with_info
+    ],
+}
+
+// Note: This should always be one version ahead of the last frozen version
+latest_android_hardware_audio_sounddose = "android.hardware.audio.sounddose-V1"
+
+// Modules that depend on android.hardware.audio.sounddose directly can include
+// the following cc_defaults to avoid explicitly managing dependency versions
+// across many scattered files.
+cc_defaults {
+    name: "latest_android_hardware_audio_sounddose_ndk_shared",
+    shared_libs: [
+        latest_android_hardware_audio_sounddose + "-ndk",
+    ],
+}
+
+cc_defaults {
+    name: "latest_android_hardware_audio_sounddose_ndk_static",
+    static_libs: [
+        latest_android_hardware_audio_sounddose + "-ndk",
+    ],
+}
diff --git a/audio/aidl/sounddose/aidl_api/android.hardware.audio.core.sounddose/current/android/hardware/audio/core/ISoundDose.aidl b/audio/aidl/sounddose/aidl_api/android.hardware.audio.core.sounddose/current/android/hardware/audio/core/ISoundDose.aidl
new file mode 100644
index 0000000..dff17e2
--- /dev/null
+++ b/audio/aidl/sounddose/aidl_api/android.hardware.audio.core.sounddose/current/android/hardware/audio/core/ISoundDose.aidl
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file 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.audio.core;
+@VintfStability
+interface ISoundDose {
+  void setOutputRs2(float rs2ValueDbA);
+  float getOutputRs2();
+  void registerSoundDoseCallback(in android.hardware.audio.core.ISoundDose.IHalSoundDoseCallback callback);
+  const int DEFAULT_MAX_RS2 = 100;
+  @VintfStability
+  interface IHalSoundDoseCallback {
+    oneway void onMomentaryExposureWarning(float currentDbA, in android.media.audio.common.AudioDevice audioDevice);
+    oneway void onNewMelValues(in android.hardware.audio.core.ISoundDose.IHalSoundDoseCallback.MelRecord melRecord, in android.media.audio.common.AudioDevice audioDevice);
+    @VintfStability
+    parcelable MelRecord {
+      float[] melValues;
+      long timestamp;
+    }
+  }
+}
diff --git a/audio/aidl/sounddose/aidl_api/android.hardware.audio.sounddose/current/android/hardware/audio/sounddose/ISoundDoseFactory.aidl b/audio/aidl/sounddose/aidl_api/android.hardware.audio.sounddose/current/android/hardware/audio/sounddose/ISoundDoseFactory.aidl
new file mode 100644
index 0000000..7dda011
--- /dev/null
+++ b/audio/aidl/sounddose/aidl_api/android.hardware.audio.sounddose/current/android/hardware/audio/sounddose/ISoundDoseFactory.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file 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.audio.sounddose;
+@VintfStability
+interface ISoundDoseFactory {
+  @nullable android.hardware.audio.core.ISoundDose getSoundDose(in @utf8InCpp String module);
+}
diff --git a/audio/aidl/sounddose/android/hardware/audio/sounddose/ISoundDoseFactory.aidl b/audio/aidl/sounddose/android/hardware/audio/sounddose/ISoundDoseFactory.aidl
new file mode 100644
index 0000000..3487237
--- /dev/null
+++ b/audio/aidl/sounddose/android/hardware/audio/sounddose/ISoundDoseFactory.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.audio.sounddose;
+
+import android.hardware.audio.core.ISoundDose;
+
+/**
+ * This interface is used to provide an easy way to implement the ISoundDose interface
+ * without switching the audio HAL to AIDL. The implementation is intended as a workaround
+ * for the certification with IEC62368-1 3rd edition and EN50332-3.
+ * Note that this interface will be deprecated in favor of the audio AIDL HAL.
+ */
+@VintfStability
+interface ISoundDoseFactory {
+    /**
+     * Retrieve the sound dose interface for a given audio HAL module name.
+     *
+     * If a device must comply to IEC62368-1 3rd edition audio safety requirements and is
+     * implementing audio offload decoding or other direct playback paths where volume control
+     * happens below the audio HAL, it must return an instance of the ISoundDose interface.
+     * The same instance must be returned during the lifetime of the HAL module.
+     * If the HAL module does not support sound dose, null must be returned, without throwing
+     * any errors.
+     *
+     * @param module for which we trigger sound dose updates.
+     * @return An instance of the ISoundDose interface implementation.
+     * @throws EX_ILLEGAL_STATE If there was an error creating an instance.
+     */
+    @nullable ISoundDose getSoundDose(in @utf8InCpp String module);
+}
diff --git a/audio/aidl/sounddose/default/Android.bp b/audio/aidl/sounddose/default/Android.bp
new file mode 100644
index 0000000..bd770fa
--- /dev/null
+++ b/audio/aidl/sounddose/default/Android.bp
@@ -0,0 +1,46 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_interfaces_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_defaults {
+    name: "aidlsounddoseservice_defaults",
+    vendor: true,
+    header_libs: [
+        "libsounddoseaidl_headers",
+    ],
+}
+
+cc_library {
+    name: "libsounddoseserviceexampleimpl",
+    defaults: [
+        "aidlsounddoseservice_defaults",
+        "latest_android_media_audio_common_types_ndk_shared",
+        "latest_android_hardware_audio_core_sounddose_ndk_shared",
+        "latest_android_hardware_audio_sounddose_ndk_shared",
+    ],
+    export_include_dirs: ["include"],
+    srcs: [
+        "SoundDoseFactory.cpp",
+    ],
+    shared_libs: [
+        "libaudioservicesounddoseimpl",
+        "libbase",
+        "libbinder_ndk",
+    ],
+
+    visibility: [
+        "//hardware/interfaces/audio/common/all-versions/default/service",
+    ],
+}
+
+cc_library_headers {
+    name: "libsounddoseaidl_headers",
+    export_include_dirs: ["include"],
+    vendor_available: true,
+    host_supported: true,
+}
diff --git a/audio/aidl/sounddose/default/SoundDoseFactory.cpp b/audio/aidl/sounddose/default/SoundDoseFactory.cpp
new file mode 100644
index 0000000..50796d0
--- /dev/null
+++ b/audio/aidl/sounddose/default/SoundDoseFactory.cpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "AHAL_SoundDoseFactory"
+
+#include "SoundDoseFactory.h"
+
+#include <android-base/logging.h>
+#include <core-impl/SoundDose.h>
+
+namespace aidl::android::hardware::audio::sounddose {
+
+using ::aidl::android::hardware::audio::core::SoundDose;
+
+ndk::ScopedAStatus SoundDoseFactory::getSoundDose(const std::string& in_module,
+                                                  std::shared_ptr<ISoundDose>* _aidl_return) {
+    auto soundDoseIt = mSoundDoseBinderMap.find(in_module);
+    if (soundDoseIt != mSoundDoseBinderMap.end()) {
+        *_aidl_return = ISoundDose::fromBinder(soundDoseIt->second);
+
+        LOG(DEBUG) << __func__
+                   << ": returning cached instance of ISoundDose: " << _aidl_return->get()
+                   << " for module " << in_module;
+        return ndk::ScopedAStatus::ok();
+    }
+
+    auto soundDose = ndk::SharedRefBase::make<SoundDose>();
+    mSoundDoseBinderMap[in_module] = soundDose->asBinder();
+    *_aidl_return = soundDose;
+
+    LOG(DEBUG) << __func__ << ": returning new instance of ISoundDose: " << _aidl_return->get()
+               << " for module " << in_module;
+    return ndk::ScopedAStatus::ok();
+}
+
+}  // namespace aidl::android::hardware::audio::sounddose
diff --git a/audio/aidl/sounddose/default/include/SoundDoseFactory.h b/audio/aidl/sounddose/default/include/SoundDoseFactory.h
new file mode 100644
index 0000000..4cf3277
--- /dev/null
+++ b/audio/aidl/sounddose/default/include/SoundDoseFactory.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/audio/core/ISoundDose.h>
+#include <aidl/android/hardware/audio/sounddose/BnSoundDoseFactory.h>
+#include <android/binder_interface_utils.h>
+
+#include <unordered_map>
+
+namespace aidl::android::hardware::audio::sounddose {
+
+using ::aidl::android::hardware::audio::core::ISoundDose;
+
+class SoundDoseFactory : public BnSoundDoseFactory {
+  public:
+    ndk::ScopedAStatus getSoundDose(const std::string& module,
+                                    std::shared_ptr<ISoundDose>* _aidl_return) override;
+
+  private:
+    std::unordered_map<std::string, ndk::SpAIBinder> mSoundDoseBinderMap;
+};
+
+}  // namespace aidl::android::hardware::audio::sounddose
diff --git a/audio/aidl/sounddose/vts/Android.bp b/audio/aidl/sounddose/vts/Android.bp
new file mode 100644
index 0000000..88be968
--- /dev/null
+++ b/audio/aidl/sounddose/vts/Android.bp
@@ -0,0 +1,36 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_interfaces_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_test {
+    name: "VtsHalSoundDoseFactoryTargetTest",
+    defaults: [
+        "latest_android_hardware_audio_core_sounddose_ndk_static",
+        "latest_android_hardware_audio_sounddose_ndk_static",
+        "latest_android_media_audio_common_types_ndk_static",
+        "use_libaidlvintf_gtest_helper_static",
+        "VtsHalTargetTestDefaults",
+    ],
+    shared_libs: [
+        "libbinder_ndk",
+        "libcutils",
+    ],
+    srcs: [
+        "VtsHalSoundDoseFactoryTargetTest.cpp",
+    ],
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+        "-Wthread-safety",
+    ],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
+}
diff --git a/audio/aidl/sounddose/vts/TEST_MAPPING b/audio/aidl/sounddose/vts/TEST_MAPPING
new file mode 100644
index 0000000..bebeed9
--- /dev/null
+++ b/audio/aidl/sounddose/vts/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit": [
+    {
+      "name": "VtsHalSoundDoseFactoryTargetTest"
+    }
+  ]
+}
diff --git a/audio/aidl/sounddose/vts/VtsHalSoundDoseFactoryTargetTest.cpp b/audio/aidl/sounddose/vts/VtsHalSoundDoseFactoryTargetTest.cpp
new file mode 100644
index 0000000..7448c1f
--- /dev/null
+++ b/audio/aidl/sounddose/vts/VtsHalSoundDoseFactoryTargetTest.cpp
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "VtsHalSoundDose.Factory"
+#include <android-base/logging.h>
+
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/audio/sounddose/ISoundDoseFactory.h>
+#include <android/binder_manager.h>
+
+#include <memory>
+
+namespace android::hardware::audio::common::testing {
+
+namespace detail {
+
+inline ::testing::AssertionResult assertIsOk(const char* expr, const ::ndk::ScopedAStatus& status) {
+    if (status.isOk()) {
+        return ::testing::AssertionSuccess();
+    }
+    return ::testing::AssertionFailure()
+           << "Expected the transaction \'" << expr << "\' to succeed\n"
+           << "  but it has failed with: " << status;
+}
+
+}  // namespace detail
+
+}  // namespace android::hardware::audio::common::testing
+
+// Test that the transaction status 'isOk'
+#define EXPECT_IS_OK(ret) \
+    EXPECT_PRED_FORMAT1(::android::hardware::audio::common::testing::detail::assertIsOk, ret)
+
+using namespace android;
+
+using aidl::android::hardware::audio::core::ISoundDose;
+using aidl::android::hardware::audio::sounddose::ISoundDoseFactory;
+
+class SoundDoseFactory : public testing::TestWithParam<std::string> {
+  public:
+    void SetUp() override { ASSERT_NO_FATAL_FAILURE(ConnectToService(GetParam())); }
+
+    void TearDown() override {}
+
+    void ConnectToService(const std::string& interfaceName) {
+        ndk::SpAIBinder binder =
+                ndk::SpAIBinder(AServiceManager_waitForService(interfaceName.c_str()));
+        if (binder == nullptr) {
+            LOG(ERROR) << "Failed to get service " << interfaceName;
+        } else {
+            LOG(DEBUG) << "Succeeded to get service " << interfaceName;
+        }
+        soundDoseFactory = ISoundDoseFactory::fromBinder(binder);
+        ASSERT_NE(soundDoseFactory, nullptr);
+    }
+
+    std::shared_ptr<ISoundDoseFactory> soundDoseFactory;
+};
+
+TEST_P(SoundDoseFactory, GetSoundDoseForSameModule) {
+    const std::string module = "primary";
+
+    std::shared_ptr<ISoundDose> soundDose1;
+    EXPECT_IS_OK(soundDoseFactory->getSoundDose(module, &soundDose1));
+
+    if (soundDose1 == nullptr) {
+        LOG(WARNING) << "Primary module does not support sound dose";
+        return;
+    }
+
+    std::shared_ptr<ISoundDose> soundDose2;
+    EXPECT_IS_OK(soundDoseFactory->getSoundDose(module, &soundDose2));
+    EXPECT_NE(nullptr, soundDose2);
+    EXPECT_EQ(soundDose1->asBinder(), soundDose2->asBinder())
+            << "getSoundDose must return the same interface for the same module";
+}
+
+INSTANTIATE_TEST_SUITE_P(
+        SoundDoseFactoryTest, SoundDoseFactory,
+        testing::ValuesIn(android::getAidlHalInstanceNames(ISoundDoseFactory::descriptor)),
+        android::PrintInstanceNameToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SoundDoseFactory);
diff --git a/audio/aidl/vts/Android.bp b/audio/aidl/vts/Android.bp
index 4414e26..aeff615 100644
--- a/audio/aidl/vts/Android.bp
+++ b/audio/aidl/vts/Android.bp
@@ -24,6 +24,7 @@
         "android.hardware.common-V2-ndk",
         "android.hardware.common.fmq-V1-ndk",
         "libaudioaidlcommon",
+        "libaidlcommonsupport",
     ],
     header_libs: ["libaudioaidl_headers"],
     cflags: [
@@ -73,6 +74,12 @@
 }
 
 cc_test {
+    name: "VtsHalDownmixTargetTest",
+    defaults: ["VtsHalAudioTargetTestDefaults"],
+    srcs: ["VtsHalDownmixTargetTest.cpp"],
+}
+
+cc_test {
     name: "VtsHalEqualizerTargetTest",
     defaults: ["VtsHalAudioTargetTestDefaults"],
     srcs: ["VtsHalEqualizerTargetTest.cpp"],
diff --git a/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp b/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
index d21b118..2508afd 100644
--- a/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
@@ -82,6 +82,7 @@
 using aidl::android::media::audio::common::AudioSource;
 using aidl::android::media::audio::common::AudioUsage;
 using aidl::android::media::audio::common::Void;
+using android::hardware::audio::common::getChannelCount;
 using android::hardware::audio::common::isBitPositionFlagSet;
 using android::hardware::audio::common::isTelephonyDeviceType;
 using android::hardware::audio::common::StreamLogic;
@@ -189,6 +190,29 @@
     AudioPortConfig mConfig;
 };
 
+template <typename T>
+void GenerateTestArrays(size_t validElementCount, T validMin, T validMax,
+                        std::vector<std::vector<T>>* validValues,
+                        std::vector<std::vector<T>>* invalidValues) {
+    validValues->emplace_back(validElementCount, validMin);
+    validValues->emplace_back(validElementCount, validMax);
+    validValues->emplace_back(validElementCount, (validMin + validMax) / 2.f);
+    if (validElementCount > 0) {
+        invalidValues->emplace_back(validElementCount - 1, validMin);
+    }
+    invalidValues->emplace_back(validElementCount + 1, validMin);
+    for (auto m : {-2, -1, 2}) {
+        const auto invalidMin = m * validMin;
+        if (invalidMin < validMin || invalidMin > validMax) {
+            invalidValues->emplace_back(validElementCount, invalidMin);
+        }
+        const auto invalidMax = m * validMax;
+        if (invalidMax < validMin || invalidMax > validMax) {
+            invalidValues->emplace_back(validElementCount, invalidMax);
+        }
+    }
+}
+
 template <typename PropType, class Instance, typename Getter, typename Setter>
 void TestAccessors(Instance* inst, Getter getter, Setter setter,
                    const std::vector<PropType>& validValues,
@@ -202,13 +226,14 @@
     ASSERT_TRUE(status.isOk()) << "Unexpected status from a getter: " << status;
     *isSupported = true;
     for (const auto v : validValues) {
-        EXPECT_IS_OK((inst->*setter)(v)) << "for valid value: " << v;
+        EXPECT_IS_OK((inst->*setter)(v)) << "for a valid value: " << ::testing::PrintToString(v);
         PropType currentValue{};
         EXPECT_IS_OK((inst->*getter)(&currentValue));
         EXPECT_EQ(v, currentValue);
     }
     for (const auto v : invalidValues) {
-        EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, (inst->*setter)(v)) << "for invalid value: " << v;
+        EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, (inst->*setter)(v))
+                << "for an invalid value: " << ::testing::PrintToString(v);
     }
     EXPECT_IS_OK((inst->*setter)(initialValue)) << "Failed to restore the initial value";
 }
@@ -1721,6 +1746,33 @@
     }
 }
 
+// See b/262930731. In the absence of offloaded effect implementations,
+// currently we can only pass a nullptr, and the HAL module must either reject
+// it as an invalid argument, or say that offloaded effects are not supported.
+TEST_P(AudioCoreModule, AddRemoveEffectInvalidArguments) {
+    ndk::ScopedAStatus addEffectStatus = module->addDeviceEffect(-1, nullptr);
+    ndk::ScopedAStatus removeEffectStatus = module->removeDeviceEffect(-1, nullptr);
+    const bool isSupported = addEffectStatus.getExceptionCode() != EX_UNSUPPORTED_OPERATION;
+    if (isSupported) {
+        EXPECT_EQ(EX_ILLEGAL_ARGUMENT, addEffectStatus.getExceptionCode());
+        EXPECT_EQ(EX_ILLEGAL_ARGUMENT, removeEffectStatus.getExceptionCode());
+    } else if (EX_UNSUPPORTED_OPERATION != removeEffectStatus.getExceptionCode()) {
+        GTEST_FAIL() << "addEffect and removeEffect must be either supported or not supported "
+                     << "together";
+    } else {
+        GTEST_SKIP() << "Offloaded effects not supported";
+    }
+    // Test rejection of a nullptr effect with a valid device port Id.
+    ASSERT_NO_FATAL_FAILURE(SetUpModuleConfig());
+    const auto configs = moduleConfig->getPortConfigsForAttachedDevicePorts();
+    for (const auto& config : configs) {
+        WithAudioPortConfig portConfig(config);
+        ASSERT_NO_FATAL_FAILURE(portConfig.SetUp(module.get()));
+        EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->addDeviceEffect(portConfig.getId(), nullptr));
+        EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->removeDeviceEffect(portConfig.getId(), nullptr));
+    }
+}
+
 class AudioCoreTelephony : public AudioCoreModuleBase, public testing::TestWithParam<std::string> {
   public:
     void SetUp() override {
@@ -1874,9 +1926,7 @@
         }
         WithStream<Stream> stream(portConfig.value());
         ASSERT_NO_FATAL_FAILURE(stream.SetUpPortConfig(module.get()));
-        // The buffer size of 1 frame should be impractically small, and thus
-        // less than any minimum buffer size suggested by any HAL.
-        for (long bufferSize : std::array<long, 4>{-1, 0, 1, std::numeric_limits<long>::max()}) {
+        for (long bufferSize : std::array<long, 3>{-1, 0, std::numeric_limits<long>::max()}) {
             EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, stream.SetUpNoChecks(module.get(), bufferSize))
                     << "for the buffer size " << bufferSize;
             EXPECT_EQ(nullptr, stream.get());
@@ -2019,6 +2069,79 @@
         }
     }
 
+    void HwGainHwVolume() {
+        const auto ports =
+                moduleConfig->getMixPorts(IOTraits<Stream>::is_input, false /*attachedOnly*/);
+        if (ports.empty()) {
+            GTEST_SKIP() << "No mix ports";
+        }
+        bool atLeastOneSupports = false;
+        for (const auto& port : ports) {
+            const auto portConfig = moduleConfig->getSingleConfigForMixPort(true, port);
+            if (!portConfig.has_value()) continue;
+            WithStream<Stream> stream(portConfig.value());
+            ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
+            std::vector<std::vector<float>> validValues, invalidValues;
+            bool isSupported = false;
+            if constexpr (IOTraits<Stream>::is_input) {
+                GenerateTestArrays<float>(getChannelCount(portConfig.value().channelMask.value()),
+                                          IStreamIn::HW_GAIN_MIN, IStreamIn::HW_GAIN_MAX,
+                                          &validValues, &invalidValues);
+                EXPECT_NO_FATAL_FAILURE(TestAccessors<std::vector<float>>(
+                        stream.get(), &IStreamIn::getHwGain, &IStreamIn::setHwGain, validValues,
+                        invalidValues, &isSupported));
+            } else {
+                GenerateTestArrays<float>(getChannelCount(portConfig.value().channelMask.value()),
+                                          IStreamOut::HW_VOLUME_MIN, IStreamOut::HW_VOLUME_MAX,
+                                          &validValues, &invalidValues);
+                EXPECT_NO_FATAL_FAILURE(TestAccessors<std::vector<float>>(
+                        stream.get(), &IStreamOut::getHwVolume, &IStreamOut::setHwVolume,
+                        validValues, invalidValues, &isSupported));
+            }
+            if (isSupported) atLeastOneSupports = true;
+        }
+        if (!atLeastOneSupports) {
+            GTEST_SKIP() << "Hardware gain / volume is not supported";
+        }
+    }
+
+    // See b/262930731. In the absence of offloaded effect implementations,
+    // currently we can only pass a nullptr, and the HAL module must either reject
+    // it as an invalid argument, or say that offloaded effects are not supported.
+    void AddRemoveEffectInvalidArguments() {
+        const auto ports =
+                moduleConfig->getMixPorts(IOTraits<Stream>::is_input, false /*attachedOnly*/);
+        if (ports.empty()) {
+            GTEST_SKIP() << "No mix ports";
+        }
+        bool atLeastOneSupports = false;
+        for (const auto& port : ports) {
+            const auto portConfig = moduleConfig->getSingleConfigForMixPort(true, port);
+            if (!portConfig.has_value()) continue;
+            WithStream<Stream> stream(portConfig.value());
+            ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
+            std::shared_ptr<IStreamCommon> streamCommon;
+            ASSERT_IS_OK(stream.get()->getStreamCommon(&streamCommon));
+            ASSERT_NE(nullptr, streamCommon);
+            ndk::ScopedAStatus addEffectStatus = streamCommon->addEffect(nullptr);
+            ndk::ScopedAStatus removeEffectStatus = streamCommon->removeEffect(nullptr);
+            const bool isSupported = addEffectStatus.getExceptionCode() != EX_UNSUPPORTED_OPERATION;
+            if (isSupported) {
+                EXPECT_EQ(EX_ILLEGAL_ARGUMENT, addEffectStatus.getExceptionCode());
+                EXPECT_EQ(EX_ILLEGAL_ARGUMENT, removeEffectStatus.getExceptionCode());
+                atLeastOneSupports = true;
+            } else if (EX_UNSUPPORTED_OPERATION != removeEffectStatus.getExceptionCode()) {
+                ADD_FAILURE()
+                        << "addEffect and removeEffect must be either supported or not supported "
+                        << "together";
+                atLeastOneSupports = true;
+            }
+        }
+        if (!atLeastOneSupports) {
+            GTEST_SKIP() << "Offloaded effects not supported";
+        }
+    }
+
     void OpenTwiceSamePortConfigImpl(const AudioPortConfig& portConfig) {
         WithStream<Stream> stream1(portConfig);
         ASSERT_NO_FATAL_FAILURE(stream1.SetUp(module.get(), kDefaultBufferSizeFrames));
@@ -2095,6 +2218,8 @@
 TEST_IN_AND_OUT_STREAM(UpdateHwAvSyncId);
 TEST_IN_AND_OUT_STREAM(GetVendorParameters);
 TEST_IN_AND_OUT_STREAM(SetVendorParameters);
+TEST_IN_AND_OUT_STREAM(HwGainHwVolume);
+TEST_IN_AND_OUT_STREAM(AddRemoveEffectInvalidArguments);
 
 namespace aidl::android::hardware::audio::core {
 std::ostream& operator<<(std::ostream& os, const IStreamIn::MicrophoneDirection& md) {
diff --git a/audio/aidl/vts/VtsHalDownmixTargetTest.cpp b/audio/aidl/vts/VtsHalDownmixTargetTest.cpp
new file mode 100644
index 0000000..8612660
--- /dev/null
+++ b/audio/aidl/vts/VtsHalDownmixTargetTest.cpp
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "VtsHalDownmixTargetTest"
+
+#include <Utils.h>
+#include <aidl/Vintf.h>
+#include "EffectHelper.h"
+
+using namespace android;
+
+using aidl::android::hardware::audio::effect::Capability;
+using aidl::android::hardware::audio::effect::Descriptor;
+using aidl::android::hardware::audio::effect::Downmix;
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::IFactory;
+using aidl::android::hardware::audio::effect::kDownmixTypeUUID;
+using aidl::android::hardware::audio::effect::kEffectNullUuid;
+using aidl::android::hardware::audio::effect::Parameter;
+
+/**
+ * Here we focus on specific parameter checking, general IEffect interfaces testing performed in
+ * VtsAudioEffectTargetTest.
+ */
+enum ParamName { PARAM_INSTANCE_NAME, PARAM_TYPE };
+using DownmixParamTestParam =
+        std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, Downmix::Type>;
+
+// Testing for enum values
+const std::vector<Downmix::Type> kTypeValues = {Downmix::Type::STRIP, Downmix::Type::FOLD};
+
+class DownmixParamTest : public ::testing::TestWithParam<DownmixParamTestParam>,
+                         public EffectHelper {
+  public:
+    DownmixParamTest() : mParamType(std::get<PARAM_TYPE>(GetParam())) {
+        std::tie(mFactory, mDescriptor) = std::get<PARAM_INSTANCE_NAME>(GetParam());
+    }
+
+    void SetUp() override {
+        ASSERT_NE(nullptr, mFactory);
+        ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+
+        Parameter::Specific specific = getDefaultParamSpecific();
+        Parameter::Common common = EffectHelper::createParamCommon(
+                0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */,
+                kInputFrameCount /* iFrameCount */, kOutputFrameCount /* oFrameCount */);
+        IEffect::OpenEffectReturn ret;
+        ASSERT_NO_FATAL_FAILURE(open(mEffect, common, specific, &ret, EX_NONE));
+        ASSERT_NE(nullptr, mEffect);
+    }
+
+    void TearDown() override {
+        ASSERT_NO_FATAL_FAILURE(close(mEffect));
+        ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
+    }
+
+    static const long kInputFrameCount = 0x100, kOutputFrameCount = 0x100;
+    std::shared_ptr<IFactory> mFactory;
+    std::shared_ptr<IEffect> mEffect;
+    Descriptor mDescriptor;
+    Downmix::Type mParamType = Downmix::Type::STRIP;
+
+    void SetAndGetDownmixParameters() {
+        for (auto& it : mTags) {
+            auto& tag = it.first;
+            auto& dm = it.second;
+
+            // set parameter
+            Parameter expectParam;
+            Parameter::Specific specific;
+            specific.set<Parameter::Specific::downmix>(dm);
+            expectParam.set<Parameter::specific>(specific);
+            // All values are valid, set parameter should succeed
+            EXPECT_STATUS(EX_NONE, mEffect->setParameter(expectParam)) << expectParam.toString();
+
+            // get parameter
+            Parameter getParam;
+            Parameter::Id id;
+            Downmix::Id dmId;
+            dmId.set<Downmix::Id::commonTag>(tag);
+            id.set<Parameter::Id::downmixTag>(dmId);
+            EXPECT_STATUS(EX_NONE, mEffect->getParameter(id, &getParam));
+
+            EXPECT_EQ(expectParam, getParam);
+        }
+    }
+
+    void addTypeParam(Downmix::Type type) {
+        Downmix dm;
+        dm.set<Downmix::type>(type);
+        mTags.push_back({Downmix::type, dm});
+    }
+
+    Parameter::Specific getDefaultParamSpecific() {
+        Downmix dm = Downmix::make<Downmix::type>(Downmix::Type::STRIP);
+        Parameter::Specific specific = Parameter::Specific::make<Parameter::Specific::downmix>(dm);
+        return specific;
+    }
+
+  private:
+    std::vector<std::pair<Downmix::Tag, Downmix>> mTags;
+    void CleanUp() { mTags.clear(); }
+};
+
+TEST_P(DownmixParamTest, SetAndGetType) {
+    EXPECT_NO_FATAL_FAILURE(addTypeParam(mParamType));
+    SetAndGetDownmixParameters();
+}
+
+INSTANTIATE_TEST_SUITE_P(
+        DownmixTest, DownmixParamTest,
+        ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
+                                   IFactory::descriptor, kDownmixTypeUUID)),
+                           testing::ValuesIn(kTypeValues)),
+        [](const testing::TestParamInfo<DownmixParamTest::ParamType>& info) {
+            auto descriptor = std::get<PARAM_INSTANCE_NAME>(info.param).second;
+            std::string type = std::to_string(static_cast<int>(std::get<PARAM_TYPE>(info.param)));
+            std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
+                               descriptor.common.name + "_UUID_" +
+                               descriptor.common.id.uuid.toString() + "_type" + type;
+            std::replace_if(
+                    name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
+            return name;
+        });
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DownmixParamTest);
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    ABinderProcess_setThreadPoolMaxThreadCount(1);
+    ABinderProcess_startThreadPool();
+    return RUN_ALL_TESTS();
+}
diff --git a/audio/common/all-versions/default/service/Android.bp b/audio/common/all-versions/default/service/Android.bp
index 9890be2..2fcfb23 100644
--- a/audio/common/all-versions/default/service/Android.bp
+++ b/audio/common/all-versions/default/service/Android.bp
@@ -38,9 +38,15 @@
     name: "android.hardware.audio.service",
 
     init_rc: ["android.hardware.audio.service.rc"],
+    vintf_fragments: ["android.hardware.audio.sounddose-aidl.xml"],
     relative_install_path: "hw",
     vendor: true,
 
+    defaults: [
+        "android_hardware_audio_config_defaults",
+        "latest_android_hardware_audio_sounddose_ndk_shared",
+    ],
+
     srcs: ["service.cpp"],
 
     cflags: [
@@ -50,6 +56,7 @@
     ],
 
     shared_libs: [
+        "//hardware/interfaces/audio/aidl/sounddose/default:libsounddoseserviceexampleimpl",
         "libcutils",
         "libbinder",
         "libbinder_ndk",
@@ -58,10 +65,6 @@
         "libutils",
         "libhardware",
     ],
-
-    defaults: [
-        "android_hardware_audio_config_defaults",
-    ],
 }
 
 // Legacy service name, use android.hardware.audio.service instead
diff --git a/audio/common/all-versions/default/service/android.hardware.audio.sounddose-aidl.xml b/audio/common/all-versions/default/service/android.hardware.audio.sounddose-aidl.xml
new file mode 100644
index 0000000..a297bfb
--- /dev/null
+++ b/audio/common/all-versions/default/service/android.hardware.audio.sounddose-aidl.xml
@@ -0,0 +1,7 @@
+<manifest version="1.0" type="device">
+  <hal format="aidl">
+    <name>android.hardware.audio.sounddose</name>
+    <version>1</version>
+    <fqname>ISoundDoseFactory/default</fqname>
+  </hal>
+</manifest>
diff --git a/audio/common/all-versions/default/service/service.cpp b/audio/common/all-versions/default/service/service.cpp
index fbf6165..e79ad75 100644
--- a/audio/common/all-versions/default/service/service.cpp
+++ b/audio/common/all-versions/default/service/service.cpp
@@ -20,6 +20,10 @@
 #include <string>
 #include <vector>
 
+#include <SoundDoseFactory.h>
+#include <android-base/logging.h>
+#include <android/binder_ibinder_platform.h>
+#include <android/binder_manager.h>
 #include <android/binder_process.h>
 #include <binder/ProcessState.h>
 #include <cutils/properties.h>
@@ -33,6 +37,8 @@
 
 using InterfacesList = std::vector<std::string>;
 
+using aidl::android::hardware::audio::sounddose::SoundDoseFactory;
+
 /** Try to register the provided factories in the provided order.
  *  If any registers successfully, do not register any other and return true.
  *  If all fail, return false.
@@ -164,5 +170,13 @@
         }
     }
 
+    // Register ISoundDoseFactory interface as a workaround for using the audio AIDL HAL
+    auto soundDoseDefault = ndk::SharedRefBase::make<SoundDoseFactory>();
+    const std::string soundDoseDefaultName =
+            std::string() + SoundDoseFactory::descriptor + "/default";
+    binder_status_t status = AServiceManager_addService(soundDoseDefault->asBinder().get(),
+                                                        soundDoseDefaultName.c_str());
+    CHECK_EQ(STATUS_OK, status);
+
     joinRpcThreadpool();
 }
diff --git a/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/CameraMetadataSection.aidl b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/CameraMetadataSection.aidl
index e28ecad..d99f16e 100644
--- a/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/CameraMetadataSection.aidl
+++ b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/CameraMetadataSection.aidl
@@ -71,5 +71,6 @@
   ANDROID_AUTOMOTIVE = 30,
   ANDROID_AUTOMOTIVE_LENS = 31,
   ANDROID_EXTENSION = 32,
+  ANDROID_JPEGR = 33,
   VENDOR_SECTION = 32768,
 }
diff --git a/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/CameraMetadataSectionStart.aidl b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/CameraMetadataSectionStart.aidl
index a223309..0bcd846 100644
--- a/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/CameraMetadataSectionStart.aidl
+++ b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/CameraMetadataSectionStart.aidl
@@ -71,5 +71,6 @@
   ANDROID_AUTOMOTIVE_START = 1966080,
   ANDROID_AUTOMOTIVE_LENS_START = 2031616,
   ANDROID_EXTENSION_START = 2097152,
+  ANDROID_JPEGR_START = 2162688,
   VENDOR_SECTION_START = -2147483648,
 }
diff --git a/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/CameraMetadataTag.aidl b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/CameraMetadataTag.aidl
index ecbfc93..b836dbe 100644
--- a/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/CameraMetadataTag.aidl
+++ b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/CameraMetadataTag.aidl
@@ -335,4 +335,10 @@
   ANDROID_HEIC_INFO_MAX_JPEG_APP_SEGMENTS_COUNT = 1900545,
   ANDROID_AUTOMOTIVE_LOCATION = 1966080,
   ANDROID_AUTOMOTIVE_LENS_FACING = 2031616,
+  ANDROID_JPEGR_AVAILABLE_JPEG_R_STREAM_CONFIGURATIONS = 2162688,
+  ANDROID_JPEGR_AVAILABLE_JPEG_R_MIN_FRAME_DURATIONS = 2162689,
+  ANDROID_JPEGR_AVAILABLE_JPEG_R_STALL_DURATIONS = 2162690,
+  ANDROID_JPEGR_AVAILABLE_JPEG_R_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION = 2162691,
+  ANDROID_JPEGR_AVAILABLE_JPEG_R_MIN_FRAME_DURATIONS_MAXIMUM_RESOLUTION = 2162692,
+  ANDROID_JPEGR_AVAILABLE_JPEG_R_STALL_DURATIONS_MAXIMUM_RESOLUTION = 2162693,
 }
diff --git a/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/JpegrAvailableJpegRStreamConfigurations.aidl b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/JpegrAvailableJpegRStreamConfigurations.aidl
new file mode 100644
index 0000000..cd005b5
--- /dev/null
+++ b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/JpegrAvailableJpegRStreamConfigurations.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *//*
+ * Autogenerated from camera metadata definitions in
+ * /system/media/camera/docs/metadata_definitions.xml
+ * *** DO NOT EDIT BY HAND ***
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file 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.camera.metadata;
+@Backing(type="int") @VintfStability
+enum JpegrAvailableJpegRStreamConfigurations {
+  ANDROID_JPEGR_AVAILABLE_JPEG_R_STREAM_CONFIGURATIONS_OUTPUT = 0,
+  ANDROID_JPEGR_AVAILABLE_JPEG_R_STREAM_CONFIGURATIONS_INPUT = 1,
+}
diff --git a/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/JpegrAvailableJpegRStreamConfigurationsMaximumResolution.aidl b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/JpegrAvailableJpegRStreamConfigurationsMaximumResolution.aidl
new file mode 100644
index 0000000..68028db
--- /dev/null
+++ b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/JpegrAvailableJpegRStreamConfigurationsMaximumResolution.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *//*
+ * Autogenerated from camera metadata definitions in
+ * /system/media/camera/docs/metadata_definitions.xml
+ * *** DO NOT EDIT BY HAND ***
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file 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.camera.metadata;
+@Backing(type="int") @VintfStability
+enum JpegrAvailableJpegRStreamConfigurationsMaximumResolution {
+  ANDROID_JPEGR_AVAILABLE_JPEG_R_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION_OUTPUT = 0,
+  ANDROID_JPEGR_AVAILABLE_JPEG_R_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION_INPUT = 1,
+}
diff --git a/camera/metadata/aidl/android/hardware/camera/metadata/CameraMetadataSection.aidl b/camera/metadata/aidl/android/hardware/camera/metadata/CameraMetadataSection.aidl
index 0d79f0d..73bcc12 100644
--- a/camera/metadata/aidl/android/hardware/camera/metadata/CameraMetadataSection.aidl
+++ b/camera/metadata/aidl/android/hardware/camera/metadata/CameraMetadataSection.aidl
@@ -62,5 +62,6 @@
     ANDROID_AUTOMOTIVE,
     ANDROID_AUTOMOTIVE_LENS,
     ANDROID_EXTENSION,
+    ANDROID_JPEGR,
     VENDOR_SECTION = 0x8000,
 }
diff --git a/camera/metadata/aidl/android/hardware/camera/metadata/CameraMetadataSectionStart.aidl b/camera/metadata/aidl/android/hardware/camera/metadata/CameraMetadataSectionStart.aidl
index 8f57128..75e7915 100644
--- a/camera/metadata/aidl/android/hardware/camera/metadata/CameraMetadataSectionStart.aidl
+++ b/camera/metadata/aidl/android/hardware/camera/metadata/CameraMetadataSectionStart.aidl
@@ -64,5 +64,6 @@
     ANDROID_AUTOMOTIVE_START = CameraMetadataSection.ANDROID_AUTOMOTIVE << 16,
     ANDROID_AUTOMOTIVE_LENS_START = CameraMetadataSection.ANDROID_AUTOMOTIVE_LENS << 16,
     ANDROID_EXTENSION_START = CameraMetadataSection.ANDROID_EXTENSION << 16,
+    ANDROID_JPEGR_START = CameraMetadataSection.ANDROID_JPEGR << 16,
     VENDOR_SECTION_START = CameraMetadataSection.VENDOR_SECTION << 16,
 }
diff --git a/camera/metadata/aidl/android/hardware/camera/metadata/CameraMetadataTag.aidl b/camera/metadata/aidl/android/hardware/camera/metadata/CameraMetadataTag.aidl
index 2e9bde9..83e9230 100644
--- a/camera/metadata/aidl/android/hardware/camera/metadata/CameraMetadataTag.aidl
+++ b/camera/metadata/aidl/android/hardware/camera/metadata/CameraMetadataTag.aidl
@@ -2298,4 +2298,56 @@
      * passenger seats.</p>
      */
     ANDROID_AUTOMOTIVE_LENS_FACING = CameraMetadataSectionStart.ANDROID_AUTOMOTIVE_LENS_START,
+    /**
+     * android.jpegr.availableJpegRStreamConfigurations [static, enum[], ndk_public]
+     *
+     * <p>The available Jpeg/R stream
+     * configurations that this camera device supports
+     * (i.e. format, width, height, output/input stream).</p>
+     */
+    ANDROID_JPEGR_AVAILABLE_JPEG_R_STREAM_CONFIGURATIONS = CameraMetadataSectionStart.ANDROID_JPEGR_START,
+    /**
+     * android.jpegr.availableJpegRMinFrameDurations [static, int64[], ndk_public]
+     *
+     * <p>This lists the minimum frame duration for each
+     * format/size combination for Jpeg/R output formats.</p>
+     */
+    ANDROID_JPEGR_AVAILABLE_JPEG_R_MIN_FRAME_DURATIONS,
+    /**
+     * android.jpegr.availableJpegRStallDurations [static, int64[], ndk_public]
+     *
+     * <p>This lists the maximum stall duration for each
+     * output format/size combination for Jpeg/R streams.</p>
+     */
+    ANDROID_JPEGR_AVAILABLE_JPEG_R_STALL_DURATIONS,
+    /**
+     * android.jpegr.availableJpegRStreamConfigurationsMaximumResolution [static, enum[], ndk_public]
+     *
+     * <p>The available Jpeg/R stream
+     * configurations that this camera device supports
+     * (i.e. format, width, height, output/input stream).</p>
+     */
+    ANDROID_JPEGR_AVAILABLE_JPEG_R_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION,
+    /**
+     * android.jpegr.availableJpegRMinFrameDurationsMaximumResolution [static, int64[], ndk_public]
+     *
+     * <p>This lists the minimum frame duration for each
+     * format/size combination for Jpeg/R output formats for CaptureRequests where
+     * ANDROID_SENSOR_PIXEL_MODE is set to
+     * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraMetadata.html#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION">CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION</a>.</p>
+     *
+     * @see ANDROID_SENSOR_PIXEL_MODE
+     */
+    ANDROID_JPEGR_AVAILABLE_JPEG_R_MIN_FRAME_DURATIONS_MAXIMUM_RESOLUTION,
+    /**
+     * android.jpegr.availableJpegRStallDurationsMaximumResolution [static, int64[], ndk_public]
+     *
+     * <p>This lists the maximum stall duration for each
+     * output format/size combination for Jpeg/R streams for CaptureRequests where
+     * ANDROID_SENSOR_PIXEL_MODE is set to
+     * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraMetadata.html#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION">CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION</a>.</p>
+     *
+     * @see ANDROID_SENSOR_PIXEL_MODE
+     */
+    ANDROID_JPEGR_AVAILABLE_JPEG_R_STALL_DURATIONS_MAXIMUM_RESOLUTION,
 }
diff --git a/camera/metadata/aidl/android/hardware/camera/metadata/JpegrAvailableJpegRStreamConfigurations.aidl b/camera/metadata/aidl/android/hardware/camera/metadata/JpegrAvailableJpegRStreamConfigurations.aidl
new file mode 100644
index 0000000..911a062
--- /dev/null
+++ b/camera/metadata/aidl/android/hardware/camera/metadata/JpegrAvailableJpegRStreamConfigurations.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Autogenerated from camera metadata definitions in
+ * /system/media/camera/docs/metadata_definitions.xml
+ * *** DO NOT EDIT BY HAND ***
+ */
+
+package android.hardware.camera.metadata;
+
+/**
+ * android.jpegr.availableJpegRStreamConfigurations enumeration values
+ * @see ANDROID_JPEGR_AVAILABLE_JPEG_R_STREAM_CONFIGURATIONS
+ */
+@VintfStability
+@Backing(type="int")
+enum JpegrAvailableJpegRStreamConfigurations {
+    ANDROID_JPEGR_AVAILABLE_JPEG_R_STREAM_CONFIGURATIONS_OUTPUT,
+    ANDROID_JPEGR_AVAILABLE_JPEG_R_STREAM_CONFIGURATIONS_INPUT,
+}
diff --git a/camera/metadata/aidl/android/hardware/camera/metadata/JpegrAvailableJpegRStreamConfigurationsMaximumResolution.aidl b/camera/metadata/aidl/android/hardware/camera/metadata/JpegrAvailableJpegRStreamConfigurationsMaximumResolution.aidl
new file mode 100644
index 0000000..9e78662
--- /dev/null
+++ b/camera/metadata/aidl/android/hardware/camera/metadata/JpegrAvailableJpegRStreamConfigurationsMaximumResolution.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Autogenerated from camera metadata definitions in
+ * /system/media/camera/docs/metadata_definitions.xml
+ * *** DO NOT EDIT BY HAND ***
+ */
+
+package android.hardware.camera.metadata;
+
+/**
+ * android.jpegr.availableJpegRStreamConfigurationsMaximumResolution enumeration values
+ * @see ANDROID_JPEGR_AVAILABLE_JPEG_R_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION
+ */
+@VintfStability
+@Backing(type="int")
+enum JpegrAvailableJpegRStreamConfigurationsMaximumResolution {
+    ANDROID_JPEGR_AVAILABLE_JPEG_R_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION_OUTPUT,
+    ANDROID_JPEGR_AVAILABLE_JPEG_R_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION_INPUT,
+}
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index a907f20..b2433e9 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -53,6 +53,14 @@
         </interface>
     </hal>
     <hal format="aidl" optional="true">
+        <name>android.hardware.audio.sounddose</name>
+        <version>1</version>
+        <interface>
+            <name>ISoundDoseFactory</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="aidl" optional="true">
          <name>android.hardware.authsecret</name>
          <version>1</version>
          <interface>
@@ -441,7 +449,7 @@
     </hal>
     <hal format="aidl" optional="false">
         <name>android.hardware.power</name>
-        <version>2-4</version>
+        <version>4</version>
         <interface>
             <name>IPower</name>
             <instance>default</instance>
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Dataspace.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Dataspace.aidl
index 668b033..563b6c1 100644
--- a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Dataspace.aidl
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Dataspace.aidl
@@ -94,5 +94,6 @@
   DYNAMIC_DEPTH = 4098,
   JPEG_APP_SEGMENTS = 4099,
   HEIF = 4100,
+  JPEG_R = 4101,
   BT709_FULL_RANGE = 146866176,
 }
diff --git a/graphics/common/aidl/android/hardware/graphics/common/Dataspace.aidl b/graphics/common/aidl/android/hardware/graphics/common/Dataspace.aidl
index 5e9360f..b44e613 100644
--- a/graphics/common/aidl/android/hardware/graphics/common/Dataspace.aidl
+++ b/graphics/common/aidl/android/hardware/graphics/common/Dataspace.aidl
@@ -668,6 +668,19 @@
     HEIF = 0x1004,
 
     /**
+     * ISO/IEC TBD
+     *
+     * JPEG image with embedded 10-bit recovery map following the Jpeg/R specification.
+     *
+     * This value must always remain aligned with the public ImageFormat Jpeg/R definition and is
+     * valid with formats:
+     *    HAL_PIXEL_FORMAT_BLOB: JPEG image encoded by Jpeg/R encoder according to ISO/IEC TBD.
+     * The image contains a standard SDR JPEG and a recovery map. Jpeg/R decoders can use the
+     * map to recover the 10-bit input image.
+     */
+    JPEG_R = 0x1005,
+
+    /**
      * ITU-R Recommendation 709 (BT.709)
      *
      * High-definition television
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/LayerCommand.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/LayerCommand.aidl
index 0c5fac9..6d32218 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/LayerCommand.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/LayerCommand.aidl
@@ -54,4 +54,5 @@
   @nullable android.hardware.graphics.composer3.PerFrameMetadata[] perFrameMetadata;
   @nullable android.hardware.graphics.composer3.PerFrameMetadataBlob[] perFrameMetadataBlob;
   @nullable android.hardware.graphics.common.Rect[] blockingRegion;
+  @nullable int[] bufferSlotsToClear;
 }
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/LayerCommand.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/LayerCommand.aidl
index f3b67a9..fd50be9 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/LayerCommand.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/LayerCommand.aidl
@@ -258,4 +258,11 @@
      * the screen.
      */
     @nullable Rect[] blockingRegion;
+
+    /**
+     * Specifies which buffer slots should be cleared of buffer references
+     * because these buffers will no longer be used and the memory should
+     * be freed.
+     */
+    @nullable int[] bufferSlotsToClear;
 }
diff --git a/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientWriter.h b/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientWriter.h
index e35d07b..22020c0 100644
--- a/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientWriter.h
+++ b/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientWriter.h
@@ -142,6 +142,14 @@
         flushLayerCommand();
     }
 
+    void setLayerBufferSlotsToClear(int64_t display, int64_t layer,
+                                    const std::vector<uint32_t>& slotsToClear) {
+        LayerCommand& layerCommand = getLayerCommand(display, layer);
+        for (auto slot : slotsToClear) {
+            layerCommand.bufferSlotsToClear.emplace(static_cast<int32_t>(slot));
+        }
+    }
+
     void setLayerSurfaceDamage(int64_t display, int64_t layer, const std::vector<Rect>& damage) {
         getLayerCommand(display, layer).damage.emplace(damage.begin(), damage.end());
     }
diff --git a/graphics/composer/aidl/vts/VtsComposerClient.cpp b/graphics/composer/aidl/vts/VtsComposerClient.cpp
index 34cc802..00b578b 100644
--- a/graphics/composer/aidl/vts/VtsComposerClient.cpp
+++ b/graphics/composer/aidl/vts/VtsComposerClient.cpp
@@ -58,6 +58,12 @@
     return verifyComposerCallbackParams() && destroyAllLayers();
 }
 
+std::pair<ScopedAStatus, int32_t> VtsComposerClient::getInterfaceVersion() {
+    int32_t version = 1;
+    auto status = mComposerClient->getInterfaceVersion(&version);
+    return {std::move(status), version};
+}
+
 std::pair<ScopedAStatus, VirtualDisplay> VtsComposerClient::createVirtualDisplay(
         int32_t width, int32_t height, PixelFormat pixelFormat, int32_t bufferSlotCount) {
     VirtualDisplay outVirtualDisplay;
diff --git a/graphics/composer/aidl/vts/VtsComposerClient.h b/graphics/composer/aidl/vts/VtsComposerClient.h
index 1883336..e61fde9 100644
--- a/graphics/composer/aidl/vts/VtsComposerClient.h
+++ b/graphics/composer/aidl/vts/VtsComposerClient.h
@@ -61,6 +61,8 @@
 
     bool tearDown();
 
+    std::pair<ScopedAStatus, int32_t> getInterfaceVersion();
+
     std::pair<ScopedAStatus, VirtualDisplay> createVirtualDisplay(int32_t width, int32_t height,
                                                                   PixelFormat pixelFormat,
                                                                   int32_t bufferSlotCount);
diff --git a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp
index 93d9693..166127d 100644
--- a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp
+++ b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp
@@ -379,9 +379,16 @@
 }
 
 TEST_P(GraphicsCompositionTest, SetLayerBufferWithSlotsToClear) {
-    const auto& [status, readbackBufferAttributes] =
+    const auto& [versionStatus, version] = mComposerClient->getInterfaceVersion();
+    ASSERT_TRUE(versionStatus.isOk());
+    if (version == 1) {
+        GTEST_SUCCEED() << "Device does not support the new API for clearing buffer slots";
+        return;
+    }
+
+    const auto& [readbackStatus, readbackBufferAttributes] =
             mComposerClient->getReadbackBufferAttributes(getPrimaryDisplayId());
-    if (!status.isOk()) {
+    if (!readbackStatus.isOk()) {
         GTEST_SUCCEED() << "Readback not supported";
         return;
     }
@@ -396,9 +403,6 @@
     // no fence needed for the readback buffer
     ScopedFileDescriptor noFence(-1);
 
-    sp<GraphicBuffer> clearSlotBuffer = allocateBuffer(1u, 1u, GRALLOC_USAGE_HW_COMPOSER);
-    ASSERT_NE(nullptr, clearSlotBuffer);
-
     // red buffer
     uint64_t usage = GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_SW_READ_OFTEN;
     sp<GraphicBuffer> redBuffer = allocateBuffer(usage);
@@ -412,10 +416,16 @@
     int blueFence;
     ASSERT_NO_FATAL_FAILURE(ReadbackHelper::fillBufferAndGetFence(blueBuffer, BLUE, &blueFence));
 
+    // green buffer
+    sp<GraphicBuffer> greenBuffer = allocateBuffer(usage);
+    ASSERT_NE(nullptr, greenBuffer);
+    int greenFence;
+    ASSERT_NO_FATAL_FAILURE(ReadbackHelper::fillBufferAndGetFence(greenBuffer, GREEN, &greenFence));
+
     // layer defaults
     common::Rect rectFullDisplay = {0, 0, getDisplayWidth(), getDisplayHeight()};
     int64_t display = getPrimaryDisplayId();
-    auto [layerStatus, layer] = mComposerClient->createLayer(getPrimaryDisplayId(), 3);
+    const auto& [layerStatus, layer] = mComposerClient->createLayer(getPrimaryDisplayId(), 3);
     ASSERT_TRUE(layerStatus.isOk());
     mWriter->setLayerDisplayFrame(display, layer, rectFullDisplay);
     mWriter->setLayerCompositionType(display, layer, Composition::DEVICE);
@@ -454,13 +464,12 @@
         ReadbackHelper::compareColorToBuffer(RED, readbackBuffer, fence);
     }
 
-    // clear the slot for the blue buffer
-    // should still be red
+    // change the layer to the green buffer
+    // should be green
     {
         auto status = mComposerClient->setReadbackBuffer(display, readbackBuffer->handle, noFence);
         ASSERT_TRUE(status.isOk());
-        mWriter->setLayerBufferWithNewCommand(display, layer, /*slot*/ 0, clearSlotBuffer->handle,
-                                              /*fence*/ -1);
+        mWriter->setLayerBuffer(display, layer, /*slot*/ 2, greenBuffer->handle, greenFence);
         mWriter->validateDisplay(display, ComposerClientWriter::kNoTimestamp);
         execute();
         ASSERT_TRUE(mReader.takeChangedCompositionTypes(display).empty());
@@ -469,17 +478,106 @@
         execute();
         auto [fenceStatus, fence] = mComposerClient->getReadbackBufferFence(display);
         ASSERT_TRUE(fenceStatus.isOk());
-        ReadbackHelper::compareColorToBuffer(RED, readbackBuffer, fence);
+        ReadbackHelper::compareColorToBuffer(GREEN, readbackBuffer, fence);
     }
 
-    // clear the slot for the red buffer, and set the buffer with the same slot to the blue buffer
+    // clear the slots for all buffers
+    // should still be green since the active buffer should not be cleared by the HAL implementation
+    {
+        auto status = mComposerClient->setReadbackBuffer(display, readbackBuffer->handle, noFence);
+        ASSERT_TRUE(status.isOk());
+        mWriter->setLayerBufferSlotsToClear(display, layer, /*slotsToClear*/ {0, 1, 2});
+        mWriter->validateDisplay(display, ComposerClientWriter::kNoTimestamp);
+        execute();
+        ASSERT_TRUE(mReader.takeChangedCompositionTypes(display).empty());
+        ASSERT_TRUE(mReader.takeErrors().empty());
+        mWriter->presentDisplay(display);
+        execute();
+        auto [fenceStatus, fence] = mComposerClient->getReadbackBufferFence(display);
+        ASSERT_TRUE(fenceStatus.isOk());
+        ReadbackHelper::compareColorToBuffer(GREEN, readbackBuffer, fence);
+    }
+
+    // clear the slot for the green buffer, and set the buffer with the same slot to the blue buffer
     // should be blue
     {
         auto status = mComposerClient->setReadbackBuffer(display, readbackBuffer->handle, noFence);
         ASSERT_TRUE(status.isOk());
-        mWriter->setLayerBufferWithNewCommand(display, layer, /*slot*/ 1, clearSlotBuffer->handle,
-                                              /*fence*/ -1);
-        mWriter->setLayerBuffer(display, layer, /*slot*/ 1, blueBuffer->handle, blueFence);
+        mWriter->setLayerBufferSlotsToClear(display, layer, /*slotsToClear*/ {2});
+        mWriter->setLayerBuffer(display, layer, /*slot*/ 2, blueBuffer->handle, blueFence);
+        mWriter->validateDisplay(display, ComposerClientWriter::kNoTimestamp);
+        execute();
+        ASSERT_TRUE(mReader.takeChangedCompositionTypes(display).empty());
+        ASSERT_TRUE(mReader.takeErrors().empty());
+        mWriter->presentDisplay(display);
+        execute();
+        auto [fenceStatus, fence] = mComposerClient->getReadbackBufferFence(display);
+        ASSERT_TRUE(fenceStatus.isOk());
+        ReadbackHelper::compareColorToBuffer(BLUE, readbackBuffer, fence);
+    }
+}
+
+TEST_P(GraphicsCompositionTest, SetLayerBufferWithSlotsToClear_backwardsCompatible) {
+    const auto& [versionStatus, version] = mComposerClient->getInterfaceVersion();
+    ASSERT_TRUE(versionStatus.isOk());
+    if (version > 1) {
+        GTEST_SUCCEED() << "Device does not need a backwards compatible way to clear buffer slots";
+        return;
+    }
+
+    const auto& [readbackStatus, readbackBufferAttributes] =
+            mComposerClient->getReadbackBufferAttributes(getPrimaryDisplayId());
+    if (!readbackStatus.isOk()) {
+        GTEST_SUCCEED() << "Readback not supported";
+        return;
+    }
+
+    sp<GraphicBuffer> readbackBuffer;
+    ASSERT_NO_FATAL_FAILURE(ReadbackHelper::createReadbackBuffer(
+            readbackBufferAttributes, getPrimaryDisplay(), &readbackBuffer));
+    if (readbackBuffer == nullptr) {
+        GTEST_SUCCEED() << "Unsupported readback buffer attributes";
+        return;
+    }
+    // no fence needed for the readback buffer
+    ScopedFileDescriptor noFence(-1);
+
+    sp<GraphicBuffer> clearSlotBuffer = allocateBuffer(1u, 1u, GRALLOC_USAGE_HW_COMPOSER);
+    ASSERT_NE(nullptr, clearSlotBuffer);
+
+    // red buffer
+    uint64_t usage = GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_SW_READ_OFTEN;
+    sp<GraphicBuffer> redBuffer = allocateBuffer(usage);
+    ASSERT_NE(nullptr, redBuffer);
+    int redFence;
+    ASSERT_NO_FATAL_FAILURE(ReadbackHelper::fillBufferAndGetFence(redBuffer, RED, &redFence));
+
+    // blue buffer
+    sp<GraphicBuffer> blueBuffer = allocateBuffer(usage);
+    ASSERT_NE(nullptr, blueBuffer);
+    int blueFence;
+    ASSERT_NO_FATAL_FAILURE(ReadbackHelper::fillBufferAndGetFence(blueBuffer, BLUE, &blueFence));
+
+    // green buffer
+    sp<GraphicBuffer> greenBuffer = allocateBuffer(usage);
+    ASSERT_NE(nullptr, greenBuffer);
+    int greenFence;
+    ASSERT_NO_FATAL_FAILURE(ReadbackHelper::fillBufferAndGetFence(greenBuffer, GREEN, &greenFence));
+
+    // layer defaults
+    common::Rect rectFullDisplay = {0, 0, getDisplayWidth(), getDisplayHeight()};
+    int64_t display = getPrimaryDisplayId();
+    const auto& [layerStatus, layer] = mComposerClient->createLayer(getPrimaryDisplayId(), 3);
+    ASSERT_TRUE(layerStatus.isOk());
+    mWriter->setLayerDisplayFrame(display, layer, rectFullDisplay);
+    mWriter->setLayerCompositionType(display, layer, Composition::DEVICE);
+
+    // set the layer to the blue buffer
+    // should be blue
+    {
+        auto status = mComposerClient->setReadbackBuffer(display, readbackBuffer->handle, noFence);
+        ASSERT_TRUE(status.isOk());
+        mWriter->setLayerBuffer(display, layer, /*slot*/ 0, blueBuffer->handle, blueFence);
         mWriter->validateDisplay(display, ComposerClientWriter::kNoTimestamp);
         execute();
         ASSERT_TRUE(mReader.takeChangedCompositionTypes(display).empty());
@@ -491,27 +589,82 @@
         ReadbackHelper::compareColorToBuffer(BLUE, readbackBuffer, fence);
     }
 
-    // clear the slot for the now-blue buffer
-    // should be black (no buffer)
-    // TODO(b/262037933) Ensure we never clear the active buffer's slot with the placeholder buffer
-    // by setting the layer to the color black
+    // change the layer to the red buffer
+    // should be red
     {
         auto status = mComposerClient->setReadbackBuffer(display, readbackBuffer->handle, noFence);
         ASSERT_TRUE(status.isOk());
-        mWriter->setLayerBufferWithNewCommand(display, layer, /*slot*/ 1, clearSlotBuffer->handle,
-                                              /*fence*/ -1);
+        mWriter->setLayerBuffer(display, layer, /*slot*/ 1, redBuffer->handle, redFence);
         mWriter->validateDisplay(display, ComposerClientWriter::kNoTimestamp);
         execute();
-        if (!mReader.takeChangedCompositionTypes(display).empty()) {
-            GTEST_SUCCEED();
-            return;
-        }
+        ASSERT_TRUE(mReader.takeChangedCompositionTypes(display).empty());
         ASSERT_TRUE(mReader.takeErrors().empty());
         mWriter->presentDisplay(display);
         execute();
         auto [fenceStatus, fence] = mComposerClient->getReadbackBufferFence(display);
         ASSERT_TRUE(fenceStatus.isOk());
-        ReadbackHelper::compareColorToBuffer(BLACK, readbackBuffer, fence);
+        ReadbackHelper::compareColorToBuffer(RED, readbackBuffer, fence);
+    }
+
+    // change the layer to the green buffer
+    // should be green
+    {
+        auto status = mComposerClient->setReadbackBuffer(display, readbackBuffer->handle, noFence);
+        ASSERT_TRUE(status.isOk());
+        mWriter->setLayerBuffer(display, layer, /*slot*/ 2, greenBuffer->handle, greenFence);
+        mWriter->validateDisplay(display, ComposerClientWriter::kNoTimestamp);
+        execute();
+        ASSERT_TRUE(mReader.takeChangedCompositionTypes(display).empty());
+        ASSERT_TRUE(mReader.takeErrors().empty());
+        mWriter->presentDisplay(display);
+        execute();
+        auto [fenceStatus, fence] = mComposerClient->getReadbackBufferFence(display);
+        ASSERT_TRUE(fenceStatus.isOk());
+        ReadbackHelper::compareColorToBuffer(GREEN, readbackBuffer, fence);
+    }
+
+    // clear the slot for the blue buffer
+    // should still be green
+    {
+        auto status = mComposerClient->setReadbackBuffer(display, readbackBuffer->handle, noFence);
+        ASSERT_TRUE(status.isOk());
+        mWriter->setLayerBufferWithNewCommand(display, layer, /*slot*/ 0, clearSlotBuffer->handle,
+                                              /*fence*/ -1);
+        // SurfaceFlinger will re-set the active buffer slot after other buffer slots are cleared
+        mWriter->setLayerBufferWithNewCommand(display, layer, /*slot*/ 2, /*handle*/ nullptr,
+                                              /*fence*/ -1);
+        mWriter->validateDisplay(display, ComposerClientWriter::kNoTimestamp);
+        execute();
+        ASSERT_TRUE(mReader.takeChangedCompositionTypes(display).empty());
+        ASSERT_TRUE(mReader.takeErrors().empty());
+        mWriter->presentDisplay(display);
+        execute();
+        auto [fenceStatus, fence] = mComposerClient->getReadbackBufferFence(display);
+        ASSERT_TRUE(fenceStatus.isOk());
+        ReadbackHelper::compareColorToBuffer(GREEN, readbackBuffer, fence);
+    }
+
+    // clear the slot for all buffers, and set the buffer with the same slot as the green buffer
+    // should be blue now
+    {
+        auto status = mComposerClient->setReadbackBuffer(display, readbackBuffer->handle, noFence);
+        ASSERT_TRUE(status.isOk());
+        mWriter->setLayerBufferWithNewCommand(display, layer, /*slot*/ 0, clearSlotBuffer->handle,
+                                              /*fence*/ -1);
+        mWriter->setLayerBufferWithNewCommand(display, layer, /*slot*/ 1, clearSlotBuffer->handle,
+                                              /*fence*/ -1);
+        // SurfaceFlinger will never clear the active buffer (slot 2), but will free up the
+        // buffer slot so it will be re-used for the next setLayerBuffer command
+        mWriter->setLayerBuffer(display, layer, /*slot*/ 2, blueBuffer->handle, blueFence);
+        mWriter->validateDisplay(display, ComposerClientWriter::kNoTimestamp);
+        execute();
+        ASSERT_TRUE(mReader.takeChangedCompositionTypes(display).empty());
+        ASSERT_TRUE(mReader.takeErrors().empty());
+        mWriter->presentDisplay(display);
+        execute();
+        auto [fenceStatus, fence] = mComposerClient->getReadbackBufferFence(display);
+        ASSERT_TRUE(fenceStatus.isOk());
+        ReadbackHelper::compareColorToBuffer(BLUE, readbackBuffer, fence);
     }
 }
 
diff --git a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp
index 0f00fd6..7b852e0 100644
--- a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp
+++ b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp
@@ -1647,28 +1647,85 @@
 }
 
 TEST_P(GraphicsComposerAidlCommandTest, SetLayerBufferWithSlotsToClear) {
-    auto clearSlotBuffer = allocate(1u, 1u, ::android::PIXEL_FORMAT_RGB_888);
-    ASSERT_NE(nullptr, clearSlotBuffer);
-    auto clearSlotBufferHandle = clearSlotBuffer->handle;
+    const auto& [versionStatus, version] = mComposerClient->getInterfaceVersion();
+    ASSERT_TRUE(versionStatus.isOk());
+    if (version == 1) {
+        GTEST_SUCCEED() << "Device does not support the new API for clearing buffer slots";
+        return;
+    }
+
+    const auto& [layerStatus, layer] =
+            mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount);
+    EXPECT_TRUE(layerStatus.isOk());
+
+    auto& writer = getWriter(getPrimaryDisplayId());
 
     const auto buffer1 = allocate(::android::PIXEL_FORMAT_RGBA_8888);
     ASSERT_NE(nullptr, buffer1);
     const auto handle1 = buffer1->handle;
-    const auto& [layerStatus, layer] =
-            mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount);
-    EXPECT_TRUE(layerStatus.isOk());
-    auto& writer = getWriter(getPrimaryDisplayId());
     writer.setLayerBuffer(getPrimaryDisplayId(), layer, /*slot*/ 0, handle1, /*acquireFence*/ -1);
     execute();
     ASSERT_TRUE(mReader.takeErrors().empty());
 
-    // Ensure we can clear a buffer slot and then set that same slot with a new buffer
     const auto buffer2 = allocate(::android::PIXEL_FORMAT_RGBA_8888);
     ASSERT_NE(nullptr, buffer2);
     const auto handle2 = buffer2->handle;
-    writer.setLayerBufferWithNewCommand(getPrimaryDisplayId(), layer, /* slot */ 0,
+    writer.setLayerBuffer(getPrimaryDisplayId(), layer, /*slot*/ 1, handle2, /*acquireFence*/ -1);
+    execute();
+    ASSERT_TRUE(mReader.takeErrors().empty());
+
+    // Ensure we can clear the buffer slots and then set the active slot with a new buffer
+    const auto buffer3 = allocate(::android::PIXEL_FORMAT_RGBA_8888);
+    ASSERT_NE(nullptr, buffer3);
+    const auto handle3 = buffer3->handle;
+    writer.setLayerBufferSlotsToClear(getPrimaryDisplayId(), layer, /*slotsToClear*/ {0, 1});
+    writer.setLayerBuffer(getPrimaryDisplayId(), layer, /*slot*/ 1, handle3, /*acquireFence*/ -1);
+    execute();
+    ASSERT_TRUE(mReader.takeErrors().empty());
+}
+
+TEST_P(GraphicsComposerAidlCommandTest, SetLayerBufferWithSlotsToClear_backwardsCompatible) {
+    const auto& [versionStatus, version] = mComposerClient->getInterfaceVersion();
+    ASSERT_TRUE(versionStatus.isOk());
+    if (version > 1) {
+        GTEST_SUCCEED() << "Device does not need a backwards compatible way to clear buffer slots";
+        return;
+    }
+
+    auto clearSlotBuffer = allocate(1u, 1u, ::android::PIXEL_FORMAT_RGB_888);
+    ASSERT_NE(nullptr, clearSlotBuffer);
+    auto clearSlotBufferHandle = clearSlotBuffer->handle;
+
+    const auto& [layerStatus, layer] =
+            mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount);
+    EXPECT_TRUE(layerStatus.isOk());
+
+    auto& writer = getWriter(getPrimaryDisplayId());
+
+    const auto buffer1 = allocate(::android::PIXEL_FORMAT_RGBA_8888);
+    ASSERT_NE(nullptr, buffer1);
+    const auto handle1 = buffer1->handle;
+    writer.setLayerBuffer(getPrimaryDisplayId(), layer, /*slot*/ 0, handle1, /*acquireFence*/ -1);
+    execute();
+    ASSERT_TRUE(mReader.takeErrors().empty());
+
+    const auto buffer2 = allocate(::android::PIXEL_FORMAT_RGBA_8888);
+    ASSERT_NE(nullptr, buffer2);
+    const auto handle2 = buffer2->handle;
+    EXPECT_TRUE(layerStatus.isOk());
+    writer.setLayerBuffer(getPrimaryDisplayId(), layer, /*slot*/ 1, handle2, /*acquireFence*/ -1);
+    execute();
+    ASSERT_TRUE(mReader.takeErrors().empty());
+
+    // Ensure we can clear a buffer slot and then set that same slot with a new buffer
+    const auto buffer3 = allocate(::android::PIXEL_FORMAT_RGBA_8888);
+    ASSERT_NE(nullptr, buffer3);
+    const auto handle3 = buffer2->handle;
+    // SurfaceFlinger will never clear the active buffer, instead it will clear non-active buffers
+    // and then re-use the active buffer's slot for the new buffer
+    writer.setLayerBufferWithNewCommand(getPrimaryDisplayId(), layer, /*slot*/ 0,
                                         clearSlotBufferHandle, /*acquireFence*/ -1);
-    writer.setLayerBuffer(getPrimaryDisplayId(), layer, /*slot*/ 0, handle2, /*acquireFence*/ -1);
+    writer.setLayerBuffer(getPrimaryDisplayId(), layer, /*slot*/ 1, handle3, /*acquireFence*/ -1);
     execute();
     ASSERT_TRUE(mReader.takeErrors().empty());
 }
diff --git a/identity/support/Android.bp b/identity/support/Android.bp
index 4e3d1f7..3096fe5 100644
--- a/identity/support/Android.bp
+++ b/identity/support/Android.bp
@@ -65,57 +65,3 @@
     ],
     test_suites: ["general-tests"],
 }
-
-// --
-
-cc_library {
-    name: "libcppbor",
-    vendor_available: true,
-    host_supported: true,
-    srcs: [
-        "src/cppbor.cpp",
-        "src/cppbor_parse.cpp",
-    ],
-    export_include_dirs: [
-        "include/cppbor",
-    ],
-    shared_libs: [
-        "libbase",
-    ],
-}
-
-cc_test {
-    name: "cppbor_test",
-    tidy_timeout_srcs: [
-        "tests/cppbor_test.cpp",
-    ],
-    srcs: [
-        "tests/cppbor_test.cpp",
-    ],
-    shared_libs: [
-        "libcppbor_external",
-        "libbase",
-    ],
-    static_libs: [
-        "libgmock",
-    ],
-    test_suites: ["general-tests"],
-}
-
-cc_test_host {
-    name: "cppbor_host_test",
-    tidy_timeout_srcs: [
-        "tests/cppbor_test.cpp",
-    ],
-    srcs: [
-        "tests/cppbor_test.cpp",
-    ],
-    shared_libs: [
-        "libcppbor_external",
-        "libbase",
-    ],
-    static_libs: [
-        "libgmock",
-    ],
-    test_suites: ["general-tests"],
-}
diff --git a/identity/support/include/cppbor/README.md b/identity/support/include/cppbor/README.md
deleted file mode 100644
index 723bfcf..0000000
--- a/identity/support/include/cppbor/README.md
+++ /dev/null
@@ -1,216 +0,0 @@
-CppBor: A Modern C++ CBOR Parser and Generator
-==============================================
-
-CppBor provides a natural and easy-to-use syntax for constructing and
-parsing CBOR messages.  It does not (yet) support all features of
-CBOR, nor (yet) support validation against CDDL schemata, though both
-are planned.  CBOR features that aren't supported include:
-
-* Indefinite length values
-* Semantic tagging
-* Floating point
-
-CppBor requires C++-17.
-
-## CBOR representation
-
-CppBor represents CBOR data items as instances of the `Item` class or,
-more precisely, as instances of subclasses of `Item`, since `Item` is a
-pure interface.  The subclasses of `Item` correspond almost one-to-one
-with CBOR major types, and are named to match the CDDL names to which
-they correspond.  They are:
-
-* `Uint` corresponds to major type 0, and can hold unsigned integers
-  up through (2^64 - 1).
-* `Nint` corresponds to major type 1.  It can only hold values from -1
-  to -(2^63 - 1), since it's internal representation is an int64_t.
-  This can be fixed, but it seems unlikely that applications will need
-  the omitted range from -(2^63) to (2^64 - 1), since it's
-  inconvenient to represent them in many programming languages.
-* `Int` is an abstract base of `Uint` and `Nint` that facilitates
-  working with all signed integers representable with int64_t.
-* `Bstr` corresponds to major type 2, a byte string.
-* `Tstr` corresponds to major type 3, a text string.
-* `Array` corresponds to major type 4, an Array.  It holds a
-  variable-length array of `Item`s.
-* `Map` corresponds to major type 5, a Map.  It holds a
-  variable-length array of pairs of `Item`s.
-* `Simple` corresponds to major type 7.  It's an abstract class since
-  items require more specific type.
-* `Bool` is the only currently-implemented subclass of `Simple`.
-
-Note that major type 6, semantic tag, is not yet implemented.
-
-In practice, users of CppBor will rarely use most of these classes
-when generating CBOR encodings.  This is because CppBor provides
-straightforward conversions from the obvious normal C++ types.
-Specifically, the following conversions are provided in appropriate
-contexts:
-
-* Signed and unsigned integers convert to `Uint` or `Nint`, as
-  appropriate.
-* `std::string`, `std::string_view`, `const char*` and
-  `std::pair<char iterator, char iterator>` convert to `Tstr`.
-* `std::vector<uint8_t>`, `std::pair<uint8_t iterator, uint8_t
-  iterator>` and `std::pair<uint8_t*, size_t>` convert to `Bstr`.
-* `bool` converts to `Bool`.
-
-## CBOR generation
-
-### Complete tree generation
-
-The set of `encode` methods in `Item` provide the interface for
-producing encoded CBOR.  The basic process for "complete tree"
-generation (as opposed to "incremental" generation, which is discussed
-below) is to construct an `Item` which models the data to be encoded,
-and then call one of the `encode` methods, whichever is convenient for
-the encoding destination.  A trivial example:
-
-```
-cppbor::Uint val(0);
-std::vector<uint8_t> encoding = val.encode();
-```
-
-    It's relatively rare that single values are encoded as above.  More often, the
-    "root" data item will be an `Array` or `Map` which contains a more complex structure.For example
-    :
-
-``` using cppbor::Map;
-using cppbor::Array;
-
-std::vector<uint8_t> vec =  // ...
-    Map val("key1", Array(Map("key_a", 99 "key_b", vec), "foo"), "key2", true);
-std::vector<uint8_t> encoding = val.encode();
-```
-
-This creates a map with two entries, with `Tstr` keys "Outer1" and
-"Outer2", respectively.  The "Outer1" entry has as its value an
-`Array` containing a `Map` and a `Tstr`.  The "Outer2" entry has a
-`Bool` value.
-
-This example demonstrates how automatic conversion of C++ types to
-CppBor `Item` subclass instances is done.  Where the caller provides a
-C++ or C string, a `Tstr` entry is added.  Where the caller provides
-an integer literal or variable, a `Uint` or `Nint` is added, depending
-on whether the value is positive or negative.
-
-As an alternative, a more fluent-style API is provided for building up
-structures.  For example:
-
-```
-using cppbor::Map;
-using cppbor::Array;
-
-std::vector<uint8_t> vec =  // ...
-    Map val();
-val.add("key1", Array().add(Map().add("key_a", 99).add("key_b", vec)).add("foo")).add("key2", true);
-std::vector<uint8_t> encoding = val.encode();
-```
-
-    An advantage of this interface over the constructor -
-    based creation approach above is that it need not be done all at once
-        .The `add` methods return a reference to the object added to to allow calls to be chained,
-    but chaining is not necessary; calls can be made
-sequentially, as the data to add is available.
-
-#### `encode` methods
-
-There are several variations of `Item::encode`, all of which
-accomplish the same task but output the encoded data in different
-ways, and with somewhat different performance characteristics.  The
-provided options are:
-
-* `bool encode(uint8\_t** pos, const uint8\_t* end)` encodes into the
-  buffer referenced by the range [`*pos`, end).  `*pos` is moved.  If
-  the encoding runs out of buffer space before finishing, the method
-  returns false.  This is the most efficient way to encode, into an
-  already-allocated buffer.
-* `void encode(EncodeCallback encodeCallback)` calls `encodeCallback`
-  for each encoded byte.  It's the responsibility of the implementor
-  of the callback to behave safely in the event that the output buffer
-  (if applicable) is exhausted.  This is less efficient than the prior
-  method because it imposes an additional function call for each byte.
-* `template </*...*/> void encode(OutputIterator i)`
-  encodes into the provided iterator.  SFINAE ensures that the
-  template doesn't match for non-iterators.  The implementation
-  actually uses the callback-based method, plus has whatever overhead
-  the iterator adds.
-* `std::vector<uint8_t> encode()` creates a new std::vector, reserves
-  sufficient capacity to hold the encoding, and inserts the encoded
-  bytes with a std::pushback_iterator and the previous method.
-* `std::string toString()` does the same as the previous method, but
-  returns a string instead of a vector.
-
-### Incremental generation
-
-Incremental generation requires deeper understanding of CBOR, because
-the library can't do as much to ensure that the output is valid.  The
-basic tool for intcremental generation is the `encodeHeader`
-function.  There are two variations, one which writes into a buffer,
-and one which uses a callback.  Both simply write out the bytes of a
-header.  To construct the same map as in the above examples,
-incrementally, one might write:
-
-```
-using namespace cppbor;  // For example brevity
-
-std::vector encoding;
-auto iter = std::back_inserter(result);
-encodeHeader(MAP, 2 /* # of map entries */, iter);
-std::string s = "key1";
-encodeHeader(TSTR, s.size(), iter);
-std::copy(s.begin(), s.end(), iter);
-encodeHeader(ARRAY, 2 /* # of array entries */, iter);
-Map().add("key_a", 99).add("key_b", vec).encode(iter)
-s = "foo";
-encodeHeader(TSTR, foo.size(), iter);
-std::copy(s.begin(), s.end(), iter);
-s = "key2";
-encodeHeader(TSTR, foo.size(), iter);
-std::copy(s.begin(), s.end(), iter);
-encodeHeader(SIMPLE, TRUE, iter);
-```
-
-As the above example demonstrates, the styles can be mixed -- Note the
-creation and encoding of the inner Map using the fluent style.
-
-## Parsing
-
-CppBor also supports parsing of encoded CBOR data, with the same
-feature set as encoding.  There are two basic approaches to parsing,
-"full" and "stream"
-
-### Full parsing
-
-Full parsing means completely parsing a (possibly-compound) data
-item from a byte buffer.  The `parse` functions that do not take a
-`ParseClient` pointer do this.  They return a `ParseResult` which is a
-tuple of three values:
-
-* std::unique_ptr<Item> that points to the parsed item, or is nullptr
-  if there was a parse error.
-* const uint8_t* that points to the byte after the end of the decoded
-  item, or to the first unparseable byte in the event of an error.
-* std::string that is empty on success or contains an error message if
-  a parse error occurred.
-
-Assuming a successful parse, you can then use `Item::type()` to
-discover the type of the parsed item (e.g. MAP), and then use the
-appropriate `Item::as*()` method (e.g. `Item::asMap()`) to get a
-pointer to an interface which allows you to retrieve specific values.
-
-### Stream parsing
-
-Stream parsing is more complex, but more flexible.  To use
-StreamParsing, you must create your own subclass of `ParseClient` and
-call one of the `parse` functions that accepts it.  See the
-`ParseClient` methods docstrings for details.
-
-One unusual feature of stream parsing is that the `ParseClient`
-callback methods not only provide the parsed Item, but also pointers
-to the portion of the buffer that encode that Item.  This is useful
-if, for example, you want to find an element inside of a structure,
-and then copy the encoding of that sub-structure, without bothering to
-parse the rest.
-
-The full parser is implemented with the stream parser.
diff --git a/identity/support/include/cppbor/cppbor.h b/identity/support/include/cppbor/cppbor.h
deleted file mode 100644
index af5d82e..0000000
--- a/identity/support/include/cppbor/cppbor.h
+++ /dev/null
@@ -1,827 +0,0 @@
-/*
- * Copyright (c) 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 <cstdint>
-#include <functional>
-#include <iterator>
-#include <memory>
-#include <numeric>
-#include <string>
-#include <vector>
-
-namespace cppbor {
-
-enum MajorType : uint8_t {
-    UINT = 0 << 5,
-    NINT = 1 << 5,
-    BSTR = 2 << 5,
-    TSTR = 3 << 5,
-    ARRAY = 4 << 5,
-    MAP = 5 << 5,
-    SEMANTIC = 6 << 5,
-    SIMPLE = 7 << 5,
-};
-
-enum SimpleType {
-    BOOLEAN,
-    NULL_T,  // Only two supported, as yet.
-};
-
-enum SpecialAddlInfoValues : uint8_t {
-    FALSE = 20,
-    TRUE = 21,
-    NULL_V = 22,
-    ONE_BYTE_LENGTH = 24,
-    TWO_BYTE_LENGTH = 25,
-    FOUR_BYTE_LENGTH = 26,
-    EIGHT_BYTE_LENGTH = 27,
-};
-
-class Item;
-class Uint;
-class Nint;
-class Int;
-class Tstr;
-class Bstr;
-class Simple;
-class Bool;
-class Array;
-class Map;
-class Null;
-class Semantic;
-
-/**
- * Returns the size of a CBOR header that contains the additional info value addlInfo.
- */
-size_t headerSize(uint64_t addlInfo);
-
-/**
- * Encodes a CBOR header with the specified type and additional info into the range [pos, end).
- * Returns a pointer to one past the last byte written, or nullptr if there isn't sufficient space
- * to write the header.
- */
-uint8_t* encodeHeader(MajorType type, uint64_t addlInfo, uint8_t* pos, const uint8_t* end);
-
-using EncodeCallback = std::function<void(uint8_t)>;
-
-/**
- * Encodes a CBOR header with the specified type and additional info, passing each byte in turn to
- * encodeCallback.
- */
-void encodeHeader(MajorType type, uint64_t addlInfo, EncodeCallback encodeCallback);
-
-/**
- * Encodes a CBOR header with the specified type and additional info, writing each byte to the
- * provided OutputIterator.
- */
-template <typename OutputIterator,
-          typename = std::enable_if_t<std::is_base_of_v<
-                  std::output_iterator_tag,
-                  typename std::iterator_traits<OutputIterator>::iterator_category>>>
-void encodeHeader(MajorType type, uint64_t addlInfo, OutputIterator iter) {
-    return encodeHeader(type, addlInfo, [&](uint8_t v) { *iter++ = v; });
-}
-
-/**
- * Item represents a CBOR-encodeable data item.  Item is an abstract interface with a set of virtual
- * methods that allow encoding of the item or conversion to the appropriate derived type.
- */
-class Item {
-  public:
-    virtual ~Item() {}
-
-    /**
-     * Returns the CBOR type of the item.
-     */
-    virtual MajorType type() const = 0;
-
-    // These methods safely downcast an Item to the appropriate subclass.
-    virtual const Int* asInt() const { return nullptr; }
-    virtual const Uint* asUint() const { return nullptr; }
-    virtual const Nint* asNint() const { return nullptr; }
-    virtual const Tstr* asTstr() const { return nullptr; }
-    virtual const Bstr* asBstr() const { return nullptr; }
-    virtual const Simple* asSimple() const { return nullptr; }
-    virtual const Map* asMap() const { return nullptr; }
-    virtual const Array* asArray() const { return nullptr; }
-    virtual const Semantic* asSemantic() const { return nullptr; }
-
-    /**
-     * Returns true if this is a "compound" item, i.e. one that contains one or more other items.
-     */
-    virtual bool isCompound() const { return false; }
-
-    bool operator==(const Item& other) const&;
-    bool operator!=(const Item& other) const& { return !(*this == other); }
-
-    /**
-     * Returns the number of bytes required to encode this Item into CBOR.  Note that if this is a
-     * complex Item, calling this method will require walking the whole tree.
-     */
-    virtual size_t encodedSize() const = 0;
-
-    /**
-     * Encodes the Item into buffer referenced by range [*pos, end).  Returns a pointer to one past
-     * the last position written.  Returns nullptr if there isn't enough space to encode.
-     */
-    virtual uint8_t* encode(uint8_t* pos, const uint8_t* end) const = 0;
-
-    /**
-     * Encodes the Item by passing each encoded byte to encodeCallback.
-     */
-    virtual void encode(EncodeCallback encodeCallback) const = 0;
-
-    /**
-     * Clones the Item
-     */
-    virtual std::unique_ptr<Item> clone() const = 0;
-
-    /**
-     * Encodes the Item into the provided OutputIterator.
-     */
-    template <typename OutputIterator,
-              typename = typename std::iterator_traits<OutputIterator>::iterator_category>
-    void encode(OutputIterator i) const {
-        return encode([&](uint8_t v) { *i++ = v; });
-    }
-
-    /**
-     * Encodes the Item into a new std::vector<uint8_t>.
-     */
-    std::vector<uint8_t> encode() const {
-        std::vector<uint8_t> retval;
-        retval.reserve(encodedSize());
-        encode(std::back_inserter(retval));
-        return retval;
-    }
-
-    /**
-     * Encodes the Item into a new std::string.
-     */
-    std::string toString() const {
-        std::string retval;
-        retval.reserve(encodedSize());
-        encode([&](uint8_t v) { retval.push_back(v); });
-        return retval;
-    }
-
-    /**
-     * Encodes only the header of the Item.
-     */
-    inline uint8_t* encodeHeader(uint64_t addlInfo, uint8_t* pos, const uint8_t* end) const {
-        return ::cppbor::encodeHeader(type(), addlInfo, pos, end);
-    }
-
-    /**
-     * Encodes only the header of the Item.
-     */
-    inline void encodeHeader(uint64_t addlInfo, EncodeCallback encodeCallback) const {
-        ::cppbor::encodeHeader(type(), addlInfo, encodeCallback);
-    }
-};
-
-/**
- * Int is an abstraction that allows Uint and Nint objects to be manipulated without caring about
- * the sign.
- */
-class Int : public Item {
-  public:
-    bool operator==(const Int& other) const& { return value() == other.value(); }
-
-    virtual int64_t value() const = 0;
-
-    const Int* asInt() const override { return this; }
-};
-
-/**
- * Uint is a concrete Item that implements CBOR major type 0.
- */
-class Uint : public Int {
-  public:
-    static constexpr MajorType kMajorType = UINT;
-
-    explicit Uint(uint64_t v) : mValue(v) {}
-
-    bool operator==(const Uint& other) const& { return mValue == other.mValue; }
-
-    MajorType type() const override { return kMajorType; }
-    const Uint* asUint() const override { return this; }
-
-    size_t encodedSize() const override { return headerSize(mValue); }
-
-    int64_t value() const override { return mValue; }
-    uint64_t unsignedValue() const { return mValue; }
-
-    using Item::encode;
-    uint8_t* encode(uint8_t* pos, const uint8_t* end) const override {
-        return encodeHeader(mValue, pos, end);
-    }
-    void encode(EncodeCallback encodeCallback) const override {
-        encodeHeader(mValue, encodeCallback);
-    }
-
-    virtual std::unique_ptr<Item> clone() const override { return std::make_unique<Uint>(mValue); }
-
-  private:
-    uint64_t mValue;
-};
-
-/**
- * Nint is a concrete Item that implements CBOR major type 1.
-
- * Note that it is incapable of expressing the full range of major type 1 values, becaue it can only
- * express values that fall into the range [std::numeric_limits<int64_t>::min(), -1].  It cannot
- * express values in the range [std::numeric_limits<int64_t>::min() - 1,
- * -std::numeric_limits<uint64_t>::max()].
- */
-class Nint : public Int {
-  public:
-    static constexpr MajorType kMajorType = NINT;
-
-    explicit Nint(int64_t v);
-
-    bool operator==(const Nint& other) const& { return mValue == other.mValue; }
-
-    MajorType type() const override { return kMajorType; }
-    const Nint* asNint() const override { return this; }
-    size_t encodedSize() const override { return headerSize(addlInfo()); }
-
-    int64_t value() const override { return mValue; }
-
-    using Item::encode;
-    uint8_t* encode(uint8_t* pos, const uint8_t* end) const override {
-        return encodeHeader(addlInfo(), pos, end);
-    }
-    void encode(EncodeCallback encodeCallback) const override {
-        encodeHeader(addlInfo(), encodeCallback);
-    }
-
-    virtual std::unique_ptr<Item> clone() const override { return std::make_unique<Nint>(mValue); }
-
-  private:
-    uint64_t addlInfo() const { return -1LL - mValue; }
-
-    int64_t mValue;
-};
-
-/**
- * Bstr is a concrete Item that implements major type 2.
- */
-class Bstr : public Item {
-  public:
-    static constexpr MajorType kMajorType = BSTR;
-
-    // Construct from a vector
-    explicit Bstr(std::vector<uint8_t> v) : mValue(std::move(v)) {}
-
-    // Construct from a string
-    explicit Bstr(const std::string& v)
-        : mValue(reinterpret_cast<const uint8_t*>(v.data()),
-                 reinterpret_cast<const uint8_t*>(v.data()) + v.size()) {}
-
-    // Construct from a pointer/size pair
-    explicit Bstr(const std::pair<const uint8_t*, size_t>& buf)
-        : mValue(buf.first, buf.first + buf.second) {}
-
-    // Construct from a pair of iterators
-    template <typename I1, typename I2,
-              typename = typename std::iterator_traits<I1>::iterator_category,
-              typename = typename std::iterator_traits<I2>::iterator_category>
-    explicit Bstr(const std::pair<I1, I2>& pair) : mValue(pair.first, pair.second) {}
-
-    // Construct from an iterator range.
-    template <typename I1, typename I2,
-              typename = typename std::iterator_traits<I1>::iterator_category,
-              typename = typename std::iterator_traits<I2>::iterator_category>
-    Bstr(I1 begin, I2 end) : mValue(begin, end) {}
-
-    bool operator==(const Bstr& other) const& { return mValue == other.mValue; }
-
-    MajorType type() const override { return kMajorType; }
-    const Bstr* asBstr() const override { return this; }
-    size_t encodedSize() const override { return headerSize(mValue.size()) + mValue.size(); }
-    using Item::encode;
-    uint8_t* encode(uint8_t* pos, const uint8_t* end) const override;
-    void encode(EncodeCallback encodeCallback) const override {
-        encodeHeader(mValue.size(), encodeCallback);
-        encodeValue(encodeCallback);
-    }
-
-    const std::vector<uint8_t>& value() const { return mValue; }
-
-    virtual std::unique_ptr<Item> clone() const override { return std::make_unique<Bstr>(mValue); }
-
-  private:
-    void encodeValue(EncodeCallback encodeCallback) const;
-
-    std::vector<uint8_t> mValue;
-};
-
-/**
- * Bstr is a concrete Item that implements major type 3.
- */
-class Tstr : public Item {
-  public:
-    static constexpr MajorType kMajorType = TSTR;
-
-    // Construct from a string
-    explicit Tstr(std::string v) : mValue(std::move(v)) {}
-
-    // Construct from a string_view
-    explicit Tstr(const std::string_view& v) : mValue(v) {}
-
-    // Construct from a C string
-    explicit Tstr(const char* v) : mValue(std::string(v)) {}
-
-    // Construct from a pair of iterators
-    template <typename I1, typename I2,
-              typename = typename std::iterator_traits<I1>::iterator_category,
-              typename = typename std::iterator_traits<I2>::iterator_category>
-    explicit Tstr(const std::pair<I1, I2>& pair) : mValue(pair.first, pair.second) {}
-
-    // Construct from an iterator range
-    template <typename I1, typename I2,
-              typename = typename std::iterator_traits<I1>::iterator_category,
-              typename = typename std::iterator_traits<I2>::iterator_category>
-    Tstr(I1 begin, I2 end) : mValue(begin, end) {}
-
-    bool operator==(const Tstr& other) const& { return mValue == other.mValue; }
-
-    MajorType type() const override { return kMajorType; }
-    const Tstr* asTstr() const override { return this; }
-    size_t encodedSize() const override { return headerSize(mValue.size()) + mValue.size(); }
-    using Item::encode;
-    uint8_t* encode(uint8_t* pos, const uint8_t* end) const override;
-    void encode(EncodeCallback encodeCallback) const override {
-        encodeHeader(mValue.size(), encodeCallback);
-        encodeValue(encodeCallback);
-    }
-
-    const std::string& value() const { return mValue; }
-
-    virtual std::unique_ptr<Item> clone() const override { return std::make_unique<Tstr>(mValue); }
-
-  private:
-    void encodeValue(EncodeCallback encodeCallback) const;
-
-    std::string mValue;
-};
-
-/**
- * CompoundItem is an abstract Item that provides common functionality for Items that contain other
- * items, i.e. Arrays (CBOR type 4) and Maps (CBOR type 5).
- */
-class CompoundItem : public Item {
-  public:
-    bool operator==(const CompoundItem& other) const&;
-
-    virtual size_t size() const { return mEntries.size(); }
-
-    bool isCompound() const override { return true; }
-
-    size_t encodedSize() const override {
-        return std::accumulate(mEntries.begin(), mEntries.end(), headerSize(size()),
-                               [](size_t sum, auto& entry) { return sum + entry->encodedSize(); });
-    }
-
-    using Item::encode;  // Make base versions visible.
-    uint8_t* encode(uint8_t* pos, const uint8_t* end) const override;
-    void encode(EncodeCallback encodeCallback) const override;
-
-    virtual uint64_t addlInfo() const = 0;
-
-  protected:
-    std::vector<std::unique_ptr<Item>> mEntries;
-};
-
-/*
- * Array is a concrete Item that implements CBOR major type 4.
- *
- * Note that Arrays are not copyable.  This is because copying them is expensive and making them
- * move-only ensures that they're never copied accidentally.  If you actually want to copy an Array,
- * use the clone() method.
- */
-class Array : public CompoundItem {
-  public:
-    static constexpr MajorType kMajorType = ARRAY;
-
-    Array() = default;
-    Array(const Array& other) = delete;
-    Array(Array&&) = default;
-    Array& operator=(const Array&) = delete;
-    Array& operator=(Array&&) = default;
-
-    /**
-     * Construct an Array from a variable number of arguments of different types.  See
-     * details::makeItem below for details on what types may be provided.  In general, this accepts
-     * all of the types you'd expect and doest the things you'd expect (integral values are addes as
-     * Uint or Nint, std::string and char* are added as Tstr, bools are added as Bool, etc.).
-     */
-    template <typename... Args, typename Enable>
-    Array(Args&&... args);
-
-    /**
-     * Append a single element to the Array, of any compatible type.
-     */
-    template <typename T>
-    Array& add(T&& v) &;
-    template <typename T>
-    Array&& add(T&& v) &&;
-
-    const std::unique_ptr<Item>& operator[](size_t index) const { return mEntries[index]; }
-    std::unique_ptr<Item>& operator[](size_t index) { return mEntries[index]; }
-
-    MajorType type() const override { return kMajorType; }
-    const Array* asArray() const override { return this; }
-
-    virtual std::unique_ptr<Item> clone() const override;
-
-    uint64_t addlInfo() const override { return size(); }
-};
-
-/*
- * Map is a concrete Item that implements CBOR major type 5.
- *
- * Note that Maps are not copyable.  This is because copying them is expensive and making them
- * move-only ensures that they're never copied accidentally.  If you actually want to copy a
- * Map, use the clone() method.
- */
-class Map : public CompoundItem {
-  public:
-    static constexpr MajorType kMajorType = MAP;
-
-    Map() = default;
-    Map(const Map& other) = delete;
-    Map(Map&&) = default;
-    Map& operator=(const Map& other) = delete;
-    Map& operator=(Map&&) = default;
-
-    /**
-     * Construct a Map from a variable number of arguments of different types.  An even number of
-     * arguments must be provided (this is verified statically). See details::makeItem below for
-     * details on what types may be provided.  In general, this accepts all of the types you'd
-     * expect and doest the things you'd expect (integral values are addes as Uint or Nint,
-     * std::string and char* are added as Tstr, bools are added as Bool, etc.).
-     */
-    template <typename... Args, typename Enable>
-    Map(Args&&... args);
-
-    /**
-     * Append a key/value pair to the Map, of any compatible types.
-     */
-    template <typename Key, typename Value>
-    Map& add(Key&& key, Value&& value) &;
-    template <typename Key, typename Value>
-    Map&& add(Key&& key, Value&& value) &&;
-
-    size_t size() const override {
-        assertInvariant();
-        return mEntries.size() / 2;
-    }
-
-    template <typename Key, typename Enable>
-    std::pair<std::unique_ptr<Item>&, bool> get(Key key);
-
-    std::pair<const std::unique_ptr<Item>&, const std::unique_ptr<Item>&> operator[](
-            size_t index) const {
-        assertInvariant();
-        return {mEntries[index * 2], mEntries[index * 2 + 1]};
-    }
-
-    std::pair<std::unique_ptr<Item>&, std::unique_ptr<Item>&> operator[](size_t index) {
-        assertInvariant();
-        return {mEntries[index * 2], mEntries[index * 2 + 1]};
-    }
-
-    MajorType type() const override { return kMajorType; }
-    const Map* asMap() const override { return this; }
-
-    virtual std::unique_ptr<Item> clone() const override;
-
-    uint64_t addlInfo() const override { return size(); }
-
-  private:
-    void assertInvariant() const;
-};
-
-class Semantic : public CompoundItem {
-  public:
-    static constexpr MajorType kMajorType = SEMANTIC;
-
-    template <typename T>
-    explicit Semantic(uint64_t value, T&& child);
-
-    Semantic(const Semantic& other) = delete;
-    Semantic(Semantic&&) = default;
-    Semantic& operator=(const Semantic& other) = delete;
-    Semantic& operator=(Semantic&&) = default;
-
-    size_t size() const override {
-        assertInvariant();
-        return 1;
-    }
-
-    size_t encodedSize() const override {
-        return std::accumulate(mEntries.begin(), mEntries.end(), headerSize(mValue),
-                               [](size_t sum, auto& entry) { return sum + entry->encodedSize(); });
-    }
-
-    MajorType type() const override { return kMajorType; }
-    const Semantic* asSemantic() const override { return this; }
-
-    const std::unique_ptr<Item>& child() const {
-        assertInvariant();
-        return mEntries[0];
-    }
-
-    std::unique_ptr<Item>& child() {
-        assertInvariant();
-        return mEntries[0];
-    }
-
-    uint64_t value() const { return mValue; }
-
-    uint64_t addlInfo() const override { return value(); }
-
-    virtual std::unique_ptr<Item> clone() const override {
-        assertInvariant();
-        return std::make_unique<Semantic>(mValue, mEntries[0]->clone());
-    }
-
-  protected:
-    Semantic() = default;
-    Semantic(uint64_t value) : mValue(value) {}
-    uint64_t mValue;
-
-  private:
-    void assertInvariant() const;
-};
-
-/**
- * Simple is abstract Item that implements CBOR major type 7.  It is intended to be subclassed to
- * create concrete Simple types.  At present only Bool is provided.
- */
-class Simple : public Item {
-  public:
-    static constexpr MajorType kMajorType = SIMPLE;
-
-    bool operator==(const Simple& other) const&;
-
-    virtual SimpleType simpleType() const = 0;
-    MajorType type() const override { return kMajorType; }
-
-    const Simple* asSimple() const override { return this; }
-
-    virtual const Bool* asBool() const { return nullptr; };
-    virtual const Null* asNull() const { return nullptr; };
-};
-
-/**
- * Bool is a concrete type that implements CBOR major type 7, with additional item values for TRUE
- * and FALSE.
- */
-class Bool : public Simple {
-  public:
-    static constexpr SimpleType kSimpleType = BOOLEAN;
-
-    explicit Bool(bool v) : mValue(v) {}
-
-    bool operator==(const Bool& other) const& { return mValue == other.mValue; }
-
-    SimpleType simpleType() const override { return kSimpleType; }
-    const Bool* asBool() const override { return this; }
-
-    size_t encodedSize() const override { return 1; }
-
-    using Item::encode;
-    uint8_t* encode(uint8_t* pos, const uint8_t* end) const override {
-        return encodeHeader(mValue ? TRUE : FALSE, pos, end);
-    }
-    void encode(EncodeCallback encodeCallback) const override {
-        encodeHeader(mValue ? TRUE : FALSE, encodeCallback);
-    }
-
-    bool value() const { return mValue; }
-
-    virtual std::unique_ptr<Item> clone() const override { return std::make_unique<Bool>(mValue); }
-
-  private:
-    bool mValue;
-};
-
-/**
- * Null is a concrete type that implements CBOR major type 7, with additional item value for NULL
- */
-class Null : public Simple {
-  public:
-    static constexpr SimpleType kSimpleType = NULL_T;
-
-    explicit Null() {}
-
-    SimpleType simpleType() const override { return kSimpleType; }
-    const Null* asNull() const override { return this; }
-
-    size_t encodedSize() const override { return 1; }
-
-    using Item::encode;
-    uint8_t* encode(uint8_t* pos, const uint8_t* end) const override {
-        return encodeHeader(NULL_V, pos, end);
-    }
-    void encode(EncodeCallback encodeCallback) const override {
-        encodeHeader(NULL_V, encodeCallback);
-    }
-
-    virtual std::unique_ptr<Item> clone() const override { return std::make_unique<Null>(); }
-};
-
-template <typename T>
-std::unique_ptr<T> downcastItem(std::unique_ptr<Item>&& v) {
-    static_assert(std::is_base_of_v<Item, T> && !std::is_abstract_v<T>,
-                  "returned type is not an Item or is an abstract class");
-    if (v && T::kMajorType == v->type()) {
-        if constexpr (std::is_base_of_v<Simple, T>) {
-            if (T::kSimpleType != v->asSimple()->simpleType()) {
-                return nullptr;
-            }
-        }
-        return std::unique_ptr<T>(static_cast<T*>(v.release()));
-    } else {
-        return nullptr;
-    }
-}
-
-/**
- * Details. Mostly you shouldn't have to look below, except perhaps at the docstring for makeItem.
- */
-namespace details {
-
-template <typename T, typename V, typename Enable = void>
-struct is_iterator_pair_over : public std::false_type {};
-
-template <typename I1, typename I2, typename V>
-struct is_iterator_pair_over<
-        std::pair<I1, I2>, V,
-        typename std::enable_if_t<std::is_same_v<V, typename std::iterator_traits<I1>::value_type>>>
-    : public std::true_type {};
-
-template <typename T, typename V, typename Enable = void>
-struct is_unique_ptr_of_subclass_of_v : public std::false_type {};
-
-template <typename T, typename P>
-struct is_unique_ptr_of_subclass_of_v<T, std::unique_ptr<P>,
-                                      typename std::enable_if_t<std::is_base_of_v<T, P>>>
-    : public std::true_type {};
-
-/* check if type is one of std::string (1), std::string_view (2), null-terminated char* (3) or pair
- *     of iterators (4)*/
-template <typename T, typename Enable = void>
-struct is_text_type_v : public std::false_type {};
-
-template <typename T>
-struct is_text_type_v<
-        T, typename std::enable_if_t<
-                   /* case 1 */  //
-                   std::is_same_v<std::remove_cv_t<std::remove_reference_t<T>>, std::string>
-                   /* case 2 */  //
-                   || std::is_same_v<std::remove_cv_t<std::remove_reference_t<T>>, std::string_view>
-                   /* case 3 */                                                 //
-                   || std::is_same_v<std::remove_cv_t<std::decay_t<T>>, char*>  //
-                   || std::is_same_v<std::remove_cv_t<std::decay_t<T>>, const char*>
-                   /* case 4 */
-                   || details::is_iterator_pair_over<T, char>::value>> : public std::true_type {};
-
-/**
- * Construct a unique_ptr<Item> from many argument types. Accepts:
- *
- * (a) booleans;
- * (b) integers, all sizes and signs;
- * (c) text strings, as defined by is_text_type_v above;
- * (d) byte strings, as std::vector<uint8_t>(d1), pair of iterators (d2) or pair<uint8_t*, size_T>
- *     (d3); and
- * (e) Item subclass instances, including Array and Map.  Items may be provided by naked pointer
- *     (e1), unique_ptr (e2), reference (e3) or value (e3).  If provided by reference or value, will
- *     be moved if possible.  If provided by pointer, ownership is taken.
- * (f) null pointer;
- */
-template <typename T>
-std::unique_ptr<Item> makeItem(T v) {
-    Item* p = nullptr;
-    if constexpr (/* case a */ std::is_same_v<T, bool>) {
-        p = new Bool(v);
-    } else if constexpr (/* case b */ std::is_integral_v<T>) {  // b
-        if (v < 0) {
-            p = new Nint(v);
-        } else {
-            p = new Uint(static_cast<uint64_t>(v));
-        }
-    } else if constexpr (/* case c */  //
-                         details::is_text_type_v<T>::value) {
-        p = new Tstr(v);
-    } else if constexpr (/* case d1 */  //
-                         std::is_same_v<std::remove_cv_t<std::remove_reference_t<T>>,
-                                        std::vector<uint8_t>>
-                         /* case d2 */  //
-                         || details::is_iterator_pair_over<T, uint8_t>::value
-                         /* case d3 */  //
-                         || std::is_same_v<std::remove_cv_t<std::remove_reference_t<T>>,
-                                           std::pair<uint8_t*, size_t>>) {
-        p = new Bstr(v);
-    } else if constexpr (/* case e1 */  //
-                         std::is_pointer_v<T> &&
-                         std::is_base_of_v<Item, std::remove_pointer_t<T>>) {
-        p = v;
-    } else if constexpr (/* case e2 */  //
-                         details::is_unique_ptr_of_subclass_of_v<Item, T>::value) {
-        p = v.release();
-    } else if constexpr (/* case e3 */  //
-                         std::is_base_of_v<Item, T>) {
-        p = new T(std::move(v));
-    } else if constexpr (/* case f */ std::is_null_pointer_v<T>) {
-        p = new Null();
-    } else {
-        // It's odd that this can't be static_assert(false), since it shouldn't be evaluated if one
-        // of the above ifs matches.  But static_assert(false) always triggers.
-        static_assert(std::is_same_v<T, bool>, "makeItem called with unsupported type");
-    }
-    return std::unique_ptr<Item>(p);
-}
-
-}  // namespace details
-
-template <typename... Args,
-          /* Prevent use as copy ctor */ typename = std::enable_if_t<
-                  (sizeof...(Args)) != 1 ||
-                  !(std::is_same_v<Array, std::remove_cv_t<std::remove_reference_t<Args>>> || ...)>>
-Array::Array(Args&&... args) {
-    mEntries.reserve(sizeof...(args));
-    (mEntries.push_back(details::makeItem(std::forward<Args>(args))), ...);
-}
-
-template <typename T>
-Array& Array::add(T&& v) & {
-    mEntries.push_back(details::makeItem(std::forward<T>(v)));
-    return *this;
-}
-
-template <typename T>
-Array&& Array::add(T&& v) && {
-    mEntries.push_back(details::makeItem(std::forward<T>(v)));
-    return std::move(*this);
-}
-
-template <typename... Args,
-          /* Prevent use as copy ctor */ typename = std::enable_if_t<(sizeof...(Args)) != 1>>
-Map::Map(Args&&... args) {
-    static_assert((sizeof...(Args)) % 2 == 0, "Map must have an even number of entries");
-    mEntries.reserve(sizeof...(args));
-    (mEntries.push_back(details::makeItem(std::forward<Args>(args))), ...);
-}
-
-template <typename Key, typename Value>
-Map& Map::add(Key&& key, Value&& value) & {
-    mEntries.push_back(details::makeItem(std::forward<Key>(key)));
-    mEntries.push_back(details::makeItem(std::forward<Value>(value)));
-    return *this;
-}
-
-template <typename Key, typename Value>
-Map&& Map::add(Key&& key, Value&& value) && {
-    this->add(std::forward<Key>(key), std::forward<Value>(value));
-    return std::move(*this);
-}
-
-template <typename Key, typename = std::enable_if_t<std::is_integral_v<Key> ||
-                                                    details::is_text_type_v<Key>::value>>
-std::pair<std::unique_ptr<Item>&, bool> Map::get(Key key) {
-    assertInvariant();
-    auto keyItem = details::makeItem(key);
-    for (size_t i = 0; i < mEntries.size(); i += 2) {
-        if (*keyItem == *mEntries[i]) {
-            return {mEntries[i + 1], true};
-        }
-    }
-    return {keyItem, false};
-}
-
-template <typename T>
-Semantic::Semantic(uint64_t value, T&& child) : mValue(value) {
-    mEntries.reserve(1);
-    mEntries.push_back(details::makeItem(std::forward<T>(child)));
-}
-
-}  // namespace cppbor
diff --git a/identity/support/include/cppbor/cppbor_parse.h b/identity/support/include/cppbor/cppbor_parse.h
deleted file mode 100644
index 66cd5a3..0000000
--- a/identity/support/include/cppbor/cppbor_parse.h
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright (c) 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 "cppbor.h"
-
-namespace cppbor {
-
-using ParseResult = std::tuple<std::unique_ptr<Item> /* result */, const uint8_t* /* newPos */,
-                               std::string /* errMsg */>;
-
-/**
- * Parse the first CBOR data item (possibly compound) from the range [begin, end).
- *
- * Returns a tuple of Item pointer, buffer pointer and error message.  If parsing is successful, the
- * Item pointer is non-null, the buffer pointer points to the first byte after the
- * successfully-parsed item and the error message string is empty.  If parsing fails, the Item
- * pointer is null, the buffer pointer points to the first byte that was unparseable (the first byte
- * of a data item header that is malformed in some way, e.g. an invalid value, or a length that is
- * too large for the remining buffer, etc.) and the string contains an error message describing the
- * problem encountered.
- */
-ParseResult parse(const uint8_t* begin, const uint8_t* end);
-
-/**
- * Parse the first CBOR data item (possibly compound) from the byte vector.
- *
- * Returns a tuple of Item pointer, buffer pointer and error message.  If parsing is successful, the
- * Item pointer is non-null, the buffer pointer points to the first byte after the
- * successfully-parsed item and the error message string is empty.  If parsing fails, the Item
- * pointer is null, the buffer pointer points to the first byte that was unparseable (the first byte
- * of a data item header that is malformed in some way, e.g. an invalid value, or a length that is
- * too large for the remining buffer, etc.) and the string contains an error message describing the
- * problem encountered.
- */
-inline ParseResult parse(const std::vector<uint8_t>& encoding) {
-    return parse(encoding.data(), encoding.data() + encoding.size());
-}
-
-/**
- * Parse the first CBOR data item (possibly compound) from the range [begin, begin + size).
- *
- * Returns a tuple of Item pointer, buffer pointer and error message.  If parsing is successful, the
- * Item pointer is non-null, the buffer pointer points to the first byte after the
- * successfully-parsed item and the error message string is empty.  If parsing fails, the Item
- * pointer is null, the buffer pointer points to the first byte that was unparseable (the first byte
- * of a data item header that is malformed in some way, e.g. an invalid value, or a length that is
- * too large for the remining buffer, etc.) and the string contains an error message describing the
- * problem encountered.
- */
-inline ParseResult parse(const uint8_t* begin, size_t size) {
-    return parse(begin, begin + size);
-}
-
-class ParseClient;
-
-/**
- * Parse the CBOR data in the range [begin, end) in streaming fashion, calling methods on the
- * provided ParseClient when elements are found.
- */
-void parse(const uint8_t* begin, const uint8_t* end, ParseClient* parseClient);
-
-/**
- * Parse the CBOR data in the vector in streaming fashion, calling methods on the
- * provided ParseClient when elements are found.
- */
-inline void parse(const std::vector<uint8_t>& encoding, ParseClient* parseClient) {
-    return parse(encoding.data(), encoding.data() + encoding.size(), parseClient);
-}
-
-/**
- * A pure interface that callers of the streaming parse functions must implement.
- */
-class ParseClient {
-  public:
-    virtual ~ParseClient() {}
-
-    /**
-     * Called when an item is found.  The Item pointer points to the found item; use type() and
-     * the appropriate as*() method to examine the value.  hdrBegin points to the first byte of the
-     * header, valueBegin points to the first byte of the value and end points one past the end of
-     * the item.  In the case of header-only items, such as integers, and compound items (ARRAY,
-     * MAP or SEMANTIC) whose end has not yet been found, valueBegin and end are equal and point to
-     * the byte past the header.
-     *
-     * Note that for compound types (ARRAY, MAP, and SEMANTIC), the Item will have no content.  For
-     * Map and Array items, the size() method will return a correct value, but the index operators
-     * are unsafe, and the object cannot be safely compared with another Array/Map.
-     *
-     * The method returns a ParseClient*.  In most cases "return this;" will be the right answer,
-     * but a different ParseClient may be returned, which the parser will begin using. If the method
-     * returns nullptr, parsing will be aborted immediately.
-     */
-    virtual ParseClient* item(std::unique_ptr<Item>& item, const uint8_t* hdrBegin,
-                              const uint8_t* valueBegin, const uint8_t* end) = 0;
-
-    /**
-     * Called when the end of a compound item (MAP or ARRAY) is found.  The item argument will be
-     * the same one passed to the item() call -- and may be empty if item() moved its value out.
-     * hdrBegin, valueBegin and end point to the beginning of the item header, the beginning of the
-     * first contained value, and one past the end of the last contained value, respectively.
-     *
-     * Note that the Item will have no content.
-     *
-     * As with item(), itemEnd() can change the ParseClient by returning a different one, or end the
-     * parsing by returning nullptr;
-     */
-    virtual ParseClient* itemEnd(std::unique_ptr<Item>& item, const uint8_t* hdrBegin,
-                                 const uint8_t* valueBegin, const uint8_t* end) = 0;
-
-    /**
-     * Called when parsing encounters an error.  position is set to the first unparsed byte (one
-     * past the last successfully-parsed byte) and errorMessage contains an message explaining what
-     * sort of error occurred.
-     */
-    virtual void error(const uint8_t* position, const std::string& errorMessage) = 0;
-};
-
-}  // namespace cppbor
diff --git a/identity/support/src/cppbor.cpp b/identity/support/src/cppbor.cpp
deleted file mode 100644
index d289985..0000000
--- a/identity/support/src/cppbor.cpp
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * Copyright (c) 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 "cppbor.h"
-#include "cppbor_parse.h"
-
-#define LOG_TAG "CppBor"
-#include <android-base/logging.h>
-
-namespace cppbor {
-
-namespace {
-
-template <typename T, typename Iterator, typename = std::enable_if<std::is_unsigned<T>::value>>
-Iterator writeBigEndian(T value, Iterator pos) {
-    for (unsigned i = 0; i < sizeof(value); ++i) {
-        *pos++ = static_cast<uint8_t>(value >> (8 * (sizeof(value) - 1)));
-        value = static_cast<T>(value << 8);
-    }
-    return pos;
-}
-
-template <typename T, typename = std::enable_if<std::is_unsigned<T>::value>>
-void writeBigEndian(T value, std::function<void(uint8_t)>& cb) {
-    for (unsigned i = 0; i < sizeof(value); ++i) {
-        cb(static_cast<uint8_t>(value >> (8 * (sizeof(value) - 1))));
-        value = static_cast<T>(value << 8);
-    }
-}
-
-}  // namespace
-
-size_t headerSize(uint64_t addlInfo) {
-    if (addlInfo < ONE_BYTE_LENGTH) return 1;
-    if (addlInfo <= std::numeric_limits<uint8_t>::max()) return 2;
-    if (addlInfo <= std::numeric_limits<uint16_t>::max()) return 3;
-    if (addlInfo <= std::numeric_limits<uint32_t>::max()) return 5;
-    return 9;
-}
-
-uint8_t* encodeHeader(MajorType type, uint64_t addlInfo, uint8_t* pos, const uint8_t* end) {
-    size_t sz = headerSize(addlInfo);
-    if (end - pos < static_cast<ssize_t>(sz)) return nullptr;
-    switch (sz) {
-        case 1:
-            *pos++ = type | static_cast<uint8_t>(addlInfo);
-            return pos;
-        case 2:
-            *pos++ = type | ONE_BYTE_LENGTH;
-            *pos++ = static_cast<uint8_t>(addlInfo);
-            return pos;
-        case 3:
-            *pos++ = type | TWO_BYTE_LENGTH;
-            return writeBigEndian(static_cast<uint16_t>(addlInfo), pos);
-        case 5:
-            *pos++ = type | FOUR_BYTE_LENGTH;
-            return writeBigEndian(static_cast<uint32_t>(addlInfo), pos);
-        case 9:
-            *pos++ = type | EIGHT_BYTE_LENGTH;
-            return writeBigEndian(addlInfo, pos);
-        default:
-            CHECK(false);  // Impossible to get here.
-            return nullptr;
-    }
-}
-
-void encodeHeader(MajorType type, uint64_t addlInfo, EncodeCallback encodeCallback) {
-    size_t sz = headerSize(addlInfo);
-    switch (sz) {
-        case 1:
-            encodeCallback(type | static_cast<uint8_t>(addlInfo));
-            break;
-        case 2:
-            encodeCallback(type | ONE_BYTE_LENGTH);
-            encodeCallback(static_cast<uint8_t>(addlInfo));
-            break;
-        case 3:
-            encodeCallback(type | TWO_BYTE_LENGTH);
-            writeBigEndian(static_cast<uint16_t>(addlInfo), encodeCallback);
-            break;
-        case 5:
-            encodeCallback(type | FOUR_BYTE_LENGTH);
-            writeBigEndian(static_cast<uint32_t>(addlInfo), encodeCallback);
-            break;
-        case 9:
-            encodeCallback(type | EIGHT_BYTE_LENGTH);
-            writeBigEndian(addlInfo, encodeCallback);
-            break;
-        default:
-            CHECK(false);  // Impossible to get here.
-    }
-}
-
-bool Item::operator==(const Item& other) const& {
-    if (type() != other.type()) return false;
-    switch (type()) {
-        case UINT:
-            return *asUint() == *(other.asUint());
-        case NINT:
-            return *asNint() == *(other.asNint());
-        case BSTR:
-            return *asBstr() == *(other.asBstr());
-        case TSTR:
-            return *asTstr() == *(other.asTstr());
-        case ARRAY:
-            return *asArray() == *(other.asArray());
-        case MAP:
-            return *asMap() == *(other.asMap());
-        case SIMPLE:
-            return *asSimple() == *(other.asSimple());
-        case SEMANTIC:
-            return *asSemantic() == *(other.asSemantic());
-        default:
-            CHECK(false);  // Impossible to get here.
-            return false;
-    }
-}
-
-Nint::Nint(int64_t v) : mValue(v) {
-    CHECK(v < 0) << "Only negative values allowed";
-}
-
-bool Simple::operator==(const Simple& other) const& {
-    if (simpleType() != other.simpleType()) return false;
-
-    switch (simpleType()) {
-        case BOOLEAN:
-            return *asBool() == *(other.asBool());
-        case NULL_T:
-            return true;
-        default:
-            CHECK(false);  // Impossible to get here.
-            return false;
-    }
-}
-
-uint8_t* Bstr::encode(uint8_t* pos, const uint8_t* end) const {
-    pos = encodeHeader(mValue.size(), pos, end);
-    if (!pos || end - pos < static_cast<ptrdiff_t>(mValue.size())) return nullptr;
-    return std::copy(mValue.begin(), mValue.end(), pos);
-}
-
-void Bstr::encodeValue(EncodeCallback encodeCallback) const {
-    for (auto c : mValue) {
-        encodeCallback(c);
-    }
-}
-
-uint8_t* Tstr::encode(uint8_t* pos, const uint8_t* end) const {
-    pos = encodeHeader(mValue.size(), pos, end);
-    if (!pos || end - pos < static_cast<ptrdiff_t>(mValue.size())) return nullptr;
-    return std::copy(mValue.begin(), mValue.end(), pos);
-}
-
-void Tstr::encodeValue(EncodeCallback encodeCallback) const {
-    for (auto c : mValue) {
-        encodeCallback(static_cast<uint8_t>(c));
-    }
-}
-
-bool CompoundItem::operator==(const CompoundItem& other) const& {
-    return type() == other.type()             //
-           && addlInfo() == other.addlInfo()  //
-           // Can't use vector::operator== because the contents are pointers.  std::equal lets us
-           // provide a predicate that does the dereferencing.
-           && std::equal(mEntries.begin(), mEntries.end(), other.mEntries.begin(),
-                         [](auto& a, auto& b) -> bool { return *a == *b; });
-}
-
-uint8_t* CompoundItem::encode(uint8_t* pos, const uint8_t* end) const {
-    pos = encodeHeader(addlInfo(), pos, end);
-    if (!pos) return nullptr;
-    for (auto& entry : mEntries) {
-        pos = entry->encode(pos, end);
-        if (!pos) return nullptr;
-    }
-    return pos;
-}
-
-void CompoundItem::encode(EncodeCallback encodeCallback) const {
-    encodeHeader(addlInfo(), encodeCallback);
-    for (auto& entry : mEntries) {
-        entry->encode(encodeCallback);
-    }
-}
-
-void Map::assertInvariant() const {
-    CHECK(mEntries.size() % 2 == 0);
-}
-
-std::unique_ptr<Item> Map::clone() const {
-    assertInvariant();
-    auto res = std::make_unique<Map>();
-    for (size_t i = 0; i < mEntries.size(); i += 2) {
-        res->add(mEntries[i]->clone(), mEntries[i + 1]->clone());
-    }
-    return res;
-}
-
-std::unique_ptr<Item> Array::clone() const {
-    auto res = std::make_unique<Array>();
-    for (size_t i = 0; i < mEntries.size(); i++) {
-        res->add(mEntries[i]->clone());
-    }
-    return res;
-}
-
-void Semantic::assertInvariant() const {
-    CHECK(mEntries.size() == 1);
-}
-
-}  // namespace cppbor
diff --git a/identity/support/src/cppbor_parse.cpp b/identity/support/src/cppbor_parse.cpp
deleted file mode 100644
index c9ebb8a..0000000
--- a/identity/support/src/cppbor_parse.cpp
+++ /dev/null
@@ -1,351 +0,0 @@
-/*
- * Copyright (c) 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 "cppbor_parse.h"
-
-#include <sstream>
-#include <stack>
-
-#define LOG_TAG "CppBor"
-#include <android-base/logging.h>
-
-namespace cppbor {
-
-namespace {
-
-std::string insufficientLengthString(size_t bytesNeeded, size_t bytesAvail,
-                                     const std::string& type) {
-    std::stringstream errStream;
-    errStream << "Need " << bytesNeeded << " byte(s) for " << type << ", have " << bytesAvail
-              << ".";
-    return errStream.str();
-}
-
-template <typename T, typename = std::enable_if_t<std::is_unsigned_v<T>>>
-std::tuple<bool, uint64_t, const uint8_t*> parseLength(const uint8_t* pos, const uint8_t* end,
-                                                       ParseClient* parseClient) {
-    if (pos + sizeof(T) > end) {
-        parseClient->error(pos - 1, insufficientLengthString(sizeof(T), end - pos, "length field"));
-        return {false, 0, pos};
-    }
-
-    const uint8_t* intEnd = pos + sizeof(T);
-    T result = 0;
-    do {
-        result = static_cast<T>((result << 8) | *pos++);
-    } while (pos < intEnd);
-    return {true, result, pos};
-}
-
-std::tuple<const uint8_t*, ParseClient*> parseRecursively(const uint8_t* begin, const uint8_t* end,
-                                                          ParseClient* parseClient);
-
-std::tuple<const uint8_t*, ParseClient*> handleUint(uint64_t value, const uint8_t* hdrBegin,
-                                                    const uint8_t* hdrEnd,
-                                                    ParseClient* parseClient) {
-    std::unique_ptr<Item> item = std::make_unique<Uint>(value);
-    return {hdrEnd,
-            parseClient->item(item, hdrBegin, hdrEnd /* valueBegin */, hdrEnd /* itemEnd */)};
-}
-
-std::tuple<const uint8_t*, ParseClient*> handleNint(uint64_t value, const uint8_t* hdrBegin,
-                                                    const uint8_t* hdrEnd,
-                                                    ParseClient* parseClient) {
-    if (value > std::numeric_limits<int64_t>::max()) {
-        parseClient->error(hdrBegin, "NINT values that don't fit in int64_t are not supported.");
-        return {hdrBegin, nullptr /* end parsing */};
-    }
-    std::unique_ptr<Item> item = std::make_unique<Nint>(-1 - static_cast<uint64_t>(value));
-    return {hdrEnd,
-            parseClient->item(item, hdrBegin, hdrEnd /* valueBegin */, hdrEnd /* itemEnd */)};
-}
-
-std::tuple<const uint8_t*, ParseClient*> handleBool(uint64_t value, const uint8_t* hdrBegin,
-                                                    const uint8_t* hdrEnd,
-                                                    ParseClient* parseClient) {
-    std::unique_ptr<Item> item = std::make_unique<Bool>(value == TRUE);
-    return {hdrEnd,
-            parseClient->item(item, hdrBegin, hdrEnd /* valueBegin */, hdrEnd /* itemEnd */)};
-}
-
-std::tuple<const uint8_t*, ParseClient*> handleNull(const uint8_t* hdrBegin, const uint8_t* hdrEnd,
-                                                    ParseClient* parseClient) {
-    std::unique_ptr<Item> item = std::make_unique<Null>();
-    return {hdrEnd,
-            parseClient->item(item, hdrBegin, hdrEnd /* valueBegin */, hdrEnd /* itemEnd */)};
-}
-
-template <typename T>
-std::tuple<const uint8_t*, ParseClient*> handleString(uint64_t length, const uint8_t* hdrBegin,
-                                                      const uint8_t* valueBegin, const uint8_t* end,
-                                                      const std::string& errLabel,
-                                                      ParseClient* parseClient) {
-    if (end - valueBegin < static_cast<ssize_t>(length)) {
-        parseClient->error(hdrBegin, insufficientLengthString(length, end - valueBegin, errLabel));
-        return {hdrBegin, nullptr /* end parsing */};
-    }
-
-    std::unique_ptr<Item> item = std::make_unique<T>(valueBegin, valueBegin + length);
-    return {valueBegin + length,
-            parseClient->item(item, hdrBegin, valueBegin, valueBegin + length)};
-}
-
-class IncompleteItem {
-  public:
-    virtual ~IncompleteItem() {}
-    virtual void add(std::unique_ptr<Item> item) = 0;
-};
-
-class IncompleteArray : public Array, public IncompleteItem {
-  public:
-    IncompleteArray(size_t size) : mSize(size) {}
-
-    // We return the "complete" size, rather than the actual size.
-    size_t size() const override { return mSize; }
-
-    void add(std::unique_ptr<Item> item) override {
-        mEntries.reserve(mSize);
-        mEntries.push_back(std::move(item));
-    }
-
-  private:
-    size_t mSize;
-};
-
-class IncompleteMap : public Map, public IncompleteItem {
-  public:
-    IncompleteMap(size_t size) : mSize(size) {}
-
-    // We return the "complete" size, rather than the actual size.
-    size_t size() const override { return mSize; }
-
-    void add(std::unique_ptr<Item> item) override {
-        mEntries.reserve(mSize * 2);
-        mEntries.push_back(std::move(item));
-    }
-
-  private:
-    size_t mSize;
-};
-
-class IncompleteSemantic : public Semantic, public IncompleteItem {
-  public:
-    IncompleteSemantic(uint64_t value) : Semantic(value) {}
-
-    // We return the "complete" size, rather than the actual size.
-    size_t size() const override { return 1; }
-
-    void add(std::unique_ptr<Item> item) override {
-        mEntries.reserve(1);
-        mEntries.push_back(std::move(item));
-    }
-};
-
-std::tuple<const uint8_t*, ParseClient*> handleEntries(size_t entryCount, const uint8_t* hdrBegin,
-                                                       const uint8_t* pos, const uint8_t* end,
-                                                       const std::string& typeName,
-                                                       ParseClient* parseClient) {
-    while (entryCount > 0) {
-        --entryCount;
-        if (pos == end) {
-            parseClient->error(hdrBegin, "Not enough entries for " + typeName + ".");
-            return {hdrBegin, nullptr /* end parsing */};
-        }
-        std::tie(pos, parseClient) = parseRecursively(pos, end, parseClient);
-        if (!parseClient) return {hdrBegin, nullptr};
-    }
-    return {pos, parseClient};
-}
-
-std::tuple<const uint8_t*, ParseClient*> handleCompound(
-        std::unique_ptr<Item> item, uint64_t entryCount, const uint8_t* hdrBegin,
-        const uint8_t* valueBegin, const uint8_t* end, const std::string& typeName,
-        ParseClient* parseClient) {
-    parseClient =
-            parseClient->item(item, hdrBegin, valueBegin, valueBegin /* don't know the end yet */);
-    if (!parseClient) return {hdrBegin, nullptr};
-
-    const uint8_t* pos;
-    std::tie(pos, parseClient) =
-            handleEntries(entryCount, hdrBegin, valueBegin, end, typeName, parseClient);
-    if (!parseClient) return {hdrBegin, nullptr};
-
-    return {pos, parseClient->itemEnd(item, hdrBegin, valueBegin, pos)};
-}
-
-std::tuple<const uint8_t*, ParseClient*> parseRecursively(const uint8_t* begin, const uint8_t* end,
-                                                          ParseClient* parseClient) {
-    const uint8_t* pos = begin;
-
-    MajorType type = static_cast<MajorType>(*pos & 0xE0);
-    uint8_t tagInt = *pos & 0x1F;
-    ++pos;
-
-    bool success = true;
-    uint64_t addlData;
-    if (tagInt < ONE_BYTE_LENGTH || tagInt > EIGHT_BYTE_LENGTH) {
-        addlData = tagInt;
-    } else {
-        switch (tagInt) {
-            case ONE_BYTE_LENGTH:
-                std::tie(success, addlData, pos) = parseLength<uint8_t>(pos, end, parseClient);
-                break;
-
-            case TWO_BYTE_LENGTH:
-                std::tie(success, addlData, pos) = parseLength<uint16_t>(pos, end, parseClient);
-                break;
-
-            case FOUR_BYTE_LENGTH:
-                std::tie(success, addlData, pos) = parseLength<uint32_t>(pos, end, parseClient);
-                break;
-
-            case EIGHT_BYTE_LENGTH:
-                std::tie(success, addlData, pos) = parseLength<uint64_t>(pos, end, parseClient);
-                break;
-
-            default:
-                CHECK(false);  //  It's impossible to get here
-                break;
-        }
-    }
-
-    if (!success) return {begin, nullptr};
-
-    switch (type) {
-        case UINT:
-            return handleUint(addlData, begin, pos, parseClient);
-
-        case NINT:
-            return handleNint(addlData, begin, pos, parseClient);
-
-        case BSTR:
-            return handleString<Bstr>(addlData, begin, pos, end, "byte string", parseClient);
-
-        case TSTR:
-            return handleString<Tstr>(addlData, begin, pos, end, "text string", parseClient);
-
-        case ARRAY:
-            return handleCompound(std::make_unique<IncompleteArray>(addlData), addlData, begin, pos,
-                                  end, "array", parseClient);
-
-        case MAP:
-            return handleCompound(std::make_unique<IncompleteMap>(addlData), addlData * 2, begin,
-                                  pos, end, "map", parseClient);
-
-        case SEMANTIC:
-            return handleCompound(std::make_unique<IncompleteSemantic>(addlData), 1, begin, pos,
-                                  end, "semantic", parseClient);
-
-        case SIMPLE:
-            switch (addlData) {
-                case TRUE:
-                case FALSE:
-                    return handleBool(addlData, begin, pos, parseClient);
-                case NULL_V:
-                    return handleNull(begin, pos, parseClient);
-            }
-    }
-    CHECK(false);  // Impossible to get here.
-    return {};
-}
-
-class FullParseClient : public ParseClient {
-  public:
-    virtual ParseClient* item(std::unique_ptr<Item>& item, const uint8_t*, const uint8_t*,
-                              const uint8_t* end) override {
-        if (mParentStack.empty() && !item->isCompound()) {
-            // This is the first and only item.
-            mTheItem = std::move(item);
-            mPosition = end;
-            return nullptr;  //  We're done.
-        }
-
-        if (item->isCompound()) {
-            // Starting a new compound data item, i.e. a new parent.  Save it on the parent stack.
-            // It's safe to save a raw pointer because the unique_ptr is guaranteed to stay in
-            // existence until the corresponding itemEnd() call.
-            assert(dynamic_cast<CompoundItem*>(item.get()));
-            mParentStack.push(static_cast<CompoundItem*>(item.get()));
-            return this;
-        } else {
-            appendToLastParent(std::move(item));
-            return this;
-        }
-    }
-
-    virtual ParseClient* itemEnd(std::unique_ptr<Item>& item, const uint8_t*, const uint8_t*,
-                                 const uint8_t* end) override {
-        CHECK(item->isCompound() && item.get() == mParentStack.top());
-        mParentStack.pop();
-
-        if (mParentStack.empty()) {
-            mTheItem = std::move(item);
-            mPosition = end;
-            return nullptr;  // We're done
-        } else {
-            appendToLastParent(std::move(item));
-            return this;
-        }
-    }
-
-    virtual void error(const uint8_t* position, const std::string& errorMessage) override {
-        mPosition = position;
-        mErrorMessage = errorMessage;
-    }
-
-    std::tuple<std::unique_ptr<Item> /* result */, const uint8_t* /* newPos */,
-               std::string /* errMsg */>
-    parseResult() {
-        std::unique_ptr<Item> p = std::move(mTheItem);
-        return {std::move(p), mPosition, std::move(mErrorMessage)};
-    }
-
-  private:
-    void appendToLastParent(std::unique_ptr<Item> item) {
-        auto parent = mParentStack.top();
-        assert(dynamic_cast<IncompleteItem*>(parent));
-        if (parent->type() == ARRAY) {
-            static_cast<IncompleteArray*>(parent)->add(std::move(item));
-        } else if (parent->type() == MAP) {
-            static_cast<IncompleteMap*>(parent)->add(std::move(item));
-        } else if (parent->type() == SEMANTIC) {
-            static_cast<IncompleteSemantic*>(parent)->add(std::move(item));
-        } else {
-            CHECK(false);  // Impossible to get here.
-        }
-    }
-
-    std::unique_ptr<Item> mTheItem;
-    std::stack<CompoundItem*> mParentStack;
-    const uint8_t* mPosition = nullptr;
-    std::string mErrorMessage;
-};
-
-}  // anonymous namespace
-
-void parse(const uint8_t* begin, const uint8_t* end, ParseClient* parseClient) {
-    parseRecursively(begin, end, parseClient);
-}
-
-std::tuple<std::unique_ptr<Item> /* result */, const uint8_t* /* newPos */,
-           std::string /* errMsg */>
-parse(const uint8_t* begin, const uint8_t* end) {
-    FullParseClient parseClient;
-    parse(begin, end, &parseClient);
-    return parseClient.parseResult();
-}
-
-}  // namespace cppbor
diff --git a/identity/support/tests/cppbor_test.cpp b/identity/support/tests/cppbor_test.cpp
deleted file mode 100644
index 3eb5598..0000000
--- a/identity/support/tests/cppbor_test.cpp
+++ /dev/null
@@ -1,1013 +0,0 @@
-/*
- * Copyright (c) 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 <iomanip>
-#include <sstream>
-
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-
-#include "cppbor.h"
-#include "cppbor_parse.h"
-
-using namespace cppbor;
-using namespace std;
-
-using ::testing::_;
-using ::testing::AllOf;
-using ::testing::ByRef;
-using ::testing::InSequence;
-using ::testing::IsNull;
-using ::testing::NotNull;
-using ::testing::Return;
-using ::testing::Truly;
-using ::testing::Unused;
-
-string hexDump(const string& str) {
-    stringstream s;
-    for (auto c : str) {
-        s << setfill('0') << setw(2) << hex << (static_cast<unsigned>(c) & 0xff);
-    }
-    return s.str();
-}
-
-TEST(SimpleValueTest, UnsignedValueSizes) {
-    // Check that unsigned integers encode to correct lengths, and that encodedSize() is correct.
-    vector<pair<uint64_t /* value */, size_t /* expected encoded size */>> testCases{
-            {0, 1},
-            {1, 1},
-            {23, 1},
-            {24, 2},
-            {255, 2},
-            {256, 3},
-            {65535, 3},
-            {65536, 5},
-            {4294967295, 5},
-            {4294967296, 9},
-            {std::numeric_limits<uint64_t>::max(), 9},
-    };
-    for (auto& testCase : testCases) {
-        Uint val(testCase.first);
-        EXPECT_EQ(testCase.second, val.encodedSize()) << "Wrong size for value " << testCase.first;
-        EXPECT_EQ(val.encodedSize(), val.toString().size())
-                << "encodedSize and encoding disagree for value " << testCase.first;
-    }
-}
-
-TEST(SimpleValueTest, UnsignedValueEncodings) {
-    EXPECT_EQ("\x00"s, Uint(0u).toString());
-    EXPECT_EQ("\x01"s, Uint(1u).toString());
-    EXPECT_EQ("\x0a"s, Uint(10u).toString());
-    EXPECT_EQ("\x17"s, Uint(23u).toString());
-    EXPECT_EQ("\x18\x18"s, Uint(24u).toString());
-    EXPECT_EQ("\x18\x19"s, Uint(25u).toString());
-    EXPECT_EQ("\x18\x64"s, Uint(100u).toString());
-    EXPECT_EQ("\x19\x03\xe8"s, Uint(1000u).toString());
-    EXPECT_EQ("\x1a\x00\x0f\x42\x40"s, Uint(1000000u).toString());
-    EXPECT_EQ("\x1b\x00\x00\x00\xe8\xd4\xa5\x10\x00"s, Uint(1000000000000u).toString());
-    EXPECT_EQ("\x1B\x7f\xff\xff\xff\xff\xff\xff\xff"s,
-              Uint(std::numeric_limits<int64_t>::max()).toString());
-}
-
-TEST(SimpleValueTest, NegativeValueEncodings) {
-    EXPECT_EQ("\x20"s, Nint(-1).toString());
-    EXPECT_EQ("\x28"s, Nint(-9).toString());
-    EXPECT_EQ("\x29"s, Nint(-10).toString());
-    EXPECT_EQ("\x36"s, Nint(-23).toString());
-    EXPECT_EQ("\x37"s, Nint(-24).toString());
-    EXPECT_EQ("\x38\x18"s, Nint(-25).toString());
-    EXPECT_EQ("\x38\x62"s, Nint(-99).toString());
-    EXPECT_EQ("\x38\x63"s, Nint(-100).toString());
-    EXPECT_EQ("\x39\x03\xe6"s, Nint(-999).toString());
-    EXPECT_EQ("\x39\x03\xe7"s, Nint(-1000).toString());
-    EXPECT_EQ("\x3a\x00\x0f\x42\x3F"s, Nint(-1000000).toString());
-    EXPECT_EQ("\x3b\x00\x00\x00\xe8\xd4\xa5\x0f\xff"s, Nint(-1000000000000).toString());
-    EXPECT_EQ("\x3B\x7f\xff\xff\xff\xff\xff\xff\xff"s,
-              Nint(std::numeric_limits<int64_t>::min()).toString());
-}
-
-TEST(SimpleValueDeathTest, NegativeValueEncodings) {
-    EXPECT_DEATH(Nint(0), "");
-    EXPECT_DEATH(Nint(1), "");
-}
-
-TEST(SimpleValueTest, BooleanEncodings) {
-    EXPECT_EQ("\xf4"s, Bool(false).toString());
-    EXPECT_EQ("\xf5"s, Bool(true).toString());
-}
-
-TEST(SimpleValueTest, ByteStringEncodings) {
-    EXPECT_EQ("\x40", Bstr("").toString());
-    EXPECT_EQ("\x41\x61", Bstr("a").toString());
-    EXPECT_EQ("\x41\x41", Bstr("A").toString());
-    EXPECT_EQ("\x44\x49\x45\x54\x46", Bstr("IETF").toString());
-    EXPECT_EQ("\x42\x22\x5c", Bstr("\"\\").toString());
-    EXPECT_EQ("\x42\xc3\xbc", Bstr("\xc3\xbc").toString());
-    EXPECT_EQ("\x43\xe6\xb0\xb4", Bstr("\xe6\xb0\xb4").toString());
-    EXPECT_EQ("\x44\xf0\x90\x85\x91", Bstr("\xf0\x90\x85\x91").toString());
-    EXPECT_EQ("\x44\x01\x02\x03\x04", Bstr("\x01\x02\x03\x04").toString());
-    EXPECT_EQ("\x44\x40\x40\x40\x40", Bstr("@@@@").toString());
-}
-
-TEST(SimpleValueTest, TextStringEncodings) {
-    EXPECT_EQ("\x60"s, Tstr("").toString());
-    EXPECT_EQ("\x61\x61"s, Tstr("a").toString());
-    EXPECT_EQ("\x61\x41"s, Tstr("A").toString());
-    EXPECT_EQ("\x64\x49\x45\x54\x46"s, Tstr("IETF").toString());
-    EXPECT_EQ("\x62\x22\x5c"s, Tstr("\"\\").toString());
-    EXPECT_EQ("\x62\xc3\xbc"s, Tstr("\xc3\xbc").toString());
-    EXPECT_EQ("\x63\xe6\xb0\xb4"s, Tstr("\xe6\xb0\xb4").toString());
-    EXPECT_EQ("\x64\xf0\x90\x85\x91"s, Tstr("\xf0\x90\x85\x91").toString());
-    EXPECT_EQ("\x64\x01\x02\x03\x04"s, Tstr("\x01\x02\x03\x04").toString());
-}
-
-TEST(IsIteratorPairOverTest, All) {
-    EXPECT_TRUE((
-            details::is_iterator_pair_over<pair<string::iterator, string::iterator>, char>::value));
-    EXPECT_TRUE((details::is_iterator_pair_over<pair<string::const_iterator, string::iterator>,
-                                                char>::value));
-    EXPECT_TRUE((details::is_iterator_pair_over<pair<string::iterator, string::const_iterator>,
-                                                char>::value));
-    EXPECT_TRUE((details::is_iterator_pair_over<pair<char*, char*>, char>::value));
-    EXPECT_TRUE((details::is_iterator_pair_over<pair<const char*, char*>, char>::value));
-    EXPECT_TRUE((details::is_iterator_pair_over<pair<char*, const char*>, char>::value));
-    EXPECT_FALSE((details::is_iterator_pair_over<pair<string::iterator, string::iterator>,
-                                                 uint8_t>::value));
-    EXPECT_FALSE((details::is_iterator_pair_over<pair<char*, char*>, uint8_t>::value));
-    EXPECT_TRUE((details::is_iterator_pair_over<
-                 pair<vector<uint8_t>::iterator, vector<uint8_t>::iterator>, uint8_t>::value));
-    EXPECT_TRUE((details::is_iterator_pair_over<
-                 pair<vector<uint8_t>::const_iterator, vector<uint8_t>::iterator>,
-                 uint8_t>::value));
-    EXPECT_TRUE((details::is_iterator_pair_over<
-                 pair<vector<uint8_t>::iterator, vector<uint8_t>::const_iterator>,
-                 uint8_t>::value));
-    EXPECT_TRUE((details::is_iterator_pair_over<pair<uint8_t*, uint8_t*>, uint8_t>::value));
-    EXPECT_TRUE((details::is_iterator_pair_over<pair<const uint8_t*, uint8_t*>, uint8_t>::value));
-    EXPECT_TRUE((details::is_iterator_pair_over<pair<uint8_t*, const uint8_t*>, uint8_t>::value));
-    EXPECT_FALSE((details::is_iterator_pair_over<
-                  pair<vector<uint8_t>::iterator, vector<uint8_t>::iterator>, char>::value));
-    EXPECT_FALSE((details::is_iterator_pair_over<pair<uint8_t*, const uint8_t*>, char>::value));
-}
-
-TEST(MakeEntryTest, Boolean) {
-    EXPECT_EQ("\xf4"s, details::makeItem(false)->toString());
-}
-
-TEST(MakeEntryTest, Integers) {
-    EXPECT_EQ("\x00"s, details::makeItem(static_cast<uint8_t>(0))->toString());
-    EXPECT_EQ("\x00"s, details::makeItem(static_cast<uint16_t>(0))->toString());
-    EXPECT_EQ("\x00"s, details::makeItem(static_cast<uint32_t>(0))->toString());
-    EXPECT_EQ("\x00"s, details::makeItem(static_cast<uint64_t>(0))->toString());
-    EXPECT_EQ("\x00"s, details::makeItem(static_cast<int8_t>(0))->toString());
-    EXPECT_EQ("\x00"s, details::makeItem(static_cast<int16_t>(0))->toString());
-    EXPECT_EQ("\x00"s, details::makeItem(static_cast<int32_t>(0))->toString());
-    EXPECT_EQ("\x00"s, details::makeItem(static_cast<int64_t>(0))->toString());
-    EXPECT_EQ("\x20"s, details::makeItem(static_cast<int8_t>(-1))->toString());
-    EXPECT_EQ("\x20"s, details::makeItem(static_cast<int16_t>(-1))->toString());
-    EXPECT_EQ("\x20"s, details::makeItem(static_cast<int32_t>(-1))->toString());
-    EXPECT_EQ("\x20"s, details::makeItem(static_cast<int64_t>(-1))->toString());
-
-    EXPECT_EQ("\x1b\xff\xff\xff\xff\xff\xff\xff\xff"s,
-              details::makeItem(static_cast<uint64_t>(std::numeric_limits<uint64_t>::max()))
-                      ->toString());
-}
-
-TEST(MakeEntryTest, StdStrings) {
-    string s1("hello");
-    const string s2("hello");
-    EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s, details::makeItem(s1)->toString());  // copy of string
-    EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s,
-              details::makeItem(s2)->toString());  // copy of const string
-    EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s,
-              details::makeItem(std::move(s1))->toString());  // move string
-    EXPECT_EQ(0U, s1.size());                                 // Prove string was moved, not copied.
-}
-
-TEST(MakeEntryTest, StdStringViews) {
-    string_view s1("hello");
-    const string_view s2("hello");
-    EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s, details::makeItem(s1)->toString());
-    EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s, details::makeItem(s2)->toString());
-}
-
-TEST(MakeEntryTest, CStrings) {
-    char s1[] = "hello";
-    const char s2[] = "hello";
-    const char* s3 = "hello";
-    EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s, details::makeItem(s1)->toString());
-    EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s, details::makeItem(s2)->toString());
-    EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s, details::makeItem(s3)->toString());
-}
-
-TEST(MakeEntryTest, StringIteratorPairs) {
-    // Use iterators from string to prove that "real" iterators work
-    string s1 = "hello"s;
-    pair<string::iterator, string::iterator> p1 = make_pair(s1.begin(), s1.end());
-
-    const pair<string::iterator, string::iterator> p2 = p1;
-    EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s, details::makeItem(p1)->toString());
-    EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s, details::makeItem(p2)->toString());
-
-    // Use char*s  as iterators
-    const char* s2 = "hello";
-    pair p3 = make_pair(s2, s2 + 5);
-    const pair p4 = p3;
-    EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s, details::makeItem(p3)->toString());
-    EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s, details::makeItem(p4)->toString());
-}
-
-TEST(MakeEntryTest, ByteStrings) {
-    vector<uint8_t> v1 = {0x00, 0x01, 0x02};
-    const vector<uint8_t> v2 = {0x00, 0x01, 0x02};
-    EXPECT_EQ("\x43\x00\x01\x02"s, details::makeItem(v1)->toString());  // copy of vector
-    EXPECT_EQ("\x43\x00\x01\x02"s, details::makeItem(v2)->toString());  // copy of const vector
-    EXPECT_EQ("\x43\x00\x01\x02"s, details::makeItem(std::move(v1))->toString());  // move vector
-    EXPECT_EQ(0U, v1.size());  // Prove vector was moved, not copied.
-}
-
-TEST(MakeEntryTest, ByteStringIteratorPairs) {
-    using vec = vector<uint8_t>;
-    using iter = vec::iterator;
-    vec v1 = {0x00, 0x01, 0x02};
-    pair<iter, iter> p1 = make_pair(v1.begin(), v1.end());
-    const pair<iter, iter> p2 = make_pair(v1.begin(), v1.end());
-    EXPECT_EQ("\x43\x00\x01\x02"s, details::makeItem(p1)->toString());
-    EXPECT_EQ("\x43\x00\x01\x02"s, details::makeItem(p2)->toString());
-
-    // Use uint8_t*s as iterators
-    uint8_t v2[] = {0x00, 0x01, 0x02};
-    uint8_t* v3 = v2;
-    pair<uint8_t*, uint8_t*> p3 = make_pair(v2, v2 + 3);
-    const pair<uint8_t*, uint8_t*> p4 = make_pair(v2, v2 + 3);
-    pair<uint8_t*, uint8_t*> p5 = make_pair(v3, v3 + 3);
-    const pair<uint8_t*, uint8_t*> p6 = make_pair(v3, v3 + 3);
-    EXPECT_EQ("\x43\x00\x01\x02"s, details::makeItem(p3)->toString());
-    EXPECT_EQ("\x43\x00\x01\x02"s, details::makeItem(p4)->toString());
-    EXPECT_EQ("\x43\x00\x01\x02"s, details::makeItem(p5)->toString());
-    EXPECT_EQ("\x43\x00\x01\x02"s, details::makeItem(p6)->toString());
-}
-
-TEST(MakeEntryTest, ByteStringBuffers) {
-    uint8_t v1[] = {0x00, 0x01, 0x02};
-    EXPECT_EQ("\x43\x00\x01\x02"s, details::makeItem(make_pair(v1, 3))->toString());
-}
-
-TEST(MakeEntryTest, ItemPointer) {
-    Uint* p1 = new Uint(0);
-    EXPECT_EQ("\x00"s, details::makeItem(p1)->toString());
-    EXPECT_EQ("\x60"s, details::makeItem(new Tstr(string()))->toString());
-}
-
-TEST(MakeEntryTest, ItemReference) {
-    Tstr str("hello"s);
-    Tstr& strRef = str;
-    const Tstr& strConstRef = str;
-    EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s, details::makeItem(str)->toString());
-    EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s, details::makeItem(strRef)->toString());
-    EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s, details::makeItem(strConstRef)->toString());
-    EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s, details::makeItem(std::move(str))->toString());
-    EXPECT_EQ("\x60"s, details::makeItem(str)->toString());  // Prove that it moved
-
-    EXPECT_EQ("\x00"s, details::makeItem(Uint(0))->toString());
-
-    EXPECT_EQ("\x43\x00\x01\x02"s,
-              details::makeItem(Bstr(vector<uint8_t>{0x00, 0x01, 0x02}))->toString());
-
-    EXPECT_EQ("\x80"s, details::makeItem(Array())->toString());
-    EXPECT_EQ("\xa0"s, details::makeItem(Map())->toString());
-}
-
-TEST(CompoundValueTest, ArrayOfInts) {
-    EXPECT_EQ("\x80"s, Array().toString());
-    Array(Uint(0)).toString();
-
-    EXPECT_EQ("\x81\x00"s, Array(Uint(0U)).toString());
-    EXPECT_EQ("\x82\x00\x01"s, Array(Uint(0), Uint(1)).toString());
-    EXPECT_EQ("\x83\x00\x01\x38\x62"s, Array(Uint(0), Uint(1), Nint(-99)).toString());
-
-    EXPECT_EQ("\x81\x00"s, Array(0).toString());
-    EXPECT_EQ("\x82\x00\x01"s, Array(0, 1).toString());
-    EXPECT_EQ("\x83\x00\x01\x38\x62"s, Array(0, 1, -99).toString());
-}
-
-TEST(CompoundValueTest, MapOfInts) {
-    EXPECT_EQ("\xA0"s, Map().toString());
-    EXPECT_EQ("\xA1\x00\x01"s, Map(Uint(0), Uint(1)).toString());
-    // Maps with an odd number of arguments will fail to compile.  Uncomment the next lines to test.
-    // EXPECT_EQ("\xA1\x00"s, Map(Int(0)).toString());
-    // EXPECT_EQ("\xA1\x00\x01\x02"s, Map(Int(0), Int(1), Int(2)).toString());
-}
-
-TEST(CompoundValueTest, MixedArray) {
-    vector<uint8_t> vec = {3, 2, 1};
-    EXPECT_EQ("\x84\x01\x20\x43\x03\x02\x01\x65\x68\x65\x6C\x6C\x6F"s,
-              Array(Uint(1), Nint(-1), Bstr(vec), Tstr("hello")).toString());
-
-    EXPECT_EQ("\x84\x01\x20\x43\x03\x02\x01\x65\x68\x65\x6C\x6C\x6F"s,
-              Array(1, -1, vec, "hello").toString());
-}
-
-TEST(CompoundValueTest, MixedMap) {
-    vector<uint8_t> vec = {3, 2, 1};
-    EXPECT_EQ("\xA2\x01\x20\x43\x03\x02\x01\x65\x68\x65\x6C\x6C\x6F"s,
-              Map(Uint(1), Nint(-1), Bstr(vec), Tstr("hello")).toString());
-
-    EXPECT_EQ("\xA2\x01\x20\x43\x03\x02\x01\x65\x68\x65\x6C\x6C\x6F"s,
-              Map(1, -1, vec, "hello").toString());
-}
-
-TEST(CompoundValueTest, NestedStructures) {
-    vector<uint8_t> vec = {3, 2, 1};
-
-    string expectedEncoding =
-            "\xA2\x66\x4F\x75\x74\x65\x72\x31\x82\xA2\x66\x49\x6E\x6E\x65\x72\x31\x18\x63\x66\x49"
-            "\x6E"
-            "\x6E\x65\x72\x32\x43\x03\x02\x01\x63\x66\x6F\x6F\x66\x4F\x75\x74\x65\x72\x32\x0A"s;
-
-    // Do it with explicitly-created Items
-    EXPECT_EQ(expectedEncoding,
-              Map(Tstr("Outer1"),
-                  Array(  //
-                          Map(Tstr("Inner1"), Uint(99), Tstr("Inner2"), Bstr(vec)), Tstr("foo")),
-                  Tstr("Outer2"),  //
-                  Uint(10))
-                      .toString());
-    EXPECT_EQ(3U, vec.size());
-
-    // Now just use convertible types
-    EXPECT_EQ(expectedEncoding, Map("Outer1",
-                                    Array(Map("Inner1", 99,  //
-                                              "Inner2", vec),
-                                          "foo"),
-                                    "Outer2", 10)
-                                        .toString());
-    EXPECT_EQ(3U, vec.size());
-
-    // Finally, do it with the .add() method.  This is slightly less efficient, but has the
-    // advantage you can build a structure up incrementally, or somewhat fluently if you like.
-    // First, fluently.
-    EXPECT_EQ(expectedEncoding, Map().add("Outer1", Array().add(Map()  //
-                                                                        .add("Inner1", 99)
-                                                                        .add("Inner2", vec))
-                                                            .add("foo"))
-                                        .add("Outer2", 10)
-                                        .toString());
-    EXPECT_EQ(3U, vec.size());
-
-    // Next, more incrementally
-    Array arr;
-    arr.add(Map()  //
-                    .add("Inner1", 99)
-                    .add("Inner2", vec))
-            .add("foo");
-    EXPECT_EQ(3U, vec.size());
-
-    Map m;
-    m.add("Outer1", std::move(arr));  // Moving is necessary; Map and Array cannot be copied.
-    m.add("Outer2", 10);
-    auto s = m.toString();
-    EXPECT_EQ(expectedEncoding, s);
-}
-
-TEST(EncodingMethodsTest, AllVariants) {
-    Map map;
-    map.add("key1", Array().add(Map()  //
-                                        .add("key_a", 9999999)
-                                        .add("key_b", std::vector<uint8_t>{0x01, 0x02, 0x03})
-                                        .add("key_c", std::numeric_limits<uint64_t>::max())
-                                        .add("key_d", std::numeric_limits<int16_t>::min()))
-                            .add("foo"))
-            .add("key2", true);
-
-    std::vector<uint8_t> buf;
-    buf.resize(map.encodedSize());
-
-    EXPECT_EQ(buf.data() + buf.size(), map.encode(buf.data(), buf.data() + buf.size()));
-
-    EXPECT_EQ(buf, map.encode());
-
-    std::vector<uint8_t> buf2;
-    map.encode(std::back_inserter(buf2));
-    EXPECT_EQ(buf, buf2);
-
-    auto iter = buf.begin();
-    map.encode([&](uint8_t c) { EXPECT_EQ(c, *iter++); });
-}
-
-TEST(EncodingMethodsTest, UintWithTooShortBuf) {
-    Uint val(100000);
-    vector<uint8_t> buf(val.encodedSize() - 1);
-    EXPECT_EQ(nullptr, val.encode(buf.data(), buf.data() + buf.size()));
-}
-
-TEST(EncodingMethodsTest, TstrWithTooShortBuf) {
-    Tstr val("01234567890123456789012345"s);
-    vector<uint8_t> buf(1);
-    EXPECT_EQ(nullptr, val.encode(buf.data(), buf.data() + buf.size()));
-
-    buf.resize(val.encodedSize() - 1);
-    EXPECT_EQ(nullptr, val.encode(buf.data(), buf.data() + buf.size()));
-}
-
-TEST(EncodingMethodsTest, BstrWithTooShortBuf) {
-    Bstr val("01234567890123456789012345"s);
-    vector<uint8_t> buf(1);
-    EXPECT_EQ(nullptr, val.encode(buf.data(), buf.data() + buf.size()));
-
-    buf.resize(val.encodedSize() - 1);
-    EXPECT_EQ(nullptr, val.encode(buf.data(), buf.data() + buf.size()));
-}
-
-TEST(EncodingMethodsTest, ArrayWithTooShortBuf) {
-    Array val("a", 5, -100);
-
-    std::vector<uint8_t> buf(val.encodedSize() - 1);
-    EXPECT_EQ(nullptr, val.encode(buf.data(), buf.data() + buf.size()));
-}
-
-TEST(EncodingMethodsTest, MapWithTooShortBuf) {
-    Map map;
-    map.add("key1", Array().add(Map()  //
-                                        .add("key_a", 99)
-                                        .add("key_b", std::vector<uint8_t>{0x01, 0x02, 0x03}))
-                            .add("foo"))
-            .add("key2", true);
-
-    std::vector<uint8_t> buf(map.encodedSize() - 1);
-    EXPECT_EQ(nullptr, map.encode(buf.data(), buf.data() + buf.size()));
-}
-
-TEST(EqualityTest, Uint) {
-    Uint val(99);
-    EXPECT_EQ(val, Uint(99));
-
-    EXPECT_NE(val, Uint(98));
-    EXPECT_NE(val, Nint(-1));
-    EXPECT_NE(val, Tstr("99"));
-    EXPECT_NE(val, Bstr("99"));
-    EXPECT_NE(val, Bool(false));
-    EXPECT_NE(val, Array(99, 1));
-    EXPECT_NE(val, Map(99, 1));
-}
-
-TEST(EqualityTest, Nint) {
-    Nint val(-1);
-    EXPECT_EQ(val, Nint(-1));
-
-    EXPECT_NE(val, Uint(99));
-    EXPECT_NE(val, Nint(-4));
-    EXPECT_NE(val, Tstr("99"));
-    EXPECT_NE(val, Bstr("99"));
-    EXPECT_NE(val, Bool(false));
-    EXPECT_NE(val, Array(99));
-    EXPECT_NE(val, Map(99, 1));
-}
-
-TEST(EqualityTest, Tstr) {
-    Tstr val("99");
-    EXPECT_EQ(val, Tstr("99"));
-
-    EXPECT_NE(val, Uint(99));
-    EXPECT_NE(val, Nint(-1));
-    EXPECT_NE(val, Nint(-4));
-    EXPECT_NE(val, Tstr("98"));
-    EXPECT_NE(val, Bstr("99"));
-    EXPECT_NE(val, Bool(false));
-    EXPECT_NE(val, Array(99, 1));
-    EXPECT_NE(val, Map(99, 1));
-}
-
-TEST(EqualityTest, Bstr) {
-    Bstr val("99");
-    EXPECT_EQ(val, Bstr("99"));
-
-    EXPECT_NE(val, Uint(99));
-    EXPECT_NE(val, Nint(-1));
-    EXPECT_NE(val, Nint(-4));
-    EXPECT_NE(val, Tstr("99"));
-    EXPECT_NE(val, Bstr("98"));
-    EXPECT_NE(val, Bool(false));
-    EXPECT_NE(val, Array(99, 1));
-    EXPECT_NE(val, Map(99, 1));
-}
-
-TEST(EqualityTest, Bool) {
-    Bool val(false);
-    EXPECT_EQ(val, Bool(false));
-
-    EXPECT_NE(val, Uint(99));
-    EXPECT_NE(val, Nint(-1));
-    EXPECT_NE(val, Nint(-4));
-    EXPECT_NE(val, Tstr("99"));
-    EXPECT_NE(val, Bstr("98"));
-    EXPECT_NE(val, Bool(true));
-    EXPECT_NE(val, Array(99, 1));
-    EXPECT_NE(val, Map(99, 1));
-}
-
-TEST(EqualityTest, Array) {
-    Array val(99, 1);
-    EXPECT_EQ(val, Array(99, 1));
-
-    EXPECT_NE(val, Uint(99));
-    EXPECT_NE(val, Nint(-1));
-    EXPECT_NE(val, Nint(-4));
-    EXPECT_NE(val, Tstr("99"));
-    EXPECT_NE(val, Bstr("98"));
-    EXPECT_NE(val, Bool(true));
-    EXPECT_NE(val, Array(99, 2));
-    EXPECT_NE(val, Array(98, 1));
-    EXPECT_NE(val, Array(99, 1, 2));
-    EXPECT_NE(val, Map(99, 1));
-}
-
-TEST(EqualityTest, Map) {
-    Map val(99, 1);
-    EXPECT_EQ(val, Map(99, 1));
-
-    EXPECT_NE(val, Uint(99));
-    EXPECT_NE(val, Nint(-1));
-    EXPECT_NE(val, Nint(-4));
-    EXPECT_NE(val, Tstr("99"));
-    EXPECT_NE(val, Bstr("98"));
-    EXPECT_NE(val, Bool(true));
-    EXPECT_NE(val, Array(99, 1));
-    EXPECT_NE(val, Map(99, 2));
-    EXPECT_NE(val, Map(99, 1, 99, 2));
-}
-
-TEST(ConvertTest, Uint) {
-    unique_ptr<Item> item = details::makeItem(10);
-
-    EXPECT_EQ(UINT, item->type());
-    EXPECT_NE(nullptr, item->asInt());
-    EXPECT_NE(nullptr, item->asUint());
-    EXPECT_EQ(nullptr, item->asNint());
-    EXPECT_EQ(nullptr, item->asTstr());
-    EXPECT_EQ(nullptr, item->asBstr());
-    EXPECT_EQ(nullptr, item->asSimple());
-    EXPECT_EQ(nullptr, item->asMap());
-    EXPECT_EQ(nullptr, item->asArray());
-
-    EXPECT_EQ(10, item->asInt()->value());
-    EXPECT_EQ(10, item->asUint()->value());
-}
-
-TEST(ConvertTest, Nint) {
-    unique_ptr<Item> item = details::makeItem(-10);
-
-    EXPECT_EQ(NINT, item->type());
-    EXPECT_NE(nullptr, item->asInt());
-    EXPECT_EQ(nullptr, item->asUint());
-    EXPECT_NE(nullptr, item->asNint());
-    EXPECT_EQ(nullptr, item->asTstr());
-    EXPECT_EQ(nullptr, item->asBstr());
-    EXPECT_EQ(nullptr, item->asSimple());
-    EXPECT_EQ(nullptr, item->asMap());
-    EXPECT_EQ(nullptr, item->asArray());
-
-    EXPECT_EQ(-10, item->asInt()->value());
-    EXPECT_EQ(-10, item->asNint()->value());
-}
-
-TEST(ConvertTest, Tstr) {
-    unique_ptr<Item> item = details::makeItem("hello");
-
-    EXPECT_EQ(TSTR, item->type());
-    EXPECT_EQ(nullptr, item->asInt());
-    EXPECT_EQ(nullptr, item->asUint());
-    EXPECT_EQ(nullptr, item->asNint());
-    EXPECT_NE(nullptr, item->asTstr());
-    EXPECT_EQ(nullptr, item->asBstr());
-    EXPECT_EQ(nullptr, item->asSimple());
-    EXPECT_EQ(nullptr, item->asMap());
-    EXPECT_EQ(nullptr, item->asArray());
-
-    EXPECT_EQ("hello"s, item->asTstr()->value());
-}
-
-TEST(ConvertTest, Bstr) {
-    vector<uint8_t> vec{0x23, 0x24, 0x22};
-    unique_ptr<Item> item = details::makeItem(vec);
-
-    EXPECT_EQ(BSTR, item->type());
-    EXPECT_EQ(nullptr, item->asInt());
-    EXPECT_EQ(nullptr, item->asUint());
-    EXPECT_EQ(nullptr, item->asNint());
-    EXPECT_EQ(nullptr, item->asTstr());
-    EXPECT_NE(nullptr, item->asBstr());
-    EXPECT_EQ(nullptr, item->asSimple());
-    EXPECT_EQ(nullptr, item->asMap());
-    EXPECT_EQ(nullptr, item->asArray());
-
-    EXPECT_EQ(vec, item->asBstr()->value());
-}
-
-TEST(ConvertTest, Bool) {
-    unique_ptr<Item> item = details::makeItem(false);
-
-    EXPECT_EQ(SIMPLE, item->type());
-    EXPECT_EQ(nullptr, item->asInt());
-    EXPECT_EQ(nullptr, item->asUint());
-    EXPECT_EQ(nullptr, item->asNint());
-    EXPECT_EQ(nullptr, item->asTstr());
-    EXPECT_EQ(nullptr, item->asBstr());
-    EXPECT_NE(nullptr, item->asSimple());
-    EXPECT_EQ(nullptr, item->asMap());
-    EXPECT_EQ(nullptr, item->asArray());
-
-    EXPECT_EQ(BOOLEAN, item->asSimple()->simpleType());
-    EXPECT_NE(nullptr, item->asSimple()->asBool());
-
-    EXPECT_FALSE(item->asSimple()->asBool()->value());
-}
-
-TEST(ConvertTest, Map) {
-    unique_ptr<Item> item(new Map);
-
-    EXPECT_EQ(MAP, item->type());
-    EXPECT_EQ(nullptr, item->asInt());
-    EXPECT_EQ(nullptr, item->asUint());
-    EXPECT_EQ(nullptr, item->asNint());
-    EXPECT_EQ(nullptr, item->asTstr());
-    EXPECT_EQ(nullptr, item->asBstr());
-    EXPECT_EQ(nullptr, item->asSimple());
-    EXPECT_NE(nullptr, item->asMap());
-    EXPECT_EQ(nullptr, item->asArray());
-
-    EXPECT_EQ(0U, item->asMap()->size());
-}
-
-TEST(ConvertTest, Array) {
-    unique_ptr<Item> item(new Array);
-
-    EXPECT_EQ(ARRAY, item->type());
-    EXPECT_EQ(nullptr, item->asInt());
-    EXPECT_EQ(nullptr, item->asUint());
-    EXPECT_EQ(nullptr, item->asNint());
-    EXPECT_EQ(nullptr, item->asTstr());
-    EXPECT_EQ(nullptr, item->asBstr());
-    EXPECT_EQ(nullptr, item->asSimple());
-    EXPECT_EQ(nullptr, item->asMap());
-    EXPECT_NE(nullptr, item->asArray());
-
-    EXPECT_EQ(0U, item->asArray()->size());
-}
-
-class MockParseClient : public ParseClient {
-  public:
-    MOCK_METHOD4(item, ParseClient*(std::unique_ptr<Item>& item, const uint8_t* hdrBegin,
-                                    const uint8_t* valueBegin, const uint8_t* end));
-    MOCK_METHOD4(itemEnd, ParseClient*(std::unique_ptr<Item>& item, const uint8_t* hdrBegin,
-                                       const uint8_t* valueBegin, const uint8_t* end));
-    MOCK_METHOD2(error, void(const uint8_t* position, const std::string& errorMessage));
-};
-
-MATCHER_P(IsType, value, std::string("Type ") + (negation ? "doesn't match" : "matches")) {
-    return arg->type() == value;
-}
-
-MATCHER_P(MatchesItem, value, "") {
-    return arg && *arg == value;
-}
-
-MATCHER_P(IsArrayOfSize, value, "") {
-    return arg->type() == ARRAY && arg->asArray()->size() == value;
-}
-
-MATCHER_P(IsMapOfSize, value, "") {
-    return arg->type() == MAP && arg->asMap()->size() == value;
-}
-
-TEST(StreamParseTest, Uint) {
-    MockParseClient mpc;
-
-    Uint val(100);
-    auto encoded = val.encode();
-    uint8_t* encBegin = encoded.data();
-    uint8_t* encEnd = encoded.data() + encoded.size();
-
-    EXPECT_CALL(mpc, item(MatchesItem(val), encBegin, encEnd, encEnd)).WillOnce(Return(&mpc));
-    EXPECT_CALL(mpc, itemEnd(_, _, _, _)).Times(0);
-    EXPECT_CALL(mpc, error(_, _)).Times(0);
-
-    parse(encoded.data(), encoded.data() + encoded.size(), &mpc);
-}
-
-TEST(StreamParseTest, Nint) {
-    MockParseClient mpc;
-
-    Nint val(-10);
-    auto encoded = val.encode();
-    uint8_t* encBegin = encoded.data();
-    uint8_t* encEnd = encoded.data() + encoded.size();
-
-    EXPECT_CALL(mpc, item(MatchesItem(val), encBegin, encEnd, encEnd)).WillOnce(Return(&mpc));
-
-    EXPECT_CALL(mpc, itemEnd(_, _, _, _)).Times(0);
-    EXPECT_CALL(mpc, error(_, _)).Times(0);
-
-    parse(encoded.data(), encoded.data() + encoded.size(), &mpc);
-}
-
-TEST(StreamParseTest, Bool) {
-    MockParseClient mpc;
-
-    Bool val(true);
-    auto encoded = val.encode();
-    uint8_t* encBegin = encoded.data();
-    uint8_t* encEnd = encoded.data() + encoded.size();
-
-    EXPECT_CALL(mpc, item(MatchesItem(val), encBegin, encEnd, encEnd)).WillOnce(Return(&mpc));
-    EXPECT_CALL(mpc, itemEnd(_, _, _, _)).Times(0);
-    EXPECT_CALL(mpc, error(_, _)).Times(0);
-
-    parse(encoded.data(), encoded.data() + encoded.size(), &mpc);
-}
-
-TEST(StreamParseTest, Tstr) {
-    MockParseClient mpc;
-
-    Tstr val("Hello");
-    auto encoded = val.encode();
-    uint8_t* encBegin = encoded.data();
-    uint8_t* encEnd = encoded.data() + encoded.size();
-
-    EXPECT_CALL(mpc, item(MatchesItem(val), encBegin, encBegin + 1, encEnd)).WillOnce(Return(&mpc));
-    EXPECT_CALL(mpc, itemEnd(_, _, _, _)).Times(0);
-    EXPECT_CALL(mpc, error(_, _)).Times(0);
-
-    parse(encoded.data(), encoded.data() + encoded.size(), &mpc);
-}
-
-TEST(StreamParseTest, Bstr) {
-    MockParseClient mpc;
-
-    Bstr val("Hello");
-    auto encoded = val.encode();
-    uint8_t* encBegin = encoded.data();
-    uint8_t* encEnd = encoded.data() + encoded.size();
-
-    EXPECT_CALL(mpc, item(MatchesItem(val), encBegin, encBegin + 1, encEnd)).WillOnce(Return(&mpc));
-    EXPECT_CALL(mpc, itemEnd(_, _, _, _)).Times(0);
-    EXPECT_CALL(mpc, error(_, _)).Times(0);
-
-    parse(encoded.data(), encoded.data() + encoded.size(), &mpc);
-}
-
-TEST(StreamParseTest, Array) {
-    MockParseClient mpc;
-
-    Array val("Hello", 4, Array(-9, "Goodbye"), std::numeric_limits<uint64_t>::max());
-    ASSERT_NE(val[2]->asArray(), nullptr);
-    const Array& interior = *(val[2]->asArray());
-    auto encoded = val.encode();
-    uint8_t* encBegin = encoded.data();
-    uint8_t* encEnd = encoded.data() + encoded.size();
-
-    {
-        InSequence s;
-        const uint8_t* pos = encBegin;
-        EXPECT_CALL(mpc, item(IsArrayOfSize(val.size()), pos, pos + 1, pos + 1))
-                .WillOnce(Return(&mpc));
-        ++pos;
-        EXPECT_CALL(mpc, item(MatchesItem(ByRef(*val[0])), pos, pos + 1, pos + 6))
-                .WillOnce(Return(&mpc));
-        pos += 6;
-        EXPECT_CALL(mpc, item(MatchesItem(ByRef(*val[1])), pos, pos + 1, pos + 1))
-                .WillOnce(Return(&mpc));
-        ++pos;
-        const uint8_t* innerArrayBegin = pos;
-        EXPECT_CALL(mpc, item(IsArrayOfSize(interior.size()), pos, pos + 1, pos + 1))
-                .WillOnce(Return(&mpc));
-        ++pos;
-        EXPECT_CALL(mpc, item(MatchesItem(ByRef(*interior[0])), pos, pos + 1, pos + 1))
-                .WillOnce(Return(&mpc));
-        ++pos;
-        EXPECT_CALL(mpc, item(MatchesItem(ByRef(*interior[1])), pos, pos + 1, pos + 8))
-                .WillOnce(Return(&mpc));
-        pos += 8;
-        EXPECT_CALL(mpc, itemEnd(IsArrayOfSize(interior.size()), innerArrayBegin,
-                                 innerArrayBegin + 1, pos))
-                .WillOnce(Return(&mpc));
-        EXPECT_CALL(mpc, item(MatchesItem(ByRef(*val[3])), pos, pos + 9, pos + 9))
-                .WillOnce(Return(&mpc));
-        EXPECT_CALL(mpc, itemEnd(IsArrayOfSize(val.size()), encBegin, encBegin + 1, encEnd))
-                .WillOnce(Return(&mpc));
-    }
-
-    EXPECT_CALL(mpc, error(_, _))  //
-            .Times(0);
-
-    parse(encoded.data(), encoded.data() + encoded.size(), &mpc);
-}
-
-TEST(StreamParseTest, Map) {
-    MockParseClient mpc;
-
-    Map val("Hello", 4, Array(-9, "Goodbye"), std::numeric_limits<uint64_t>::max());
-    ASSERT_NE(val[1].first->asArray(), nullptr);
-    const Array& interior = *(val[1].first->asArray());
-    auto encoded = val.encode();
-    uint8_t* encBegin = encoded.data();
-    uint8_t* encEnd = encoded.data() + encoded.size();
-
-    {
-        InSequence s;
-        const uint8_t* pos = encBegin;
-        EXPECT_CALL(mpc, item(_, pos, pos + 1, pos + 1)).WillOnce(Return(&mpc));
-        ++pos;
-        EXPECT_CALL(mpc, item(MatchesItem(ByRef(*val[0].first)), pos, pos + 1, pos + 6))
-                .WillOnce(Return(&mpc));
-        pos += 6;
-        EXPECT_CALL(mpc, item(MatchesItem(ByRef(*val[0].second)), pos, pos + 1, pos + 1))
-                .WillOnce(Return(&mpc));
-        ++pos;
-        const uint8_t* innerArrayBegin = pos;
-        EXPECT_CALL(mpc, item(IsArrayOfSize(interior.size()), pos, pos + 1, pos + 1))
-                .WillOnce(Return(&mpc));
-        ++pos;
-        EXPECT_CALL(mpc, item(MatchesItem(ByRef(*interior[0])), pos, pos + 1, pos + 1))
-                .WillOnce(Return(&mpc));
-        ++pos;
-        EXPECT_CALL(mpc, item(MatchesItem(ByRef(*interior[1])), pos, pos + 1, pos + 8))
-                .WillOnce(Return(&mpc));
-        pos += 8;
-        EXPECT_CALL(mpc, itemEnd(IsArrayOfSize(interior.size()), innerArrayBegin,
-                                 innerArrayBegin + 1, pos))
-                .WillOnce(Return(&mpc));
-        EXPECT_CALL(mpc, item(MatchesItem(ByRef(*val[1].second)), pos, pos + 9, pos + 9))
-                .WillOnce(Return(&mpc));
-        EXPECT_CALL(mpc, itemEnd(IsMapOfSize(val.size()), encBegin, encBegin + 1, encEnd))
-                .WillOnce(Return(&mpc));
-    }
-
-    EXPECT_CALL(mpc, error(_, _))  //
-            .Times(0);
-
-    parse(encoded.data(), encoded.data() + encoded.size(), &mpc);
-}
-
-TEST(StreamParseTest, Semantic) {
-    MockParseClient mpc;
-
-    vector<uint8_t> encoded;
-    auto iter = back_inserter(encoded);
-    encodeHeader(SEMANTIC, 0, iter);
-    Uint(999).encode(iter);
-
-    EXPECT_CALL(mpc, item(_, _, _, _)).Times(0);
-    EXPECT_CALL(mpc, itemEnd(_, _, _, _)).Times(0);
-    EXPECT_CALL(mpc, error(encoded.data(), "Semantic tags not supported"));
-
-    parse(encoded.data(), encoded.data() + encoded.size(), &mpc);
-}
-
-TEST(FullParserTest, Uint) {
-    Uint val(10);
-
-    auto [item, pos, message] = parse(val.encode());
-    EXPECT_THAT(item, MatchesItem(val));
-}
-
-TEST(FullParserTest, Nint) {
-    Nint val(-10);
-
-    auto [item, pos, message] = parse(val.encode());
-    EXPECT_THAT(item, MatchesItem(val));
-
-    vector<uint8_t> minNint = {0x3B, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
-
-    std::tie(item, pos, message) = parse(minNint);
-    EXPECT_THAT(item, NotNull());
-    EXPECT_EQ(item->asNint()->value(), std::numeric_limits<int64_t>::min());
-}
-
-TEST(FullParserTest, NintOutOfRange) {
-    vector<uint8_t> outOfRangeNint = {0x3B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
-
-    auto [item, pos, message] = parse(outOfRangeNint);
-    EXPECT_THAT(item, IsNull());
-    EXPECT_EQ(pos, outOfRangeNint.data());
-    EXPECT_EQ(message, "NINT values that don't fit in int64_t are not supported.");
-}
-
-TEST(FullParserTest, Tstr) {
-    Tstr val("Hello");
-
-    auto [item, pos, message] = parse(val.encode());
-    EXPECT_THAT(item, MatchesItem(val));
-}
-
-TEST(FullParserTest, Bstr) {
-    Bstr val("\x00\x01\0x02"s);
-
-    auto [item, pos, message] = parse(val.encode());
-    EXPECT_THAT(item, MatchesItem(val));
-}
-
-TEST(FullParserTest, Array) {
-    Array val("hello", -4, 3);
-
-    auto encoded = val.encode();
-    auto [item, pos, message] = parse(encoded);
-    EXPECT_THAT(item, MatchesItem(ByRef(val)));
-    EXPECT_EQ(pos, encoded.data() + encoded.size());
-    EXPECT_EQ("", message);
-
-    // We've already checked it all, but walk it just for fun.
-    ASSERT_NE(nullptr, item->asArray());
-    const Array& arr = *(item->asArray());
-    ASSERT_EQ(arr[0]->type(), TSTR);
-    EXPECT_EQ(arr[0]->asTstr()->value(), "hello");
-}
-
-TEST(FullParserTest, Map) {
-    Map val("hello", -4, 3, Bstr("hi"));
-
-    auto [item, pos, message] = parse(val.encode());
-    EXPECT_THAT(item, MatchesItem(ByRef(val)));
-}
-
-TEST(FullParserTest, Complex) {
-    vector<uint8_t> vec = {0x01, 0x02, 0x08, 0x03};
-    Map val("Outer1",
-            Array(Map("Inner1", 99,  //
-                      "Inner2", vec),
-                  "foo"),
-            "Outer2", 10);
-
-    std::unique_ptr<Item> item;
-    const uint8_t* pos;
-    std::string message;
-    std::tie(item, pos, message) = parse(val.encode());
-    EXPECT_THAT(item, MatchesItem(ByRef(val)));
-}
-
-TEST(FullParserTest, IncompleteUint) {
-    Uint val(1000);
-
-    auto encoding = val.encode();
-    auto [item, pos, message] = parse(encoding.data(), encoding.size() - 1);
-    EXPECT_EQ(nullptr, item.get());
-    EXPECT_EQ(encoding.data(), pos);
-    EXPECT_EQ("Need 2 byte(s) for length field, have 1.", message);
-}
-
-TEST(FullParserTest, IncompleteString) {
-    Tstr val("hello");
-
-    auto encoding = val.encode();
-    auto [item, pos, message] = parse(encoding.data(), encoding.size() - 2);
-    EXPECT_EQ(nullptr, item.get());
-    EXPECT_EQ(encoding.data(), pos);
-    EXPECT_EQ("Need 5 byte(s) for text string, have 3.", message);
-}
-
-TEST(FullParserTest, ArrayWithInsufficientEntries) {
-    Array val(1, 2, 3, 4);
-
-    auto encoding = val.encode();
-    auto [item, pos, message] = parse(encoding.data(), encoding.size() - 1);
-    EXPECT_EQ(nullptr, item.get());
-    EXPECT_EQ(encoding.data(), pos);
-    EXPECT_EQ("Not enough entries for array.", message);
-}
-
-TEST(FullParserTest, ArrayWithTruncatedEntry) {
-    Array val(1, 2, 3, 400000);
-
-    auto encoding = val.encode();
-    auto [item, pos, message] = parse(encoding.data(), encoding.size() - 1);
-    EXPECT_EQ(nullptr, item.get());
-    EXPECT_EQ(encoding.data() + encoding.size() - 5, pos);
-    EXPECT_EQ("Need 4 byte(s) for length field, have 3.", message);
-}
-
-TEST(FullParserTest, MapWithTruncatedEntry) {
-    Map val(1, 2, 300000, 4);
-
-    auto encoding = val.encode();
-    auto [item, pos, message] = parse(encoding.data(), encoding.size() - 2);
-    EXPECT_EQ(nullptr, item.get());
-    EXPECT_EQ(encoding.data() + 3, pos);
-    EXPECT_EQ("Need 4 byte(s) for length field, have 3.", message);
-}
-int main(int argc, char** argv) {
-    ::testing::InitGoogleTest(&argc, argv);
-    return RUN_ALL_TESTS();
-}
diff --git a/security/rkp/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp b/security/rkp/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
index cb1c692..aebcf67 100644
--- a/security/rkp/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
+++ b/security/rkp/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
@@ -783,4 +783,20 @@
 
 INSTANTIATE_REM_PROV_AIDL_TEST(CertificateRequestV2Test);
 
+using VsrRequirementTest = VtsRemotelyProvisionedComponentTests;
+
+INSTANTIATE_REM_PROV_AIDL_TEST(VsrRequirementTest);
+
+TEST_P(VsrRequirementTest, VsrEnforcementTest) {
+    RpcHardwareInfo hwInfo;
+    ASSERT_TRUE(provisionable_->getHardwareInfo(&hwInfo).isOk());
+    int vsr_api_level = get_vsr_api_level();
+    if (vsr_api_level < 34) {
+        GTEST_SKIP() << "Applies only to VSR API level 34 or newer, this device is: "
+                     << vsr_api_level;
+    }
+    EXPECT_GE(hwInfo.versionNumber, 3)
+            << "VSR 14+ requires IRemotelyProvisionedComponent v3 or newer.";
+}
+
 }  // namespace aidl::android::hardware::security::keymint::test
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiNanIface.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiNanIface.aidl
index 070ca24..3dff5bf 100644
--- a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiNanIface.aidl
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiNanIface.aidl
@@ -50,6 +50,10 @@
   void stopSubscribeRequest(in char cmdId, in byte sessionId);
   void terminateDataPathRequest(in char cmdId, in int ndpInstanceId);
   void transmitFollowupRequest(in char cmdId, in android.hardware.wifi.NanTransmitFollowupRequest msg);
+  void initiatePairingRequest(in char cmdId, in android.hardware.wifi.NanPairingRequest msg);
+  void respondToPairingIndicationRequest(in char cmdId, in android.hardware.wifi.NanRespondToPairingIndicationRequest msg);
+  void initiateBootstrappingRequest(in char cmdId, in android.hardware.wifi.NanBootstrappingRequest msg);
+  void respondToBootstrappingIndicationRequest(in char cmdId, in android.hardware.wifi.NanBootstrappingResponse msg);
   const int MIN_DATA_PATH_CONFIG_PASSPHRASE_LENGTH = 8;
   const int MAX_DATA_PATH_CONFIG_PASSPHRASE_LENGTH = 63;
 }
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiNanIfaceEventCallback.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiNanIfaceEventCallback.aidl
index 591cd8c..b6c9d1f 100644
--- a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiNanIfaceEventCallback.aidl
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiNanIfaceEventCallback.aidl
@@ -60,4 +60,12 @@
   oneway void notifyStopSubscribeResponse(in char id, in android.hardware.wifi.NanStatus status);
   oneway void notifyTerminateDataPathResponse(in char id, in android.hardware.wifi.NanStatus status);
   oneway void notifyTransmitFollowupResponse(in char id, in android.hardware.wifi.NanStatus status);
+  oneway void eventPairingRequest(in android.hardware.wifi.NanPairingRequestInd event);
+  oneway void eventPairingConfirm(in android.hardware.wifi.NanPairingConfirmInd event);
+  oneway void notifyInitiatePairingResponse(in char id, in android.hardware.wifi.NanStatus status, in int pairingInstanceId);
+  oneway void notifyRespondToPairingIndicationResponse(in char id, in android.hardware.wifi.NanStatus status);
+  oneway void eventBootstrappingRequest(in android.hardware.wifi.NanBootstrappingRequestInd event);
+  oneway void eventBootstrappingConfirm(in android.hardware.wifi.NanBootstrappingConfirmInd event);
+  oneway void notifyInitiateBootstrappingResponse(in char id, in android.hardware.wifi.NanStatus status, in int bootstrappingInstanceId);
+  oneway void notifyRespondToBootstrappingIndicationResponse(in char id, in android.hardware.wifi.NanStatus status);
 }
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanBootstrappingConfirmInd.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanBootstrappingConfirmInd.aidl
new file mode 100644
index 0000000..65e85af
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanBootstrappingConfirmInd.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file 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.wifi;
+@VintfStability
+parcelable NanBootstrappingConfirmInd {
+  int bootstrappingInstanceId;
+  boolean acceptRequest;
+  android.hardware.wifi.NanStatus reasonCode;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanBootstrappingMethod.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanBootstrappingMethod.aidl
new file mode 100644
index 0000000..e5f0975
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanBootstrappingMethod.aidl
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file 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.wifi;
+@Backing(type="int") @VintfStability
+enum NanBootstrappingMethod {
+  BOOTSTRAPPING_OPPORTUNISTIC_MASK = 1,
+  BOOTSTRAPPING_PIN_CODE_DISPLAY_MASK = 2,
+  BOOTSTRAPPING_PASSPHRASE_DISPLAY_MASK = 4,
+  BOOTSTRAPPING_QR_DISPLAY_MASK = 8,
+  BOOTSTRAPPING_NFC_TAG_MASK = 16,
+  BOOTSTRAPPING_PIN_CODE_KEYPAD_MASK = 32,
+  BOOTSTRAPPING_PASSPHRASE_KEYPAD_MASK = 64,
+  BOOTSTRAPPING_QR_SCAN_MASK = 128,
+  BOOTSTRAPPING_NFC_READER_MASK = 256,
+  BOOTSTRAPPING_SERVICE_MANAGED_MASK = 16384,
+  BOOTSTRAPPING_HANDSHAKE_SHIP_MASK = 32768,
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanBootstrappingRequest.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanBootstrappingRequest.aidl
new file mode 100644
index 0000000..2be8924
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanBootstrappingRequest.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file 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.wifi;
+@VintfStability
+parcelable NanBootstrappingRequest {
+  int peerId;
+  byte[6] peerDiscMacAddr;
+  android.hardware.wifi.NanBootstrappingMethod requestBootstrappingMethod;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanBootstrappingRequestInd.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanBootstrappingRequestInd.aidl
new file mode 100644
index 0000000..a4398e9
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanBootstrappingRequestInd.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file 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.wifi;
+@VintfStability
+parcelable NanBootstrappingRequestInd {
+  byte discoverySessionId;
+  int peerId;
+  byte[6] peerDiscMacAddr;
+  int bootstrappingInstanceId;
+  android.hardware.wifi.NanBootstrappingMethod requestBootstrappingMethod;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanBootstrappingResponse.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanBootstrappingResponse.aidl
new file mode 100644
index 0000000..6dd9b26
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanBootstrappingResponse.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file 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.wifi;
+@VintfStability
+parcelable NanBootstrappingResponse {
+  int bootstrappingInstanceId;
+  boolean acceptRequest;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanCapabilities.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanCapabilities.aidl
index c44654e..5b59945 100644
--- a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanCapabilities.aidl
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanCapabilities.aidl
@@ -49,4 +49,7 @@
   int maxSubscribeInterfaceAddresses;
   android.hardware.wifi.NanCipherSuiteType supportedCipherSuites;
   boolean instantCommunicationModeSupportFlag;
+  boolean supports6g;
+  boolean supportsHe;
+  boolean supportsPairing;
 }
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanIdentityResolutionAttribute.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanIdentityResolutionAttribute.aidl
new file mode 100644
index 0000000..843107e
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanIdentityResolutionAttribute.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file 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.wifi;
+@VintfStability
+parcelable NanIdentityResolutionAttribute {
+  byte[8] nonce;
+  byte[8] tag;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanMatchInd.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanMatchInd.aidl
index ae430c4..6757bec 100644
--- a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanMatchInd.aidl
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanMatchInd.aidl
@@ -49,4 +49,6 @@
   int rangingMeasurementInMm;
   android.hardware.wifi.NanRangingIndication rangingIndicationType;
   byte[] scid;
+  android.hardware.wifi.NanPairingConfig peerPairingConfig;
+  android.hardware.wifi.NanIdentityResolutionAttribute peerNira;
 }
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanPairingAkm.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanPairingAkm.aidl
new file mode 100644
index 0000000..05bbaee
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanPairingAkm.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file 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.wifi;
+@Backing(type="int") @VintfStability
+enum NanPairingAkm {
+  SAE = 0,
+  PASN = 1,
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanPairingConfig.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanPairingConfig.aidl
new file mode 100644
index 0000000..1c04a96
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanPairingConfig.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file 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.wifi;
+@VintfStability
+parcelable NanPairingConfig {
+  boolean enablePairingSetup;
+  boolean enablePairingCache;
+  boolean enablePairingVerification;
+  int supportedBootstrappingMethods;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanPairingConfirmInd.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanPairingConfirmInd.aidl
new file mode 100644
index 0000000..8ecf22a
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanPairingConfirmInd.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file 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.wifi;
+@VintfStability
+parcelable NanPairingConfirmInd {
+  int pairingInstanceId;
+  boolean pairingSuccess;
+  android.hardware.wifi.NanStatus status;
+  android.hardware.wifi.NanPairingRequestType requestType;
+  boolean enablePairingCache;
+  android.hardware.wifi.NpkSecurityAssociation npksa;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanPairingRequest.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanPairingRequest.aidl
new file mode 100644
index 0000000..2a644ae
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanPairingRequest.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file 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.wifi;
+@VintfStability
+parcelable NanPairingRequest {
+  int peerId;
+  byte[6] peerDiscMacAddr;
+  android.hardware.wifi.NanPairingRequestType requestType;
+  boolean enablePairingCache;
+  byte[16] pairingIdentityKey;
+  android.hardware.wifi.NanPairingSecurityConfig securityConfig;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanPairingRequestInd.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanPairingRequestInd.aidl
new file mode 100644
index 0000000..66762b9
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanPairingRequestInd.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file 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.wifi;
+@VintfStability
+parcelable NanPairingRequestInd {
+  byte discoverySessionId;
+  int peerId;
+  byte[6] peerDiscMacAddr;
+  int pairingInstanceId;
+  android.hardware.wifi.NanPairingRequestType requestType;
+  boolean enablePairingCache;
+  android.hardware.wifi.NanIdentityResolutionAttribute peerNira;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanPairingRequestType.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanPairingRequestType.aidl
new file mode 100644
index 0000000..9e73e80
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanPairingRequestType.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file 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.wifi;
+@Backing(type="int") @VintfStability
+enum NanPairingRequestType {
+  NAN_PAIRING_SETUP = 0,
+  NAN_PAIRING_VERIFICATION = 1,
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanPairingSecurityConfig.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanPairingSecurityConfig.aidl
new file mode 100644
index 0000000..45af25d
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanPairingSecurityConfig.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file 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.wifi;
+@VintfStability
+parcelable NanPairingSecurityConfig {
+  android.hardware.wifi.NanPairingSecurityType securityType;
+  byte[32] pmk;
+  byte[] passphrase;
+  android.hardware.wifi.NanPairingAkm akm;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanPairingSecurityType.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanPairingSecurityType.aidl
new file mode 100644
index 0000000..a08a00f
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanPairingSecurityType.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file 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.wifi;
+@Backing(type="int") @VintfStability
+enum NanPairingSecurityType {
+  OPPORTUNISTIC = 0,
+  PMK = 1,
+  PASSPHRASE = 2,
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanPublishRequest.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanPublishRequest.aidl
index d8d6b1b..c49f5f9 100644
--- a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanPublishRequest.aidl
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanPublishRequest.aidl
@@ -38,4 +38,6 @@
   android.hardware.wifi.NanPublishType publishType;
   android.hardware.wifi.NanTxType txType;
   boolean autoAcceptDataPathRequests;
+  android.hardware.wifi.NanPairingConfig pairingConfig;
+  byte[16] identityKey;
 }
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanRespondToPairingIndicationRequest.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanRespondToPairingIndicationRequest.aidl
new file mode 100644
index 0000000..a58890c
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanRespondToPairingIndicationRequest.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file 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.wifi;
+@VintfStability
+parcelable NanRespondToPairingIndicationRequest {
+  boolean acceptRequest;
+  int pairingInstanceId;
+  android.hardware.wifi.NanPairingRequestType requestType;
+  boolean enablePairingCache;
+  byte[16] pairingIdentityKey;
+  android.hardware.wifi.NanPairingSecurityConfig securityConfig;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanStatusCode.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanStatusCode.aidl
index 9eaf518..0fe2245 100644
--- a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanStatusCode.aidl
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanStatusCode.aidl
@@ -47,4 +47,6 @@
   ALREADY_ENABLED = 10,
   FOLLOWUP_TX_QUEUE_FULL = 11,
   UNSUPPORTED_CONCURRENCY_NAN_DISABLED = 12,
+  INVALID_PAIRING_ID = 13,
+  INVALID_BOOTSTRAPPING_ID = 14,
 }
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanSubscribeRequest.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanSubscribeRequest.aidl
index bf176a5..96be096 100644
--- a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanSubscribeRequest.aidl
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanSubscribeRequest.aidl
@@ -41,4 +41,6 @@
   boolean shouldUseSrf;
   boolean isSsiRequiredForMatch;
   android.hardware.wifi.MacAddress[] intfAddr;
+  android.hardware.wifi.NanPairingConfig pairingConfig;
+  byte[16] identityKey;
 }
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NpkSecurityAssociation.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NpkSecurityAssociation.aidl
new file mode 100644
index 0000000..c558716
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NpkSecurityAssociation.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file 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.wifi;
+@VintfStability
+parcelable NpkSecurityAssociation {
+  byte[16] peerNanIdentityKey;
+  byte[16] localNanIdentityKey;
+  byte[32] npk;
+  android.hardware.wifi.NanPairingAkm akm;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttBw.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttBw.aidl
index bd7efff..f5bf894 100644
--- a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttBw.aidl
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttBw.aidl
@@ -34,6 +34,7 @@
 package android.hardware.wifi;
 @Backing(type="int") @VintfStability
 enum RttBw {
+  BW_UNSPECIFIED = 0,
   BW_5MHZ = 1,
   BW_10MHZ = 2,
   BW_20MHZ = 4,
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttResult.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttResult.aidl
index 743e0bd..8375dcb 100644
--- a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttResult.aidl
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttResult.aidl
@@ -57,4 +57,6 @@
   int negotiatedBurstNum;
   android.hardware.wifi.WifiInformationElement lci;
   android.hardware.wifi.WifiInformationElement lcr;
+  int channelFreqMHz;
+  android.hardware.wifi.RttBw packetBw;
 }
diff --git a/wifi/aidl/android/hardware/wifi/IWifiNanIface.aidl b/wifi/aidl/android/hardware/wifi/IWifiNanIface.aidl
index 45644b4..31c7ece 100644
--- a/wifi/aidl/android/hardware/wifi/IWifiNanIface.aidl
+++ b/wifi/aidl/android/hardware/wifi/IWifiNanIface.aidl
@@ -17,12 +17,16 @@
 package android.hardware.wifi;
 
 import android.hardware.wifi.IWifiNanIfaceEventCallback;
+import android.hardware.wifi.NanBootstrappingRequest;
+import android.hardware.wifi.NanBootstrappingResponse;
 import android.hardware.wifi.NanConfigRequest;
 import android.hardware.wifi.NanConfigRequestSupplemental;
 import android.hardware.wifi.NanEnableRequest;
 import android.hardware.wifi.NanInitiateDataPathRequest;
+import android.hardware.wifi.NanPairingRequest;
 import android.hardware.wifi.NanPublishRequest;
 import android.hardware.wifi.NanRespondToDataPathIndicationRequest;
+import android.hardware.wifi.NanRespondToPairingIndicationRequest;
 import android.hardware.wifi.NanSubscribeRequest;
 import android.hardware.wifi.NanTransmitFollowupRequest;
 
@@ -248,4 +252,62 @@
      *         |WifiStatusCode.ERROR_UNKNOWN|
      */
     void transmitFollowupRequest(in char cmdId, in NanTransmitFollowupRequest msg);
+
+    /**
+     * Initiate a NAN pairing operation: Initiator.
+     * Asynchronous response is with |IWifiNanIfaceEventCallback.notifyInitiatePairingResponse|.
+     *
+     * @param cmdId Command Id to use for this invocation.
+     * @param msg Instance of |NanPairingRequest|.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+     *         |WifiStatusCode.ERROR_INVALID_ARGS|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    void initiatePairingRequest(in char cmdId, in NanPairingRequest msg);
+
+    /**
+     * Respond to a received request indication of NAN pairing setup operation.
+     * An indication is received by the Responder from the Initiator.
+     * Asynchronous response is with
+     * |IWifiNanIfaceEventCallback.notifyRespondToPairingIndicationResponse|.
+     *
+     * @param cmdId Command Id to use for this invocation.
+     * @param msg Instance of |NanRespondToPairingIndicationRequest|.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+     *         |WifiStatusCode.ERROR_INVALID_ARGS|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    void respondToPairingIndicationRequest(
+            in char cmdId, in NanRespondToPairingIndicationRequest msg);
+
+    /**
+     * Initiate a NAN pairing bootstrapping operation: Initiator.
+     * Asynchronous response is with
+     * |IWifiNanIfaceEventCallback.notifyInitiateBootstrappingResponse|.
+     *
+     * @param cmdId Command Id to use for this invocation.
+     * @param msg Instance of |NanBootstrappingRequest|.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+     *         |WifiStatusCode.ERROR_INVALID_ARGS|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    void initiateBootstrappingRequest(in char cmdId, in NanBootstrappingRequest msg);
+
+    /**
+     * Respond to a received request indication of NAN pairing bootstrapping operation.
+     * An indication is received by the Responder from the Initiator.
+     * Asynchronous response is with
+     * |IWifiNanIfaceEventCallback.notifyRespondToPairingIndicationResponse|.
+     *
+     * @param cmdId Command Id to use for this invocation.
+     * @param msg Instance of |notifyRespondToBootstrappingIndicationResponse|.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+     *         |WifiStatusCode.ERROR_INVALID_ARGS|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    void respondToBootstrappingIndicationRequest(in char cmdId, in NanBootstrappingResponse msg);
 }
diff --git a/wifi/aidl/android/hardware/wifi/IWifiNanIfaceEventCallback.aidl b/wifi/aidl/android/hardware/wifi/IWifiNanIfaceEventCallback.aidl
index 470b7ba..6b06def 100644
--- a/wifi/aidl/android/hardware/wifi/IWifiNanIfaceEventCallback.aidl
+++ b/wifi/aidl/android/hardware/wifi/IWifiNanIfaceEventCallback.aidl
@@ -16,6 +16,8 @@
 
 package android.hardware.wifi;
 
+import android.hardware.wifi.NanBootstrappingConfirmInd;
+import android.hardware.wifi.NanBootstrappingRequestInd;
 import android.hardware.wifi.NanCapabilities;
 import android.hardware.wifi.NanClusterEventInd;
 import android.hardware.wifi.NanDataPathConfirmInd;
@@ -23,6 +25,8 @@
 import android.hardware.wifi.NanDataPathScheduleUpdateInd;
 import android.hardware.wifi.NanFollowupReceivedInd;
 import android.hardware.wifi.NanMatchInd;
+import android.hardware.wifi.NanPairingConfirmInd;
+import android.hardware.wifi.NanPairingRequestInd;
 import android.hardware.wifi.NanStatus;
 
 /**
@@ -319,4 +323,95 @@
      *        |NanStatusCode.FOLLOWUP_TX_QUEUE_FULL|
      */
     void notifyTransmitFollowupResponse(in char id, in NanStatus status);
+
+    /**
+     * Callback indicating that a NAN pairing setup/verification has been requested by
+     * an Initiator peer (received by the intended Responder).
+     *
+     * @param event NanPairingRequestInd containing event details.
+     */
+    void eventPairingRequest(in NanPairingRequestInd event);
+
+    /**
+     * Callback indicating that a NAN pairing setup/verification has been completed.
+     * Received by both Initiator and Responder.
+     *
+     * @param event NanPairingConfirmInd containing event details.
+     */
+    void eventPairingConfirm(in NanPairingConfirmInd event);
+
+    /**
+     * Callback invoked in response to an initiate NAN pairing request
+     * |IWifiNanIface.initiatePairingRequest|.
+     *
+     * @param cmdId Command Id corresponding to the original request.
+     * @param status NanStatus of the operation. Possible status codes are:
+     *        |NanStatusCode.SUCCESS|
+     *        |NanStatusCode.INVALID_ARGS|
+     *        |NanStatusCode.INTERNAL_FAILURE|
+     *        |NanStatusCode.PROTOCOL_FAILURE|
+     *        |NanStatusCode.INVALID_PEER_ID|
+     * @param pairingInstanceId ID of the new pairing being negotiated (on successful status).
+     */
+    void notifyInitiatePairingResponse(in char id, in NanStatus status, in int pairingInstanceId);
+
+    /**
+     * Callback invoked in response to a respond to NAN pairing indication request
+     * |IWifiNanIface.respondToPairingIndicationRequest|.
+     *
+     * @param cmdId Command Id corresponding to the original request.
+     * @param status NanStatus of the operation. Possible status codes are:
+     *        |NanStatusCode.SUCCESS|
+     *        |NanStatusCode.INVALID_ARGS|
+     *        |NanStatusCode.INTERNAL_FAILURE|
+     *        |NanStatusCode.PROTOCOL_FAILURE|
+     *        |NanStatusCode.INVALID_NDP_ID|
+     */
+    void notifyRespondToPairingIndicationResponse(in char id, in NanStatus status);
+
+    /**
+     * Callback indicating that a NAN bootstrapping setup has been requested by
+     * an Initiator peer (received by the intended Responder).
+     *
+     * @param event NanBootstrappingRequestInd containing event details.
+     */
+    void eventBootstrappingRequest(in NanBootstrappingRequestInd event);
+
+    /**
+     * Callback indicating that a NAN bootstrapping setuphas been completed.
+     * Received by Initiator.
+     *
+     * @param event NanBootstrappingConfirmInd containing event details.
+     */
+    void eventBootstrappingConfirm(in NanBootstrappingConfirmInd event);
+
+    /**
+     * Callback invoked in response to an initiate NAN pairing bootstrapping request
+     * |IWifiNanIface.initiateBootstrappingRequest|.
+     *
+     * @param cmdId Command Id corresponding to the original request.
+     * @param status NanStatus of the operation. Possible status codes are:
+     *        |NanStatusCode.SUCCESS|
+     *        |NanStatusCode.INVALID_ARGS|
+     *        |NanStatusCode.INTERNAL_FAILURE|
+     *        |NanStatusCode.PROTOCOL_FAILURE|
+     *        |NanStatusCode.INVALID_PEER_ID|
+     * @param bootstrappingInstanceId ID of the new pairing being negotiated (on successful status).
+     */
+    void notifyInitiateBootstrappingResponse(
+            in char id, in NanStatus status, in int bootstrappingInstanceId);
+
+    /**
+     * Callback invoked in response to a respond to pairing bootstrapping indication request
+     * |IWifiNanIface.respondToBootstrappingIndicationRequest|.
+     *
+     * @param cmdId Command Id corresponding to the original request.
+     * @param status NanStatus of the operation. Possible status codes are:
+     *        |NanStatusCode.SUCCESS|
+     *        |NanStatusCode.INVALID_ARGS|
+     *        |NanStatusCode.INTERNAL_FAILURE|
+     *        |NanStatusCode.PROTOCOL_FAILURE|
+     *        |NanStatusCode.INVALID_NDP_ID|
+     */
+    void notifyRespondToBootstrappingIndicationResponse(in char id, in NanStatus status);
 }
diff --git a/wifi/aidl/android/hardware/wifi/NanBootstrappingConfirmInd.aidl b/wifi/aidl/android/hardware/wifi/NanBootstrappingConfirmInd.aidl
new file mode 100644
index 0000000..5a539ee
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/NanBootstrappingConfirmInd.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi;
+
+import android.hardware.wifi.NanBootstrappingMethod;
+import android.hardware.wifi.NanStatus;
+
+@VintfStability
+parcelable NanBootstrappingConfirmInd {
+    /**
+     * Id of the bootstrapping session. Obtained as part of earlier
+     |IWifiNanIface.initiateBootstrappingRequest| success notification.
+     */
+    int bootstrappingInstanceId;
+
+    /**
+     * Indicate whether the bootstrapping method negotiation accept or not
+     */
+    boolean acceptRequest;
+
+    /**
+     * Failure reason if |acceptRequest| is false.
+     */
+    NanStatus reasonCode;
+}
diff --git a/wifi/aidl/android/hardware/wifi/NanBootstrappingMethod.aidl b/wifi/aidl/android/hardware/wifi/NanBootstrappingMethod.aidl
new file mode 100644
index 0000000..8960794
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/NanBootstrappingMethod.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi;
+
+/**
+ * Pairing bootstrapping method flag
+ */
+@VintfStability
+@Backing(type="int")
+enum NanBootstrappingMethod {
+    BOOTSTRAPPING_OPPORTUNISTIC_MASK = 1 << 0,
+    BOOTSTRAPPING_PIN_CODE_DISPLAY_MASK = 1 << 1,
+    BOOTSTRAPPING_PASSPHRASE_DISPLAY_MASK = 1 << 2,
+    BOOTSTRAPPING_QR_DISPLAY_MASK = 1 << 3,
+    BOOTSTRAPPING_NFC_TAG_MASK = 1 << 4,
+    BOOTSTRAPPING_PIN_CODE_KEYPAD_MASK = 1 << 5,
+    BOOTSTRAPPING_PASSPHRASE_KEYPAD_MASK = 1 << 6,
+    BOOTSTRAPPING_QR_SCAN_MASK = 1 << 7,
+    BOOTSTRAPPING_NFC_READER_MASK = 1 << 8,
+    BOOTSTRAPPING_SERVICE_MANAGED_MASK = 1 << 14,
+    BOOTSTRAPPING_HANDSHAKE_SHIP_MASK = 1 << 15
+}
diff --git a/wifi/aidl/android/hardware/wifi/NanBootstrappingRequest.aidl b/wifi/aidl/android/hardware/wifi/NanBootstrappingRequest.aidl
new file mode 100644
index 0000000..d553245
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/NanBootstrappingRequest.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi;
+
+import android.hardware.wifi.NanBootstrappingMethod;
+
+@VintfStability
+parcelable NanBootstrappingRequest {
+    /**
+     * ID of the peer. Obtained as part of an earlier |IWifiNanIfaceEventCallback.eventMatch| or
+     * |IWifiNanIfaceEventCallback.eventFollowupReceived|.
+     */
+    int peerId;
+
+    /**
+     * NAN management interface MAC address of the peer. Obtained as part of an earlier
+     * |IWifiNanIfaceEventCallback.eventMatch| or
+     * |IWifiNanIfaceEventCallback.eventFollowupReceived|.
+     */
+    byte[6] peerDiscMacAddr;
+
+    /**
+     * Bootstrapping method in the request, one of the |NanBootstrappingMethod|
+     */
+    NanBootstrappingMethod requestBootstrappingMethod;
+}
diff --git a/wifi/aidl/android/hardware/wifi/NanBootstrappingRequestInd.aidl b/wifi/aidl/android/hardware/wifi/NanBootstrappingRequestInd.aidl
new file mode 100644
index 0000000..e11122f
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/NanBootstrappingRequestInd.aidl
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi;
+
+import android.hardware.wifi.NanBootstrappingMethod;
+
+/**
+ * NAN Data path request indication message structure.
+ * Event indication received by an intended Responder when a NAN
+ * data request initiated by an Initiator.
+ */
+@VintfStability
+parcelable NanBootstrappingRequestInd {
+    /**
+     * Discovery session (publish or subscribe) ID of a previously created discovery session. The
+     * bootstrapping request is received in the context of this discovery session.
+     * NAN Spec: Service Descriptor Attribute (SDA) / Instance ID
+     */
+    byte discoverySessionId;
+    /**
+     * A unique ID of the peer. Can be subsequently used in |IWifiNanIface.transmitFollowupRequest|
+     * or to set up a data-path.
+     */
+    int peerId;
+    /**
+     * MAC address of the Initiator peer. This is the MAC address of the peer's
+     * management/discovery NAN interface.
+     */
+    byte[6] peerDiscMacAddr;
+
+    /**
+     * ID of bootstrapping session. Used to identify the bootstrapping further negotiation/APIs.
+     */
+    int bootstrappingInstanceId;
+
+    /**
+     * Bootstrapping method in the incoming request, one of the |NanBootstrappingMethod|
+     */
+    NanBootstrappingMethod requestBootstrappingMethod;
+}
diff --git a/wifi/aidl/android/hardware/wifi/NanBootstrappingResponse.aidl b/wifi/aidl/android/hardware/wifi/NanBootstrappingResponse.aidl
new file mode 100644
index 0000000..0a7d621
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/NanBootstrappingResponse.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi;
+
+import android.hardware.wifi.NanBootstrappingMethod;
+
+@VintfStability
+parcelable NanBootstrappingResponse {
+    /**
+     * ID of bootstrapping session. Used to identify the bootstrapping further negotiation/APIs.
+     */
+    int bootstrappingInstanceId;
+    /**
+     * True if accept the request, false otherwise.
+     */
+    boolean acceptRequest;
+}
diff --git a/wifi/aidl/android/hardware/wifi/NanCapabilities.aidl b/wifi/aidl/android/hardware/wifi/NanCapabilities.aidl
index 6042a05..0955b4c 100644
--- a/wifi/aidl/android/hardware/wifi/NanCapabilities.aidl
+++ b/wifi/aidl/android/hardware/wifi/NanCapabilities.aidl
@@ -82,7 +82,19 @@
      */
     NanCipherSuiteType supportedCipherSuites;
     /**
-     * Flag to indicate id instant communication mode is supported.
+     * Flag to indicate if instant communication mode is supported.
      */
     boolean instantCommunicationModeSupportFlag;
+    /**
+     * Flag to indicate if 6 GHz is supported.
+     */
+    boolean supports6g;
+    /**
+     * Flag to indicate if High Efficiency is supported.
+     */
+    boolean supportsHe;
+    /**
+     * Flag to indicate if NAN pairing is supported.
+     */
+    boolean supportsPairing;
 }
diff --git a/wifi/aidl/android/hardware/wifi/NanIdentityResolutionAttribute.aidl b/wifi/aidl/android/hardware/wifi/NanIdentityResolutionAttribute.aidl
new file mode 100644
index 0000000..917feff
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/NanIdentityResolutionAttribute.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi;
+
+/**
+ * NIRA for pairing identity resolution
+ */
+@VintfStability
+parcelable NanIdentityResolutionAttribute {
+    /**
+     * A random byte string to generate tag
+     */
+    byte[8] nonce;
+
+    /**
+     * A resolvable identity to identify Nan identity key
+     */
+    byte[8] tag;
+}
diff --git a/wifi/aidl/android/hardware/wifi/NanMatchInd.aidl b/wifi/aidl/android/hardware/wifi/NanMatchInd.aidl
index 896cde0..be2fa31 100644
--- a/wifi/aidl/android/hardware/wifi/NanMatchInd.aidl
+++ b/wifi/aidl/android/hardware/wifi/NanMatchInd.aidl
@@ -17,6 +17,8 @@
 package android.hardware.wifi;
 
 import android.hardware.wifi.NanCipherSuiteType;
+import android.hardware.wifi.NanIdentityResolutionAttribute;
+import android.hardware.wifi.NanPairingConfig;
 import android.hardware.wifi.NanRangingIndication;
 
 /**
@@ -126,4 +128,12 @@
      * setting up the Secure Data Path.
      */
     byte[] scid;
+    /**
+     * The config for NAN pairing set by the peer
+     */
+    NanPairingConfig peerPairingConfig;
+    /**
+     * The NIRA from peer for NAN pairing verification
+     */
+    NanIdentityResolutionAttribute peerNira;
 }
diff --git a/wifi/aidl/android/hardware/wifi/NanPairingAkm.aidl b/wifi/aidl/android/hardware/wifi/NanPairingAkm.aidl
new file mode 100644
index 0000000..31eeb2b
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/NanPairingAkm.aidl
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi;
+
+/**
+ * THe AKM used of NAN pairing
+ */
+@VintfStability @Backing(type="int") enum NanPairingAkm { SAE = 0, PASN=1 }
diff --git a/wifi/aidl/android/hardware/wifi/NanPairingConfig.aidl b/wifi/aidl/android/hardware/wifi/NanPairingConfig.aidl
new file mode 100644
index 0000000..4f9c3ae
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/NanPairingConfig.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi;
+
+import android.hardware.wifi.NanBootstrappingMethod;
+
+/**
+ * The NAN pairing config
+ */
+@VintfStability
+parcelable NanPairingConfig {
+    /**
+     * Enable NAN pairing setup
+     */
+    boolean enablePairingSetup;
+    /**
+     * Enable cache NIK/NPK after NAN pairing setup
+     */
+    boolean enablePairingCache;
+    /**
+     * Enable NAN pairing verification with cached NIK/NPK
+     */
+    boolean enablePairingVerification;
+    /**
+     * The set of supported bootstrapping methods. The |NanBootstrappingMethod| bit fields are used.
+     */
+    int supportedBootstrappingMethods;
+}
diff --git a/wifi/aidl/android/hardware/wifi/NanPairingConfirmInd.aidl b/wifi/aidl/android/hardware/wifi/NanPairingConfirmInd.aidl
new file mode 100644
index 0000000..cd98c72
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/NanPairingConfirmInd.aidl
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi;
+
+import android.hardware.wifi.NanDataPathChannelInfo;
+import android.hardware.wifi.NanPairingRequestType;
+import android.hardware.wifi.NanStatus;
+import android.hardware.wifi.NpkSecurityAssociation;
+
+/**
+ * NAN pairing confirmation indication structure. Event indication is
+ * received on both initiator and responder side when negotiation for a
+ * pairing finishes on success or failure.
+ */
+@VintfStability
+parcelable NanPairingConfirmInd {
+    /**
+     * ID of the pairing session.
+     */
+    int pairingInstanceId;
+    /**
+     * Indicates whether the pairing setup succeeded (true) or failed (false).
+     */
+    boolean pairingSuccess;
+    /**
+     * Failure reason if |pairingSuccess| is false.
+     */
+    NanStatus status;
+    /**
+     * Indicate the pairing session is of setup or verification
+     */
+    NanPairingRequestType requestType;
+    /**
+     * Whether should cache the negotiated NIK/NPK for future verification
+     */
+    boolean enablePairingCache;
+    /**
+     * The security association negotiated for the pairing, can be cached for future verification
+     */
+    NpkSecurityAssociation npksa;
+}
diff --git a/wifi/aidl/android/hardware/wifi/NanPairingRequest.aidl b/wifi/aidl/android/hardware/wifi/NanPairingRequest.aidl
new file mode 100644
index 0000000..6f1a072
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/NanPairingRequest.aidl
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi;
+
+import android.hardware.wifi.NanPairingRequestType;
+import android.hardware.wifi.NanPairingSecurityConfig;
+
+/**
+ * NAN pairing initiate request
+ * Which can be used for setup(the initial pairing request) or
+ * verification(re-pairing for paired devices)
+ */
+@VintfStability
+parcelable NanPairingRequest {
+    /**
+     * ID of the peer. Obtained as part of an earlier |IWifiNanIfaceEventCallback.eventMatch| or
+     * |IWifiNanIfaceEventCallback.eventFollowupReceived|.
+     */
+    int peerId;
+    /**
+     * NAN management interface MAC address of the peer. Obtained as part of an earlier
+     * |IWifiNanIfaceEventCallback.eventMatch| or
+     * |IWifiNanIfaceEventCallback.eventFollowupReceived|.
+     */
+    byte[6] peerDiscMacAddr;
+    /**
+     * Indicate the pairing session is for setup or verification
+     */
+    NanPairingRequestType requestType;
+    /**
+     * Whether to cache the negotiated NIK/NPK for future verification
+     */
+    boolean enablePairingCache;
+    /**
+     * The Identity key for pairing, can be used for pairing verification
+     */
+    byte[16] pairingIdentityKey;
+    /**
+     * Security config used for the pairing
+     */
+    NanPairingSecurityConfig securityConfig;
+}
diff --git a/wifi/aidl/android/hardware/wifi/NanPairingRequestInd.aidl b/wifi/aidl/android/hardware/wifi/NanPairingRequestInd.aidl
new file mode 100644
index 0000000..f247e45
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/NanPairingRequestInd.aidl
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi;
+
+import android.hardware.wifi.NanIdentityResolutionAttribute;
+import android.hardware.wifi.NanPairingRequestType;
+
+/**
+ * NAN pairing request indication message structure.
+ * Event indication received by an intended Responder when a
+ * pairing request initiated by an Initiator.
+ */
+@VintfStability
+parcelable NanPairingRequestInd {
+    /**
+     * Discovery session (publish or subscribe) ID of a previously created discovery session. The
+     * pairing request is received in the context of this discovery session.
+     * NAN Spec: Service Descriptor Attribute (SDA) / Instance ID
+     */
+    byte discoverySessionId;
+    /**
+     * A unique ID of the peer. Can be subsequently used in |IWifiNanIface.transmitFollowupRequest|
+     * or to set up a data-path.
+     */
+    int peerId;
+    /**
+     * MAC address of the Initiator peer. This is the MAC address of the peer's
+     * management/discovery NAN interface.
+     */
+    byte[6] peerDiscMacAddr;
+    /**
+     * ID of the NAN pairing Used to identify the pairing in further negotiation/APIs.
+     */
+    int pairingInstanceId;
+    /**
+     * Indicate the pairing session is of setup or verification
+     */
+    NanPairingRequestType requestType;
+    /**
+     * Whether should cache the negotiated NIK/NPK for future verification
+     */
+    boolean enablePairingCache;
+    /**
+     * The NIRA from peer for NAN pairing verification
+     */
+    NanIdentityResolutionAttribute peerNira;
+}
diff --git a/wifi/aidl/android/hardware/wifi/NanPairingRequestType.aidl b/wifi/aidl/android/hardware/wifi/NanPairingRequestType.aidl
new file mode 100644
index 0000000..a69d04e
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/NanPairingRequestType.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi;
+
+/**
+ * Type of the request of pairing
+ */
+@VintfStability
+@Backing(type="int")
+enum NanPairingRequestType {
+    NAN_PAIRING_SETUP = 0,
+    NAN_PAIRING_VERIFICATION
+}
diff --git a/wifi/aidl/android/hardware/wifi/NanPairingSecurityConfig.aidl b/wifi/aidl/android/hardware/wifi/NanPairingSecurityConfig.aidl
new file mode 100644
index 0000000..273c07e
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/NanPairingSecurityConfig.aidl
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi;
+
+import android.hardware.wifi.NanPairingAkm;
+import android.hardware.wifi.NanPairingSecurityType;
+
+/**
+ * Configuration of NAN data-path security.
+ */
+@VintfStability
+parcelable NanPairingSecurityConfig {
+    /**
+     * Security configuration of the NAN pairing. |NanPairingSecurityType.PMK| for verification.
+     * |NanPairingSecurityType.PASSPHRASE| and |NanPairingSecurityType.OPPORTUNISTIC| for setup
+     */
+    NanPairingSecurityType securityType;
+    /**
+     * Optional Pairwise Master Key (PMK). Must be specified (and is only used) if |securityType| is
+     * set to |NanDataPathSecurityType.PMK|.
+     * Ref: IEEE 802.11i
+     */
+    byte[32] pmk;
+    /**
+     * Optional Passphrase. Must be specified (and is only used) if |securityType| is set to
+     * |NanDataPathSecurityType.PASSPHRASE|.
+     * Min length: |IWifiNanIface.MIN_DATA_PATH_CONFIG_PASSPHRASE_LENGTH|
+     * Max length: |IWifiNanIface.MAX_DATA_PATH_CONFIG_PASSPHRASE_LENGTH|
+     * NAN Spec: Appendix: Mapping passphrase to PMK for NCS-SK Cipher Suites
+     */
+    byte[] passphrase;
+    /**
+     * The AKM for key exchange
+     */
+    NanPairingAkm akm;
+}
diff --git a/wifi/aidl/android/hardware/wifi/NanPairingSecurityType.aidl b/wifi/aidl/android/hardware/wifi/NanPairingSecurityType.aidl
new file mode 100644
index 0000000..0f97d51
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/NanPairingSecurityType.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi;
+
+/**
+ * NAN pairing security configuration options.
+ */
+@VintfStability
+@Backing(type="int")
+enum NanPairingSecurityType {
+    OPPORTUNISTIC,
+    PMK,
+    PASSPHRASE,
+}
diff --git a/wifi/aidl/android/hardware/wifi/NanPublishRequest.aidl b/wifi/aidl/android/hardware/wifi/NanPublishRequest.aidl
index 6dd079c..956a7df 100644
--- a/wifi/aidl/android/hardware/wifi/NanPublishRequest.aidl
+++ b/wifi/aidl/android/hardware/wifi/NanPublishRequest.aidl
@@ -17,6 +17,7 @@
 package android.hardware.wifi;
 
 import android.hardware.wifi.NanDiscoveryCommonConfig;
+import android.hardware.wifi.NanPairingConfig;
 import android.hardware.wifi.NanPublishType;
 import android.hardware.wifi.NanTxType;
 
@@ -46,4 +47,12 @@
      * the device must automatically accept the data-path request and complete the negotiation.
      */
     boolean autoAcceptDataPathRequests;
+    /**
+     * The config for NAN pairing
+     */
+    NanPairingConfig pairingConfig;
+    /**
+     * The Identity key for pairing, will generate NIRA for verification by the peer
+     */
+    byte[16] identityKey;
 }
diff --git a/wifi/aidl/android/hardware/wifi/NanRespondToPairingIndicationRequest.aidl b/wifi/aidl/android/hardware/wifi/NanRespondToPairingIndicationRequest.aidl
new file mode 100644
index 0000000..456b430
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/NanRespondToPairingIndicationRequest.aidl
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi;
+
+import android.hardware.wifi.NanPairingRequestType;
+import android.hardware.wifi.NanPairingSecurityConfig;
+
+/**
+ * Response to a pairing request from a peer.
+ */
+@VintfStability
+parcelable NanRespondToPairingIndicationRequest {
+    /**
+     * Accept (true) or reject (false) the request.
+     * NAN Spec: Data Path Attributes / NDP Attribute / Type and Status
+     */
+    boolean acceptRequest;
+    /**
+     * ID of the NAN pairing for which we're responding. Obtained as part of the request in
+     * |IWifiNanIfaceEventCallback.eventPairingRequest|.
+     */
+    int pairingInstanceId;
+    /**
+     * Indicate the pairing session is of setup or verification
+     */
+    NanPairingRequestType requestType;
+    /**
+     * Whether should cache the negotiated NIK/NPK for future verification
+     */
+    boolean enablePairingCache;
+    /**
+     * The Identity key for pairing, can be used for pairing verification
+     */
+    byte[16] pairingIdentityKey;
+    /**
+     * Security config used for the pairing
+     */
+    NanPairingSecurityConfig securityConfig;
+}
diff --git a/wifi/aidl/android/hardware/wifi/NanStatusCode.aidl b/wifi/aidl/android/hardware/wifi/NanStatusCode.aidl
index d63a50e..efce867 100644
--- a/wifi/aidl/android/hardware/wifi/NanStatusCode.aidl
+++ b/wifi/aidl/android/hardware/wifi/NanStatusCode.aidl
@@ -71,4 +71,12 @@
      * Unsupported concurrency of NAN and another feature - NAN disabled.
      */
     UNSUPPORTED_CONCURRENCY_NAN_DISABLED = 12,
+    /**
+     * If the pairing id is invalid
+     */
+    INVALID_PAIRING_ID = 13,
+    /**
+     * If the bootstrapping id is invalid
+     */
+    INVALID_BOOTSTRAPPING_ID = 14
 }
diff --git a/wifi/aidl/android/hardware/wifi/NanSubscribeRequest.aidl b/wifi/aidl/android/hardware/wifi/NanSubscribeRequest.aidl
index 12c1170..0b246ed 100644
--- a/wifi/aidl/android/hardware/wifi/NanSubscribeRequest.aidl
+++ b/wifi/aidl/android/hardware/wifi/NanSubscribeRequest.aidl
@@ -18,6 +18,7 @@
 
 import android.hardware.wifi.MacAddress;
 import android.hardware.wifi.NanDiscoveryCommonConfig;
+import android.hardware.wifi.NanPairingConfig;
 import android.hardware.wifi.NanSrfType;
 import android.hardware.wifi.NanSubscribeType;
 
@@ -67,4 +68,12 @@
      * NAN Spec: Service Descriptor Attribute (SDA) / Service Response Filter / Address Set
      */
     MacAddress[] intfAddr;
+    /**
+     * Security config used for the pairing
+     */
+    NanPairingConfig pairingConfig;
+    /**
+     * The Identity key for pairing, will generate NIRA for verification by the peer
+     */
+    byte[16] identityKey;
 }
diff --git a/wifi/aidl/android/hardware/wifi/NpkSecurityAssociation.aidl b/wifi/aidl/android/hardware/wifi/NpkSecurityAssociation.aidl
new file mode 100644
index 0000000..42612c0
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/NpkSecurityAssociation.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi;
+
+import android.hardware.wifi.NanPairingAkm;
+
+/**
+ * The security sssociation info after Aware Pairing setup.
+ */
+@VintfStability
+parcelable NpkSecurityAssociation {
+    /**
+     * The Aware pairing identity from the peer
+     */
+    byte[16] peerNanIdentityKey;
+    /**
+     * The Aware pairing identity for local device
+     */
+    byte[16] localNanIdentityKey;
+    /**
+     * The PMK is used in this security association
+     */
+    byte[32] npk;
+    /**
+     * The AKM is used for key exchange in this security sssociation
+     */
+    NanPairingAkm akm;
+}
diff --git a/wifi/aidl/android/hardware/wifi/RttBw.aidl b/wifi/aidl/android/hardware/wifi/RttBw.aidl
index 9d42dc0..be9ecbd 100644
--- a/wifi/aidl/android/hardware/wifi/RttBw.aidl
+++ b/wifi/aidl/android/hardware/wifi/RttBw.aidl
@@ -22,6 +22,7 @@
 @VintfStability
 @Backing(type="int")
 enum RttBw {
+    BW_UNSPECIFIED = 0x0,
     BW_5MHZ = 0x01,
     BW_10MHZ = 0x02,
     BW_20MHZ = 0x04,
diff --git a/wifi/aidl/android/hardware/wifi/RttResult.aidl b/wifi/aidl/android/hardware/wifi/RttResult.aidl
index 565cce7..6c45e2c 100644
--- a/wifi/aidl/android/hardware/wifi/RttResult.aidl
+++ b/wifi/aidl/android/hardware/wifi/RttResult.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.wifi;
 
+import android.hardware.wifi.RttBw;
 import android.hardware.wifi.RttStatus;
 import android.hardware.wifi.RttType;
 import android.hardware.wifi.WifiInformationElement;
@@ -132,4 +133,15 @@
      * For 11mc only.
      */
     WifiInformationElement lcr;
+    /**
+     * RTT channel frequency in MHz
+     * If frequency is unknown, this will be set to 0.
+     */
+    int channelFreqMHz;
+    /**
+     * RTT packet bandwidth.
+     * This value is an average bandwidth of the bandwidths of measurement
+     * frames. Cap the average close to a specific valid RttBw.
+     */
+    RttBw packetBw;
 }
diff --git a/wifi/aidl/default/aidl_struct_util.cpp b/wifi/aidl/default/aidl_struct_util.cpp
index 3087d66..22319ae 100644
--- a/wifi/aidl/default/aidl_struct_util.cpp
+++ b/wifi/aidl/default/aidl_struct_util.cpp
@@ -1261,6 +1261,165 @@
     CHECK(false);
 }
 
+legacy_hal::NanPairingRequestType convertAidlNanPairingRequestTypeToLegacy(
+        NanPairingRequestType type) {
+    switch (type) {
+        case NanPairingRequestType::NAN_PAIRING_SETUP:
+            return legacy_hal::NAN_PAIRING_SETUP;
+        case NanPairingRequestType::NAN_PAIRING_VERIFICATION:
+            return legacy_hal::NAN_PAIRING_VERIFICATION;
+    }
+    LOG(FATAL);
+}
+
+NanPairingRequestType convertLegacyNanPairingRequestTypeToAidl(
+        legacy_hal::NanPairingRequestType type) {
+    switch (type) {
+        case legacy_hal::NAN_PAIRING_SETUP:
+            return NanPairingRequestType::NAN_PAIRING_SETUP;
+        case legacy_hal::NAN_PAIRING_VERIFICATION:
+            return NanPairingRequestType::NAN_PAIRING_VERIFICATION;
+    }
+    LOG(FATAL);
+}
+
+legacy_hal::Akm convertAidlAkmTypeToLegacy(NanPairingAkm type) {
+    switch (type) {
+        case NanPairingAkm::SAE:
+            return legacy_hal::SAE;
+        case NanPairingAkm::PASN:
+            return legacy_hal::PASN;
+    }
+    LOG(FATAL);
+}
+
+NanPairingAkm convertLegacyAkmTypeToAidl(legacy_hal::Akm type) {
+    switch (type) {
+        case legacy_hal::SAE:
+            return NanPairingAkm::SAE;
+        case legacy_hal::PASN:
+            return NanPairingAkm::PASN;
+    }
+    LOG(FATAL);
+}
+
+uint16_t convertAidlBootstrappingMethodToLegacy(NanBootstrappingMethod type) {
+    switch (type) {
+        case NanBootstrappingMethod::BOOTSTRAPPING_OPPORTUNISTIC_MASK:
+            return NAN_PAIRING_BOOTSTRAPPING_OPPORTUNISTIC_MASK;
+        case NanBootstrappingMethod::BOOTSTRAPPING_PIN_CODE_DISPLAY_MASK:
+            return NAN_PAIRING_BOOTSTRAPPING_PIN_CODE_DISPLAY_MASK;
+        case NanBootstrappingMethod::BOOTSTRAPPING_PASSPHRASE_DISPLAY_MASK:
+            return NAN_PAIRING_BOOTSTRAPPING_PASSPHRASE_DISPLAY_MASK;
+        case NanBootstrappingMethod::BOOTSTRAPPING_QR_DISPLAY_MASK:
+            return NAN_PAIRING_BOOTSTRAPPING_QR_DISPLAY_MASK;
+        case NanBootstrappingMethod::BOOTSTRAPPING_NFC_TAG_MASK:
+            return NAN_PAIRING_BOOTSTRAPPING_NFC_TAG_MASK;
+        case NanBootstrappingMethod::BOOTSTRAPPING_PIN_CODE_KEYPAD_MASK:
+            return NAN_PAIRING_BOOTSTRAPPING_PIN_CODE_KEYPAD_MASK;
+        case NanBootstrappingMethod::BOOTSTRAPPING_PASSPHRASE_KEYPAD_MASK:
+            return NAN_PAIRING_BOOTSTRAPPING_PASSPHRASE_KEYPAD_MASK;
+        case NanBootstrappingMethod::BOOTSTRAPPING_QR_SCAN_MASK:
+            return NAN_PAIRING_BOOTSTRAPPING_QR_SCAN_MASK;
+        case NanBootstrappingMethod::BOOTSTRAPPING_NFC_READER_MASK:
+            return NAN_PAIRING_BOOTSTRAPPING_NFC_READER_MASK;
+        case NanBootstrappingMethod::BOOTSTRAPPING_SERVICE_MANAGED_MASK:
+            return NAN_PAIRING_BOOTSTRAPPING_SERVICE_MANAGED_MASK;
+        case NanBootstrappingMethod::BOOTSTRAPPING_HANDSHAKE_SHIP_MASK:
+            return NAN_PAIRING_BOOTSTRAPPING_HANDSHAKE_SHIP_MASK;
+    }
+    LOG(FATAL);
+}
+
+NanBootstrappingMethod convertLegacyBootstrappingMethodToAidl(uint16_t type) {
+    switch (type) {
+        case NAN_PAIRING_BOOTSTRAPPING_OPPORTUNISTIC_MASK:
+            return NanBootstrappingMethod::BOOTSTRAPPING_OPPORTUNISTIC_MASK;
+        case NAN_PAIRING_BOOTSTRAPPING_PIN_CODE_DISPLAY_MASK:
+            return NanBootstrappingMethod::BOOTSTRAPPING_PIN_CODE_DISPLAY_MASK;
+        case NAN_PAIRING_BOOTSTRAPPING_PASSPHRASE_DISPLAY_MASK:
+            return NanBootstrappingMethod::BOOTSTRAPPING_PASSPHRASE_DISPLAY_MASK;
+        case NAN_PAIRING_BOOTSTRAPPING_QR_DISPLAY_MASK:
+            return NanBootstrappingMethod::BOOTSTRAPPING_QR_DISPLAY_MASK;
+        case NAN_PAIRING_BOOTSTRAPPING_NFC_TAG_MASK:
+            return NanBootstrappingMethod::BOOTSTRAPPING_NFC_TAG_MASK;
+        case NAN_PAIRING_BOOTSTRAPPING_PIN_CODE_KEYPAD_MASK:
+            return NanBootstrappingMethod::BOOTSTRAPPING_PIN_CODE_KEYPAD_MASK;
+        case NAN_PAIRING_BOOTSTRAPPING_PASSPHRASE_KEYPAD_MASK:
+            return NanBootstrappingMethod::BOOTSTRAPPING_PASSPHRASE_KEYPAD_MASK;
+        case NAN_PAIRING_BOOTSTRAPPING_QR_SCAN_MASK:
+            return NanBootstrappingMethod::BOOTSTRAPPING_QR_SCAN_MASK;
+        case NAN_PAIRING_BOOTSTRAPPING_NFC_READER_MASK:
+            return NanBootstrappingMethod::BOOTSTRAPPING_NFC_READER_MASK;
+        case NAN_PAIRING_BOOTSTRAPPING_SERVICE_MANAGED_MASK:
+            return NanBootstrappingMethod::BOOTSTRAPPING_SERVICE_MANAGED_MASK;
+        case NAN_PAIRING_BOOTSTRAPPING_HANDSHAKE_SHIP_MASK:
+            return NanBootstrappingMethod::BOOTSTRAPPING_HANDSHAKE_SHIP_MASK;
+    }
+    LOG(FATAL);
+    return {};
+}
+
+bool covertAidlPairingConfigToLegacy(const NanPairingConfig& aidl_config,
+                                     legacy_hal::NanPairingConfig* legacy_config) {
+    if (!legacy_config) {
+        LOG(ERROR) << "covertAidlPairingConfigToLegacy: legacy_config is null";
+        return false;
+    }
+    legacy_config->enable_pairing_setup = aidl_config.enablePairingSetup ? 0x1 : 0x0;
+    legacy_config->enable_pairing_cache = aidl_config.enablePairingCache ? 0x1 : 0x0;
+    legacy_config->enable_pairing_verification = aidl_config.enablePairingVerification ? 0x1 : 0x0;
+    legacy_config->supported_bootstrapping_methods = aidl_config.supportedBootstrappingMethods;
+    return true;
+}
+
+bool convertLegacyPairingConfigToAidl(const legacy_hal::NanPairingConfig& legacy_config,
+                                      NanPairingConfig* aidl_config) {
+    if (!aidl_config) {
+        LOG(ERROR) << "convertLegacyPairingConfigToAidl: aidl_nira is null";
+        return false;
+    }
+    *aidl_config = {};
+    aidl_config->enablePairingSetup = legacy_config.enable_pairing_setup == 0x1;
+    aidl_config->enablePairingCache = legacy_config.enable_pairing_cache == 0x1;
+    aidl_config->enablePairingVerification = legacy_config.enable_pairing_verification == 0x1;
+    aidl_config->supportedBootstrappingMethods = legacy_config.supported_bootstrapping_methods;
+    return true;
+}
+
+bool convertLegacyNiraToAidl(const legacy_hal::NanIdentityResolutionAttribute& legacy_nira,
+                             NanIdentityResolutionAttribute* aidl_nira) {
+    if (!aidl_nira) {
+        LOG(ERROR) << "convertLegacyNiraToAidl: aidl_nira is null";
+        return false;
+    }
+    *aidl_nira = {};
+    aidl_nira->nonce = std::array<uint8_t, 8>();
+    std::copy(legacy_nira.nonce, legacy_nira.nonce + 8, std::begin(aidl_nira->nonce));
+    aidl_nira->tag = std::array<uint8_t, 8>();
+    std::copy(legacy_nira.tag, legacy_nira.tag + 8, std::begin(aidl_nira->tag));
+    return true;
+}
+
+bool convertLegacyNpsaToAidl(const legacy_hal::NpkSecurityAssociation& legacy_npsa,
+                             NpkSecurityAssociation* aidl_npsa) {
+    if (!aidl_npsa) {
+        LOG(ERROR) << "convertLegacyNiraToAidl: aidl_nira is null";
+        return false;
+    }
+    *aidl_npsa = {};
+    aidl_npsa->peerNanIdentityKey = std::array<uint8_t, 16>();
+    std::copy(legacy_npsa.peer_nan_identity_key, legacy_npsa.peer_nan_identity_key + 16,
+              std::begin(aidl_npsa->peerNanIdentityKey));
+    aidl_npsa->localNanIdentityKey = std::array<uint8_t, 16>();
+    std::copy(legacy_npsa.local_nan_identity_key, legacy_npsa.local_nan_identity_key + 16,
+              std::begin(aidl_npsa->localNanIdentityKey));
+    aidl_npsa->npk = std::array<uint8_t, 32>();
+    std::copy(legacy_npsa.npk.pmk, legacy_npsa.npk.pmk + 32, std::begin(aidl_npsa->npk));
+    aidl_npsa->akm = convertLegacyAkmTypeToAidl(legacy_npsa.akm);
+    return true;
+}
+
 NanStatusCode convertLegacyNanStatusTypeToAidl(legacy_hal::NanStatusType type) {
     switch (type) {
         case legacy_hal::NAN_STATUS_SUCCESS:
@@ -1289,6 +1448,10 @@
             return NanStatusCode::FOLLOWUP_TX_QUEUE_FULL;
         case legacy_hal::NAN_STATUS_UNSUPPORTED_CONCURRENCY_NAN_DISABLED:
             return NanStatusCode::UNSUPPORTED_CONCURRENCY_NAN_DISABLED;
+        case legacy_hal::NAN_STATUS_INVALID_PAIRING_ID:
+            return NanStatusCode::INVALID_PAIRING_ID;
+        case legacy_hal::NAN_STATUS_INVALID_BOOTSTRAPPING_ID:
+            return NanStatusCode::INVALID_BOOTSTRAPPING_ID;
     }
     CHECK(false);
 }
@@ -1679,6 +1842,12 @@
     legacy_request->service_responder_policy = aidl_request.autoAcceptDataPathRequests
                                                        ? legacy_hal::NAN_SERVICE_ACCEPT_POLICY_ALL
                                                        : legacy_hal::NAN_SERVICE_ACCEPT_POLICY_NONE;
+    memcpy(legacy_request->nan_identity_key, aidl_request.identityKey.data(), NAN_IDENTITY_KEY_LEN);
+    if (!covertAidlPairingConfigToLegacy(aidl_request.pairingConfig,
+                                         &legacy_request->nan_pairing_config)) {
+        LOG(ERROR) << "convertAidlNanPublishRequestToLegacy: invalid pairing config";
+        return false;
+    }
 
     return true;
 }
@@ -1819,7 +1988,12 @@
     for (int i = 0; i < legacy_request->num_intf_addr_present; i++) {
         memcpy(legacy_request->intf_addr[i], aidl_request.intfAddr[i].data.data(), 6);
     }
-
+    memcpy(legacy_request->nan_identity_key, aidl_request.identityKey.data(), NAN_IDENTITY_KEY_LEN);
+    if (!covertAidlPairingConfigToLegacy(aidl_request.pairingConfig,
+                                         &legacy_request->nan_pairing_config)) {
+        LOG(ERROR) << "convertAidlNanSubscribeRequestToLegacy: invalid pairing config";
+        return false;
+    }
     return true;
 }
 
@@ -2068,7 +2242,9 @@
     aidl_response->supportedCipherSuites =
             static_cast<NanCipherSuiteType>(legacy_response.cipher_suites_supported);
     aidl_response->instantCommunicationModeSupportFlag = legacy_response.is_instant_mode_supported;
-
+    aidl_response->supports6g = legacy_response.is_6g_supported;
+    aidl_response->supportsHe = legacy_response.is_he_supported;
+    aidl_response->supportsPairing = legacy_response.is_pairing_supported;
     return true;
 }
 
@@ -2105,6 +2281,16 @@
     aidl_ind->rangingIndicationType =
             static_cast<NanRangingIndication>(legacy_ind.range_info.ranging_event_type);
     aidl_ind->scid = std::vector<uint8_t>(legacy_ind.scid, legacy_ind.scid + legacy_ind.scid_len);
+
+    if (!convertLegacyNiraToAidl(legacy_ind.nira, &aidl_ind->peerNira)) {
+        LOG(ERROR) << "convertLegacyNanMatchIndToAidl: invalid NIRA";
+        return false;
+    }
+    if (!convertLegacyPairingConfigToAidl(legacy_ind.peer_pairing_config,
+                                          &aidl_ind->peerPairingConfig)) {
+        LOG(ERROR) << "convertLegacyNanMatchIndToAidl: invalid pairing config";
+        return false;
+    }
     return true;
 }
 
@@ -2363,6 +2549,8 @@
             return legacy_hal::WIFI_RTT_BW_160;
         case RttBw::BW_320MHZ:
             return legacy_hal::WIFI_RTT_BW_320;
+        case RttBw::BW_UNSPECIFIED:
+            return legacy_hal::WIFI_RTT_BW_UNSPECIFIED;
     };
     CHECK(false);
 }
@@ -2383,6 +2571,8 @@
             return RttBw::BW_160MHZ;
         case legacy_hal::WIFI_RTT_BW_320:
             return RttBw::BW_320MHZ;
+        case legacy_hal::WIFI_RTT_BW_UNSPECIFIED:
+            return RttBw::BW_UNSPECIFIED;
     };
     CHECK(false) << "Unknown legacy type: " << type;
 }
@@ -2712,6 +2902,28 @@
         if (!convertLegacyRttResultToAidl(*legacy_result, &aidl_result)) {
             return false;
         }
+        aidl_result.channelFreqMHz = 0;
+        aidl_result.packetBw = RttBw::BW_UNSPECIFIED;
+        aidl_results->push_back(aidl_result);
+    }
+    return true;
+}
+
+bool convertLegacyVectorOfRttResultV2ToAidl(
+        const std::vector<const legacy_hal::wifi_rtt_result_v2*>& legacy_results,
+        std::vector<RttResult>* aidl_results) {
+    if (!aidl_results) {
+        return false;
+    }
+    *aidl_results = {};
+    for (const auto legacy_result : legacy_results) {
+        RttResult aidl_result;
+        if (!convertLegacyRttResultToAidl(legacy_result->rtt_result, &aidl_result)) {
+            return false;
+        }
+        aidl_result.channelFreqMHz =
+                legacy_result->frequency != UNSPECIFIED ? legacy_result->frequency : 0;
+        aidl_result.packetBw = convertLegacyRttBwToAidl(legacy_result->packet_bw);
         aidl_results->push_back(aidl_result);
     }
     return true;
@@ -2861,6 +3073,235 @@
     return true;
 }
 
+bool convertAidlNanPairingInitiatorRequestToLegacy(const NanPairingRequest& aidl_request,
+                                                   legacy_hal::NanPairingRequest* legacy_request) {
+    if (!legacy_request) {
+        LOG(ERROR) << "convertAidlNanPairingInitiatorRequestToLegacy: "
+                      "legacy_request is null";
+        return false;
+    }
+    *legacy_request = {};
+
+    legacy_request->requestor_instance_id = aidl_request.peerId;
+    memcpy(legacy_request->peer_disc_mac_addr, aidl_request.peerDiscMacAddr.data(), 6);
+    legacy_request->nan_pairing_request_type =
+            convertAidlNanPairingRequestTypeToLegacy(aidl_request.requestType);
+    legacy_request->enable_pairing_cache = aidl_request.enablePairingCache;
+
+    memcpy(legacy_request->nan_identity_key, aidl_request.pairingIdentityKey.data(),
+           NAN_IDENTITY_KEY_LEN);
+
+    legacy_request->is_opportunistic =
+            aidl_request.securityConfig.securityType == NanPairingSecurityType::OPPORTUNISTIC ? 1
+                                                                                              : 0;
+    legacy_request->akm = convertAidlAkmTypeToLegacy(aidl_request.securityConfig.akm);
+    if (aidl_request.securityConfig.securityType == NanPairingSecurityType::PMK) {
+        legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PMK;
+        legacy_request->key_info.body.pmk_info.pmk_len = aidl_request.securityConfig.pmk.size();
+        if (legacy_request->key_info.body.pmk_info.pmk_len != NAN_PMK_INFO_LEN) {
+            LOG(ERROR) << "convertAidlNanPairingInitiatorRequestToLegacy: "
+                          "invalid pmk_len";
+            return false;
+        }
+        memcpy(legacy_request->key_info.body.pmk_info.pmk, aidl_request.securityConfig.pmk.data(),
+               legacy_request->key_info.body.pmk_info.pmk_len);
+    }
+    if (aidl_request.securityConfig.securityType == NanPairingSecurityType::PASSPHRASE) {
+        legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PASSPHRASE;
+        legacy_request->key_info.body.passphrase_info.passphrase_len =
+                aidl_request.securityConfig.passphrase.size();
+        if (legacy_request->key_info.body.passphrase_info.passphrase_len <
+            NAN_SECURITY_MIN_PASSPHRASE_LEN) {
+            LOG(ERROR) << "convertAidlNanPairingInitiatorRequestToLegacy: "
+                          "passphrase_len too small";
+            return false;
+        }
+        if (legacy_request->key_info.body.passphrase_info.passphrase_len >
+            NAN_SECURITY_MAX_PASSPHRASE_LEN) {
+            LOG(ERROR) << "convertAidlNanPairingInitiatorRequestToLegacy: "
+                          "passphrase_len too large";
+            return false;
+        }
+        memcpy(legacy_request->key_info.body.passphrase_info.passphrase,
+               aidl_request.securityConfig.passphrase.data(),
+               legacy_request->key_info.body.passphrase_info.passphrase_len);
+    }
+
+    return true;
+}
+
+bool convertAidlNanPairingIndicationResponseToLegacy(
+        const NanRespondToPairingIndicationRequest& aidl_request,
+        legacy_hal::NanPairingIndicationResponse* legacy_request) {
+    if (!legacy_request) {
+        LOG(ERROR) << "convertAidlNanPairingIndicationResponseToLegacy: "
+                      "legacy_request is null";
+        return false;
+    }
+    *legacy_request = {};
+
+    legacy_request->pairing_instance_id = aidl_request.pairingInstanceId;
+    legacy_request->nan_pairing_request_type =
+            convertAidlNanPairingRequestTypeToLegacy(aidl_request.requestType);
+    legacy_request->enable_pairing_cache = aidl_request.enablePairingCache;
+
+    memcpy(legacy_request->nan_identity_key, aidl_request.pairingIdentityKey.data(),
+           NAN_IDENTITY_KEY_LEN);
+
+    legacy_request->is_opportunistic =
+            aidl_request.securityConfig.securityType == NanPairingSecurityType::OPPORTUNISTIC ? 1
+                                                                                              : 0;
+    legacy_request->akm = convertAidlAkmTypeToLegacy(aidl_request.securityConfig.akm);
+    legacy_request->rsp_code =
+            aidl_request.acceptRequest ? NAN_PAIRING_REQUEST_ACCEPT : NAN_PAIRING_REQUEST_REJECT;
+    if (aidl_request.securityConfig.securityType == NanPairingSecurityType::PMK) {
+        legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PMK;
+        legacy_request->key_info.body.pmk_info.pmk_len = aidl_request.securityConfig.pmk.size();
+        if (legacy_request->key_info.body.pmk_info.pmk_len != NAN_PMK_INFO_LEN) {
+            LOG(ERROR) << "convertAidlNanPairingIndicationResponseToLegacy: "
+                          "invalid pmk_len";
+            return false;
+        }
+        memcpy(legacy_request->key_info.body.pmk_info.pmk, aidl_request.securityConfig.pmk.data(),
+               legacy_request->key_info.body.pmk_info.pmk_len);
+    }
+    if (aidl_request.securityConfig.securityType == NanPairingSecurityType::PASSPHRASE) {
+        legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PASSPHRASE;
+        legacy_request->key_info.body.passphrase_info.passphrase_len =
+                aidl_request.securityConfig.passphrase.size();
+        if (legacy_request->key_info.body.passphrase_info.passphrase_len <
+            NAN_SECURITY_MIN_PASSPHRASE_LEN) {
+            LOG(ERROR) << "convertAidlNanPairingIndicationResponseToLegacy: "
+                          "passphrase_len too small";
+            return false;
+        }
+        if (legacy_request->key_info.body.passphrase_info.passphrase_len >
+            NAN_SECURITY_MAX_PASSPHRASE_LEN) {
+            LOG(ERROR) << "convertAidlNanPairingIndicationResponseToLegacy: "
+                          "passphrase_len too large";
+            return false;
+        }
+        memcpy(legacy_request->key_info.body.passphrase_info.passphrase,
+               aidl_request.securityConfig.passphrase.data(),
+               legacy_request->key_info.body.passphrase_info.passphrase_len);
+    }
+
+    return true;
+}
+
+bool convertAidlNanBootstrappingInitiatorRequestToLegacy(
+        const NanBootstrappingRequest& aidl_request,
+        legacy_hal::NanBootstrappingRequest* legacy_request) {
+    if (!legacy_request) {
+        LOG(ERROR) << "convertAidlNanBootstrappingInitiatorRequestToLegacy: "
+                      "legacy_request is null";
+        return false;
+    }
+    *legacy_request = {};
+
+    legacy_request->requestor_instance_id = aidl_request.peerId;
+    memcpy(legacy_request->peer_disc_mac_addr, aidl_request.peerDiscMacAddr.data(), 6);
+    legacy_request->request_bootstrapping_method =
+            convertAidlBootstrappingMethodToLegacy(aidl_request.requestBootstrappingMethod);
+
+    return true;
+}
+
+bool convertAidlNanBootstrappingIndicationResponseToLegacy(
+        const NanBootstrappingResponse& aidl_request,
+        legacy_hal::NanBootstrappingIndicationResponse* legacy_request) {
+    if (!legacy_request) {
+        LOG(ERROR) << "convertAidlNanBootstrappingIndicationResponseToLegacy: "
+                      "legacy_request is null";
+        return false;
+    }
+    *legacy_request = {};
+
+    legacy_request->service_instance_id = aidl_request.bootstrappingInstanceId;
+    legacy_request->rsp_code = aidl_request.acceptRequest ? NAN_BOOTSTRAPPING_REQUEST_ACCEPT
+                                                          : NAN_BOOTSTRAPPING_REQUEST_REJECT;
+
+    return true;
+}
+
+bool convertLegacyNanPairingRequestIndToAidl(const legacy_hal::NanPairingRequestInd& legacy_ind,
+                                             NanPairingRequestInd* aidl_ind) {
+    if (!aidl_ind) {
+        LOG(ERROR) << "convertLegacyNanPairingRequestIndToAidl: aidl_ind is null";
+        return false;
+    }
+    *aidl_ind = {};
+
+    aidl_ind->discoverySessionId = legacy_ind.publish_subscribe_id;
+    aidl_ind->peerId = legacy_ind.requestor_instance_id;
+    aidl_ind->peerDiscMacAddr = std::array<uint8_t, 6>();
+    std::copy(legacy_ind.peer_disc_mac_addr, legacy_ind.peer_disc_mac_addr + 6,
+              std::begin(aidl_ind->peerDiscMacAddr));
+    aidl_ind->pairingInstanceId = legacy_ind.pairing_instance_id;
+    aidl_ind->enablePairingCache = legacy_ind.enable_pairing_cache == 1;
+    aidl_ind->requestType =
+            convertLegacyNanPairingRequestTypeToAidl(legacy_ind.nan_pairing_request_type);
+    if (!convertLegacyNiraToAidl(legacy_ind.nira, &aidl_ind->peerNira)) {
+        return false;
+    }
+    return true;
+}
+
+bool convertLegacyNanPairingConfirmIndToAidl(const legacy_hal::NanPairingConfirmInd& legacy_ind,
+                                             NanPairingConfirmInd* aidl_ind) {
+    if (!aidl_ind) {
+        LOG(ERROR) << "convertLegacyNanPairingRequestIndToAidl: aidl_ind is null";
+        return false;
+    }
+    *aidl_ind = {};
+
+    aidl_ind->pairingInstanceId = legacy_ind.pairing_instance_id;
+    aidl_ind->enablePairingCache = legacy_ind.enable_pairing_cache == 1;
+    aidl_ind->requestType =
+            convertLegacyNanPairingRequestTypeToAidl(legacy_ind.nan_pairing_request_type);
+    aidl_ind->pairingSuccess = legacy_ind.rsp_code == NAN_PAIRING_REQUEST_ACCEPT;
+    aidl_ind->status.status = convertLegacyNanStatusTypeToAidl(legacy_ind.reason_code);
+    if (!convertLegacyNpsaToAidl(legacy_ind.npk_security_association, &aidl_ind->npksa)) {
+        return false;
+    }
+    return true;
+}
+
+bool convertLegacyNanBootstrappingRequestIndToAidl(
+        const legacy_hal::NanBootstrappingRequestInd& legacy_ind,
+        NanBootstrappingRequestInd* aidl_ind) {
+    if (!aidl_ind) {
+        LOG(ERROR) << "convertLegacyNanBootstrappingRequestIndToAidl: aidl_ind is null";
+        return false;
+    }
+    *aidl_ind = {};
+
+    aidl_ind->discoverySessionId = legacy_ind.publish_subscribe_id;
+    aidl_ind->peerId = legacy_ind.requestor_instance_id;
+    aidl_ind->peerDiscMacAddr = std::array<uint8_t, 6>();
+    std::copy(legacy_ind.peer_disc_mac_addr, legacy_ind.peer_disc_mac_addr + 6,
+              std::begin(aidl_ind->peerDiscMacAddr));
+    aidl_ind->bootstrappingInstanceId = legacy_ind.bootstrapping_instance_id;
+    aidl_ind->requestBootstrappingMethod =
+            convertLegacyBootstrappingMethodToAidl(legacy_ind.request_bootstrapping_method);
+    return true;
+}
+
+bool convertLegacyNanBootstrappingConfirmIndToAidl(
+        const legacy_hal::NanBootstrappingConfirmInd& legacy_ind,
+        NanBootstrappingConfirmInd* aidl_ind) {
+    if (!aidl_ind) {
+        LOG(ERROR) << "convertLegacyNanBootstrappingConfirmIndToAidl: aidl_ind is null";
+        return false;
+    }
+    *aidl_ind = {};
+
+    aidl_ind->bootstrappingInstanceId = legacy_ind.bootstrapping_instance_id;
+    aidl_ind->acceptRequest = legacy_ind.rsp_code == NAN_BOOTSTRAPPING_REQUEST_ACCEPT;
+    aidl_ind->reasonCode.status = convertLegacyNanStatusTypeToAidl(legacy_ind.reason_code);
+    return true;
+}
+
 bool convertLegacyWifiChipCapabilitiesToAidl(
         const legacy_hal::wifi_chip_capabilities& legacy_chip_capabilities,
         WifiChipCapabilities& aidl_chip_capabilities) {
diff --git a/wifi/aidl/default/aidl_struct_util.h b/wifi/aidl/default/aidl_struct_util.h
index ac86755..e478fed 100644
--- a/wifi/aidl/default/aidl_struct_util.h
+++ b/wifi/aidl/default/aidl_struct_util.h
@@ -163,6 +163,9 @@
 bool convertLegacyVectorOfRttResultToAidl(
         const std::vector<const legacy_hal::wifi_rtt_result*>& legacy_results,
         std::vector<RttResult>* aidl_results);
+bool convertLegacyVectorOfRttResultV2ToAidl(
+        const std::vector<const legacy_hal::wifi_rtt_result_v2*>& legacy_results,
+        std::vector<RttResult>* aidl_results);
 uint32_t convertAidlWifiBandToLegacyMacBand(WifiBand band);
 uint32_t convertAidlWifiIfaceModeToLegacy(uint32_t aidl_iface_mask);
 uint32_t convertAidlUsableChannelFilterToLegacy(uint32_t aidl_filter_mask);
@@ -176,6 +179,27 @@
 bool convertLegacyWifiChipCapabilitiesToAidl(
         const legacy_hal::wifi_chip_capabilities& legacy_chip_capabilities,
         WifiChipCapabilities& aidl_chip_capabilities);
+bool convertAidlNanPairingInitiatorRequestToLegacy(const NanPairingRequest& aidl_request,
+                                                   legacy_hal::NanPairingRequest* legacy_request);
+bool convertAidlNanPairingIndicationResponseToLegacy(
+        const NanRespondToPairingIndicationRequest& aidl_response,
+        legacy_hal::NanPairingIndicationResponse* legacy_response);
+bool convertAidlNanBootstrappingInitiatorRequestToLegacy(
+        const NanBootstrappingRequest& aidl_request,
+        legacy_hal::NanBootstrappingRequest* legacy_request);
+bool convertAidlNanBootstrappingIndicationResponseToLegacy(
+        const NanBootstrappingResponse& aidl_response,
+        legacy_hal::NanBootstrappingIndicationResponse* legacy_response);
+bool convertLegacyNanPairingRequestIndToAidl(const legacy_hal::NanPairingRequestInd& legacy_ind,
+                                             NanPairingRequestInd* aidl_ind);
+bool convertLegacyNanPairingConfirmIndToAidl(const legacy_hal::NanPairingConfirmInd& legacy_ind,
+                                             NanPairingConfirmInd* aidl_ind);
+bool convertLegacyNanBootstrappingRequestIndToAidl(
+        const legacy_hal::NanBootstrappingRequestInd& legacy_ind,
+        NanBootstrappingRequestInd* aidl_ind);
+bool convertLegacyNanBootstrappingConfirmIndToAidl(
+        const legacy_hal::NanBootstrappingConfirmInd& legacy_ind,
+        NanBootstrappingConfirmInd* aidl_ind);
 }  // namespace aidl_struct_util
 }  // namespace wifi
 }  // namespace hardware
diff --git a/wifi/aidl/default/tests/aidl_struct_util_unit_tests.cpp b/wifi/aidl/default/tests/aidl_struct_util_unit_tests.cpp
index df788b8..9b9d96d 100644
--- a/wifi/aidl/default/tests/aidl_struct_util_unit_tests.cpp
+++ b/wifi/aidl/default/tests/aidl_struct_util_unit_tests.cpp
@@ -29,6 +29,12 @@
 constexpr uint32_t kIfaceChannel2 = 5;
 constexpr char kIfaceName1[] = "wlan0";
 constexpr char kIfaceName2[] = "wlan1";
+constexpr uint8_t kMacAddress[] = {0x02, 0x12, 0x45, 0x56, 0xab, 0xcc};
+byte LCI[] = {0x27, 0x1A, 0x1,  0x00, 0x8,  0x01, 0x00, 0x08, 0x00, 0x10, 0x52,
+              0x83, 0x4d, 0x12, 0xef, 0xd2, 0xb0, 0x8b, 0x9b, 0x4b, 0xf1, 0xcc,
+              0x2c, 0x00, 0x00, 0x41, 0x06, 0x03, 0x06, 0x00, 0x80};
+byte LCR[] = {0x27, 0xE,  0x1,  0x00, 0xB,  0x01, 0x00, 0x0b, 0x00, 0x09,
+              0x55, 0x53, 0x18, 0x05, 0x39, 0x34, 0x30, 0x34, 0x33};
 }  // namespace
 
 namespace aidl {
@@ -764,6 +770,100 @@
             radio_configurations_array3);
 }
 
+void verifyRttResult(wifi_rtt_result* legacy_rtt_result_ptr, RttResult* aidl_results_ptr) {
+    EXPECT_EQ((int)legacy_rtt_result_ptr->burst_num, aidl_results_ptr->burstNum);
+    EXPECT_EQ((int)legacy_rtt_result_ptr->measurement_number, aidl_results_ptr->measurementNumber);
+    EXPECT_EQ((int)legacy_rtt_result_ptr->success_number, aidl_results_ptr->successNumber);
+    EXPECT_EQ(legacy_rtt_result_ptr->number_per_burst_peer, aidl_results_ptr->numberPerBurstPeer);
+    EXPECT_EQ(legacy_rtt_result_ptr->retry_after_duration, aidl_results_ptr->retryAfterDuration);
+    EXPECT_EQ(legacy_rtt_result_ptr->rssi, aidl_results_ptr->rssi);
+    EXPECT_EQ(legacy_rtt_result_ptr->rssi_spread, aidl_results_ptr->rssiSpread);
+    EXPECT_EQ(legacy_rtt_result_ptr->rtt, aidl_results_ptr->rtt);
+    EXPECT_EQ(legacy_rtt_result_ptr->rtt_sd, aidl_results_ptr->rttSd);
+    EXPECT_EQ(legacy_rtt_result_ptr->rtt_spread, aidl_results_ptr->rttSpread);
+    EXPECT_EQ(legacy_rtt_result_ptr->distance_mm, aidl_results_ptr->distanceInMm);
+    EXPECT_EQ(legacy_rtt_result_ptr->distance_sd_mm, aidl_results_ptr->distanceSdInMm);
+    EXPECT_EQ(legacy_rtt_result_ptr->distance_spread_mm, aidl_results_ptr->distanceSpreadInMm);
+    EXPECT_EQ(legacy_rtt_result_ptr->ts, aidl_results_ptr->timeStampInUs);
+    EXPECT_EQ(legacy_rtt_result_ptr->burst_duration, aidl_results_ptr->burstDurationInMs);
+    EXPECT_EQ(legacy_rtt_result_ptr->negotiated_burst_num, aidl_results_ptr->negotiatedBurstNum);
+    EXPECT_EQ(legacy_rtt_result_ptr->LCI->id, aidl_results_ptr->lci.id);
+    for (int i = 0; i < legacy_rtt_result_ptr->LCI->len; i++) {
+        EXPECT_EQ(legacy_rtt_result_ptr->LCI->data[i], aidl_results_ptr->lci.data[i]);
+    }
+    EXPECT_EQ(legacy_rtt_result_ptr->LCR->id, aidl_results_ptr->lcr.id);
+    for (int i = 0; i < legacy_rtt_result_ptr->LCR->len; i++) {
+        EXPECT_EQ(legacy_rtt_result_ptr->LCR->data[i], aidl_results_ptr->lcr.data[i]);
+    }
+}
+
+void fillLegacyRttResult(wifi_rtt_result* rtt_result_ptr) {
+    std::copy(std::begin(kMacAddress), std::end(kMacAddress), std::begin(rtt_result_ptr->addr));
+    rtt_result_ptr->burst_num = rand();
+    rtt_result_ptr->measurement_number = rand();
+    rtt_result_ptr->success_number = rand();
+    rtt_result_ptr->number_per_burst_peer = 0xF & rand();
+    rtt_result_ptr->status = RTT_STATUS_SUCCESS;
+    rtt_result_ptr->retry_after_duration = 0xF & rand();
+    rtt_result_ptr->type = RTT_TYPE_2_SIDED;
+    rtt_result_ptr->rssi = rand();
+    rtt_result_ptr->rssi_spread = rand();
+    rtt_result_ptr->rtt = rand();
+    rtt_result_ptr->rtt_sd = rand();
+    rtt_result_ptr->rtt_spread = rand();
+    rtt_result_ptr->distance_mm = rand();
+    rtt_result_ptr->distance_sd_mm = rand();
+    rtt_result_ptr->distance_spread_mm = rand();
+    rtt_result_ptr->burst_duration = rand();
+    rtt_result_ptr->negotiated_burst_num = rand();
+    rtt_result_ptr->LCI = (wifi_information_element*)LCI;
+    rtt_result_ptr->LCR = (wifi_information_element*)LCR;
+}
+
+TEST_F(AidlStructUtilTest, convertLegacyVectorOfRttResultToAidl) {
+    std::vector<const wifi_rtt_result*> rtt_results_vec;
+    wifi_rtt_result rttResults[2];
+
+    // fill legacy rtt results
+    for (int i = 0; i < 2; i++) {
+        fillLegacyRttResult(&rttResults[i]);
+        rtt_results_vec.push_back(&rttResults[i]);
+    }
+
+    std::vector<RttResult> aidl_results;
+    aidl_struct_util::convertLegacyVectorOfRttResultToAidl(rtt_results_vec, &aidl_results);
+
+    EXPECT_EQ(rtt_results_vec.size(), aidl_results.size());
+    for (size_t i = 0; i < rtt_results_vec.size(); i++) {
+        verifyRttResult(&rttResults[i], &aidl_results[i]);
+        EXPECT_EQ(aidl_results[i].channelFreqMHz, 0);
+        EXPECT_EQ(aidl_results[i].packetBw, RttBw::BW_UNSPECIFIED);
+    }
+}
+
+TEST_F(AidlStructUtilTest, convertLegacyVectorOfRttResultV2ToAidl) {
+    std::vector<const wifi_rtt_result_v2*> rtt_results_vec_v2;
+    wifi_rtt_result_v2 rttResults_v2[2];
+
+    // fill legacy rtt results v2
+    for (int i = 0; i < 2; i++) {
+        fillLegacyRttResult(&rttResults_v2[i].rtt_result);
+        rttResults_v2[i].frequency = 2412 + i * 5;
+        rttResults_v2[i].packet_bw = WIFI_RTT_BW_80;
+        rtt_results_vec_v2.push_back(&rttResults_v2[i]);
+    }
+
+    std::vector<RttResult> aidl_results;
+    aidl_struct_util::convertLegacyVectorOfRttResultV2ToAidl(rtt_results_vec_v2, &aidl_results);
+
+    EXPECT_EQ(rtt_results_vec_v2.size(), aidl_results.size());
+    for (size_t i = 0; i < rtt_results_vec_v2.size(); i++) {
+        verifyRttResult(&rttResults_v2[i].rtt_result, &aidl_results[i]);
+        EXPECT_EQ(aidl_results[i].channelFreqMHz, rttResults_v2[i].frequency);
+        EXPECT_EQ(aidl_results[i].packetBw, RttBw::BW_80MHZ);
+    }
+}
+
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/aidl/default/tests/wifi_nan_iface_unit_tests.cpp b/wifi/aidl/default/tests/wifi_nan_iface_unit_tests.cpp
index d40801f..f81cab3 100644
--- a/wifi/aidl/default/tests/wifi_nan_iface_unit_tests.cpp
+++ b/wifi/aidl/default/tests/wifi_nan_iface_unit_tests.cpp
@@ -122,6 +122,18 @@
     MOCK_METHOD1(eventDataPathTerminated, ndk::ScopedAStatus(int32_t));
     MOCK_METHOD1(eventDataPathScheduleUpdate,
                  ndk::ScopedAStatus(const NanDataPathScheduleUpdateInd&));
+    MOCK_METHOD1(eventPairingConfirm, ndk::ScopedAStatus(const NanPairingConfirmInd&));
+    MOCK_METHOD1(eventPairingRequest, ndk::ScopedAStatus(const NanPairingRequestInd&));
+    MOCK_METHOD1(eventBootstrappingConfirm, ndk::ScopedAStatus(const NanBootstrappingConfirmInd&));
+    MOCK_METHOD1(eventBootstrappingRequest, ndk::ScopedAStatus(const NanBootstrappingRequestInd&));
+    MOCK_METHOD3(notifyInitiatePairingResponse,
+                 ndk::ScopedAStatus(char16_t, const NanStatus&, int32_t));
+    MOCK_METHOD2(notifyRespondToPairingIndicationResponse,
+                 ndk::ScopedAStatus(char16_t, const NanStatus&));
+    MOCK_METHOD3(notifyInitiateBootstrappingResponse,
+                 ndk::ScopedAStatus(char16_t, const NanStatus&, int32_t));
+    MOCK_METHOD2(notifyRespondToBootstrappingIndicationResponse,
+                 ndk::ScopedAStatus(char16_t, const NanStatus&));
 };
 
 class WifiNanIfaceTest : public Test {
diff --git a/wifi/aidl/default/wifi_legacy_hal.cpp b/wifi/aidl/default/wifi_legacy_hal.cpp
index 83f368e..54e91d4 100644
--- a/wifi/aidl/default/wifi_legacy_hal.cpp
+++ b/wifi/aidl/default/wifi_legacy_hal.cpp
@@ -181,11 +181,28 @@
 // Callback to be invoked for rtt results results.
 std::function<void(wifi_request_id, unsigned num_results, wifi_rtt_result* rtt_results[])>
         on_rtt_results_internal_callback;
+std::function<void(wifi_request_id, unsigned num_results, wifi_rtt_result_v2* rtt_results_v2[])>
+        on_rtt_results_internal_callback_v2;
+
+void invalidateRttResultsCallbacks() {
+    on_rtt_results_internal_callback = nullptr;
+    on_rtt_results_internal_callback_v2 = nullptr;
+};
+
 void onAsyncRttResults(wifi_request_id id, unsigned num_results, wifi_rtt_result* rtt_results[]) {
     const auto lock = aidl_sync_util::acquireGlobalLock();
     if (on_rtt_results_internal_callback) {
         on_rtt_results_internal_callback(id, num_results, rtt_results);
-        on_rtt_results_internal_callback = nullptr;
+        invalidateRttResultsCallbacks();
+    }
+}
+
+void onAsyncRttResultsV2(wifi_request_id id, unsigned num_results,
+                         wifi_rtt_result_v2* rtt_results_v2[]) {
+    const auto lock = aidl_sync_util::acquireGlobalLock();
+    if (on_rtt_results_internal_callback_v2) {
+        on_rtt_results_internal_callback_v2(id, num_results, rtt_results_v2);
+        invalidateRttResultsCallbacks();
     }
 }
 
@@ -334,6 +351,40 @@
     }
 }
 
+std::function<void(const NanPairingRequestInd&)> on_nan_event_pairing_request_user_callback;
+void onAsyncNanEventPairingRequest(NanPairingRequestInd* event) {
+    const auto lock = aidl_sync_util::acquireGlobalLock();
+    if (on_nan_event_pairing_request_user_callback && event) {
+        on_nan_event_pairing_request_user_callback(*event);
+    }
+}
+
+std::function<void(const NanPairingConfirmInd&)> on_nan_event_pairing_confirm_user_callback;
+void onAsyncNanEventPairingConfirm(NanPairingConfirmInd* event) {
+    const auto lock = aidl_sync_util::acquireGlobalLock();
+    if (on_nan_event_pairing_confirm_user_callback && event) {
+        on_nan_event_pairing_confirm_user_callback(*event);
+    }
+}
+
+std::function<void(const NanBootstrappingRequestInd&)>
+        on_nan_event_bootstrapping_request_user_callback;
+void onAsyncNanEventBootstrappingRequest(NanBootstrappingRequestInd* event) {
+    const auto lock = aidl_sync_util::acquireGlobalLock();
+    if (on_nan_event_bootstrapping_request_user_callback && event) {
+        on_nan_event_bootstrapping_request_user_callback(*event);
+    }
+}
+
+std::function<void(const NanBootstrappingConfirmInd&)>
+        on_nan_event_bootstrapping_confirm_user_callback;
+void onAsyncNanEventBootstrappingConfirm(NanBootstrappingConfirmInd* event) {
+    const auto lock = aidl_sync_util::acquireGlobalLock();
+    if (on_nan_event_bootstrapping_confirm_user_callback && event) {
+        on_nan_event_bootstrapping_confirm_user_callback(*event);
+    }
+}
+
 // Callbacks for the various TWT operations.
 std::function<void(const TwtSetupResponse&)> on_twt_event_setup_response_callback;
 void onAsyncTwtEventSetupResponse(TwtSetupResponse* event) {
@@ -1194,8 +1245,9 @@
 wifi_error WifiLegacyHal::startRttRangeRequest(
         const std::string& iface_name, wifi_request_id id,
         const std::vector<wifi_rtt_config>& rtt_configs,
-        const on_rtt_results_callback& on_results_user_callback) {
-    if (on_rtt_results_internal_callback) {
+        const on_rtt_results_callback& on_results_user_callback,
+        const on_rtt_results_callback_v2& on_results_user_callback_v2) {
+    if (on_rtt_results_internal_callback || on_rtt_results_internal_callback_v2) {
         return WIFI_ERROR_NOT_AVAILABLE;
     }
 
@@ -1212,12 +1264,26 @@
         on_results_user_callback(id, rtt_results_vec);
     };
 
+    on_rtt_results_internal_callback_v2 = [on_results_user_callback_v2](
+                                                  wifi_request_id id, unsigned num_results,
+                                                  wifi_rtt_result_v2* rtt_results_v2[]) {
+        if (num_results > 0 && !rtt_results_v2) {
+            LOG(ERROR) << "Unexpected nullptr in RTT results";
+            return;
+        }
+        std::vector<const wifi_rtt_result_v2*> rtt_results_vec_v2;
+        std::copy_if(rtt_results_v2, rtt_results_v2 + num_results,
+                     back_inserter(rtt_results_vec_v2),
+                     [](wifi_rtt_result_v2* rtt_result_v2) { return rtt_result_v2 != nullptr; });
+        on_results_user_callback_v2(id, rtt_results_vec_v2);
+    };
+
     std::vector<wifi_rtt_config> rtt_configs_internal(rtt_configs);
     wifi_error status = global_func_table_.wifi_rtt_range_request(
             id, getIfaceHandle(iface_name), rtt_configs.size(), rtt_configs_internal.data(),
-            {onAsyncRttResults});
+            {onAsyncRttResults, onAsyncRttResultsV2});
     if (status != WIFI_SUCCESS) {
-        on_rtt_results_internal_callback = nullptr;
+        invalidateRttResultsCallbacks();
     }
     return status;
 }
@@ -1225,7 +1291,7 @@
 wifi_error WifiLegacyHal::cancelRttRangeRequest(
         const std::string& iface_name, wifi_request_id id,
         const std::vector<std::array<uint8_t, ETH_ALEN>>& mac_addrs) {
-    if (!on_rtt_results_internal_callback) {
+    if (!on_rtt_results_internal_callback && !on_rtt_results_internal_callback_v2) {
         return WIFI_ERROR_NOT_AVAILABLE;
     }
     static_assert(sizeof(mac_addr) == sizeof(std::array<uint8_t, ETH_ALEN>),
@@ -1239,7 +1305,7 @@
     // If the request Id is wrong, don't stop the ongoing range request. Any
     // other error should be treated as the end of rtt ranging.
     if (status != WIFI_ERROR_INVALID_REQUEST_ID) {
-        on_rtt_results_internal_callback = nullptr;
+        invalidateRttResultsCallbacks();
     }
     return status;
 }
@@ -1298,6 +1364,12 @@
     on_nan_event_tca_user_callback = user_callbacks.on_event_tca;
     on_nan_event_beacon_sdf_payload_user_callback = user_callbacks.on_event_beacon_sdf_payload;
     on_nan_event_data_path_request_user_callback = user_callbacks.on_event_data_path_request;
+    on_nan_event_pairing_request_user_callback = user_callbacks.on_event_pairing_request;
+    on_nan_event_pairing_confirm_user_callback = user_callbacks.on_event_pairing_confirm;
+    on_nan_event_bootstrapping_request_user_callback =
+            user_callbacks.on_event_bootstrapping_request;
+    on_nan_event_bootstrapping_confirm_user_callback =
+            user_callbacks.on_event_bootstrapping_confirm;
     on_nan_event_data_path_confirm_user_callback = user_callbacks.on_event_data_path_confirm;
     on_nan_event_data_path_end_user_callback = user_callbacks.on_event_data_path_end;
     on_nan_event_transmit_follow_up_user_callback = user_callbacks.on_event_transmit_follow_up;
@@ -1305,16 +1377,29 @@
     on_nan_event_range_report_user_callback = user_callbacks.on_event_range_report;
     on_nan_event_schedule_update_user_callback = user_callbacks.on_event_schedule_update;
 
-    return global_func_table_.wifi_nan_register_handler(
-            getIfaceHandle(iface_name),
-            {onAsyncNanNotifyResponse, onAsyncNanEventPublishReplied,
-             onAsyncNanEventPublishTerminated, onAsyncNanEventMatch, onAsyncNanEventMatchExpired,
-             onAsyncNanEventSubscribeTerminated, onAsyncNanEventFollowup,
-             onAsyncNanEventDiscEngEvent, onAsyncNanEventDisabled, onAsyncNanEventTca,
-             onAsyncNanEventBeaconSdfPayload, onAsyncNanEventDataPathRequest,
-             onAsyncNanEventDataPathConfirm, onAsyncNanEventDataPathEnd,
-             onAsyncNanEventTransmitFollowUp, onAsyncNanEventRangeRequest,
-             onAsyncNanEventRangeReport, onAsyncNanEventScheduleUpdate});
+    return global_func_table_.wifi_nan_register_handler(getIfaceHandle(iface_name),
+                                                        {onAsyncNanNotifyResponse,
+                                                         onAsyncNanEventPublishReplied,
+                                                         onAsyncNanEventPublishTerminated,
+                                                         onAsyncNanEventMatch,
+                                                         onAsyncNanEventMatchExpired,
+                                                         onAsyncNanEventSubscribeTerminated,
+                                                         onAsyncNanEventFollowup,
+                                                         onAsyncNanEventDiscEngEvent,
+                                                         onAsyncNanEventDisabled,
+                                                         onAsyncNanEventTca,
+                                                         onAsyncNanEventBeaconSdfPayload,
+                                                         onAsyncNanEventDataPathRequest,
+                                                         onAsyncNanEventDataPathConfirm,
+                                                         onAsyncNanEventDataPathEnd,
+                                                         onAsyncNanEventTransmitFollowUp,
+                                                         onAsyncNanEventRangeRequest,
+                                                         onAsyncNanEventRangeReport,
+                                                         onAsyncNanEventScheduleUpdate,
+                                                         onAsyncNanEventPairingRequest,
+                                                         onAsyncNanEventPairingConfirm,
+                                                         onAsyncNanEventBootstrappingRequest,
+                                                         onAsyncNanEventBootstrappingConfirm});
 }
 
 wifi_error WifiLegacyHal::nanEnableRequest(const std::string& iface_name, transaction_id id,
@@ -1429,6 +1514,36 @@
                                                                 &msg_internal);
 }
 
+wifi_error WifiLegacyHal::nanPairingRequest(const std::string& iface_name, transaction_id id,
+                                            const NanPairingRequest& msg) {
+    NanPairingRequest msg_internal(msg);
+    return global_func_table_.wifi_nan_pairing_request(id, getIfaceHandle(iface_name),
+                                                       &msg_internal);
+}
+
+wifi_error WifiLegacyHal::nanPairingIndicationResponse(const std::string& iface_name,
+                                                       transaction_id id,
+                                                       const NanPairingIndicationResponse& msg) {
+    NanPairingIndicationResponse msg_internal(msg);
+    return global_func_table_.wifi_nan_pairing_indication_response(id, getIfaceHandle(iface_name),
+                                                                   &msg_internal);
+}
+
+wifi_error WifiLegacyHal::nanBootstrappingRequest(const std::string& iface_name, transaction_id id,
+                                                  const NanBootstrappingRequest& msg) {
+    NanBootstrappingRequest msg_internal(msg);
+    return global_func_table_.wifi_nan_bootstrapping_request(id, getIfaceHandle(iface_name),
+                                                             &msg_internal);
+}
+
+wifi_error WifiLegacyHal::nanBootstrappingIndicationResponse(
+        const std::string& iface_name, transaction_id id,
+        const NanBootstrappingIndicationResponse& msg) {
+    NanBootstrappingIndicationResponse msg_internal(msg);
+    return global_func_table_.wifi_nan_bootstrapping_indication_response(
+            id, getIfaceHandle(iface_name), &msg_internal);
+}
+
 typedef struct {
     u8 num_ndp_instances;
     NanDataPathId ndp_instance_id;
@@ -1734,7 +1849,7 @@
     on_error_alert_internal_callback = nullptr;
     on_radio_mode_change_internal_callback = nullptr;
     on_subsystem_restart_internal_callback = nullptr;
-    on_rtt_results_internal_callback = nullptr;
+    invalidateRttResultsCallbacks();
     on_nan_notify_response_user_callback = nullptr;
     on_nan_event_publish_terminated_user_callback = nullptr;
     on_nan_event_match_user_callback = nullptr;
@@ -1746,6 +1861,10 @@
     on_nan_event_tca_user_callback = nullptr;
     on_nan_event_beacon_sdf_payload_user_callback = nullptr;
     on_nan_event_data_path_request_user_callback = nullptr;
+    on_nan_event_pairing_request_user_callback = nullptr;
+    on_nan_event_pairing_confirm_user_callback = nullptr;
+    on_nan_event_bootstrapping_request_user_callback = nullptr;
+    on_nan_event_bootstrapping_confirm_user_callback = nullptr;
     on_nan_event_data_path_confirm_user_callback = nullptr;
     on_nan_event_data_path_end_user_callback = nullptr;
     on_nan_event_transmit_follow_up_user_callback = nullptr;
diff --git a/wifi/aidl/default/wifi_legacy_hal.h b/wifi/aidl/default/wifi_legacy_hal.h
index c40118e..5620280 100644
--- a/wifi/aidl/default/wifi_legacy_hal.h
+++ b/wifi/aidl/default/wifi_legacy_hal.h
@@ -36,6 +36,7 @@
 namespace legacy_hal {
 // Import all the types defined inside the legacy HAL header files into this
 // namespace.
+using ::Akm;
 using ::chre_nan_rtt_state;
 using ::frame_info;
 using ::frame_type;
@@ -44,6 +45,8 @@
 using ::FRAME_TYPE_UNKNOWN;
 using ::fw_roaming_state_t;
 using ::mac_addr;
+using ::NAN_BOOTSTRAPPING_INITIATOR_RESPONSE;
+using ::NAN_BOOTSTRAPPING_RESPONDER_RESPONSE;
 using ::NAN_CHANNEL_24G_BAND;
 using ::NAN_CHANNEL_5G_BAND_HIGH;
 using ::NAN_CHANNEL_5G_BAND_LOW;
@@ -65,6 +68,10 @@
 using ::NAN_MATCH_ALG_MATCH_CONTINUOUS;
 using ::NAN_MATCH_ALG_MATCH_NEVER;
 using ::NAN_MATCH_ALG_MATCH_ONCE;
+using ::NAN_PAIRING_INITIATOR_RESPONSE;
+using ::NAN_PAIRING_RESPONDER_RESPONSE;
+using ::NAN_PAIRING_SETUP;
+using ::NAN_PAIRING_VERIFICATION;
 using ::NAN_PUBLISH_TYPE_SOLICITED;
 using ::NAN_PUBLISH_TYPE_UNSOLICITED;
 using ::NAN_PUBLISH_TYPE_UNSOLICITED_SOLICITED;
@@ -97,7 +104,9 @@
 using ::NAN_STATUS_ALREADY_ENABLED;
 using ::NAN_STATUS_FOLLOWUP_QUEUE_FULL;
 using ::NAN_STATUS_INTERNAL_FAILURE;
+using ::NAN_STATUS_INVALID_BOOTSTRAPPING_ID;
 using ::NAN_STATUS_INVALID_NDP_ID;
+using ::NAN_STATUS_INVALID_PAIRING_ID;
 using ::NAN_STATUS_INVALID_PARAM;
 using ::NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID;
 using ::NAN_STATUS_INVALID_REQUESTOR_INSTANCE_ID;
@@ -117,6 +126,12 @@
 using ::NAN_TX_TYPE_UNICAST;
 using ::NAN_USE_SRF;
 using ::NanBeaconSdfPayloadInd;
+using ::NanBootstrappingConfirmInd;
+using ::NanBootstrappingIndicationResponse;
+using ::NanBootstrappingRequest;
+using ::NanBootstrappingRequestInd;
+using ::NanBootstrappingRequestResponse;
+using ::NanBootstrappingResponseCode;
 using ::NanCapabilities;
 using ::NanChannelInfo;
 using ::NanConfigRequest;
@@ -131,9 +146,18 @@
 using ::NanDiscEngEventInd;
 using ::NanEnableRequest;
 using ::NanFollowupInd;
+using ::NanIdentityResolutionAttribute;
 using ::NanMatchAlg;
 using ::NanMatchExpiredInd;
 using ::NanMatchInd;
+using ::NanPairingConfig;
+using ::NanPairingConfirmInd;
+using ::NanPairingIndicationResponse;
+using ::NanPairingRequest;
+using ::NanPairingRequestInd;
+using ::NanPairingRequestResponse;
+using ::NanPairingRequestType;
+using ::NanPairingResponseCode;
 using ::NanPublishCancelRequest;
 using ::NanPublishRequest;
 using ::NanPublishTerminatedInd;
@@ -150,6 +174,8 @@
 using ::NanTransmitFollowupInd;
 using ::NanTransmitFollowupRequest;
 using ::NanTxType;
+using ::NpkSecurityAssociation;
+using ::PASN;
 using ::ROAMING_DISABLE;
 using ::ROAMING_ENABLE;
 using ::RTT_PEER_AP;
@@ -189,6 +215,7 @@
 using ::RX_PKT_FATE_FW_DROP_OTHER;
 using ::RX_PKT_FATE_FW_QUEUED;
 using ::RX_PKT_FATE_SUCCESS;
+using ::SAE;
 using ::ssid_t;
 using ::transaction_id;
 using ::TX_PKT_FATE_ACKED;
@@ -305,6 +332,7 @@
 using ::WIFI_RTT_BW_40;
 using ::WIFI_RTT_BW_5;
 using ::WIFI_RTT_BW_80;
+using ::WIFI_RTT_BW_UNSPECIFIED;
 using ::wifi_rtt_capabilities;
 using ::wifi_rtt_config;
 using ::wifi_rtt_preamble;
@@ -315,6 +343,7 @@
 using ::WIFI_RTT_PREAMBLE_VHT;
 using ::wifi_rtt_responder;
 using ::wifi_rtt_result;
+using ::wifi_rtt_result_v2;
 using ::wifi_rtt_status;
 using ::wifi_rtt_type;
 using ::wifi_rx_packet_fate;
@@ -412,6 +441,10 @@
     std::function<void(const NanRangeRequestInd&)> on_event_range_request;
     std::function<void(const NanRangeReportInd&)> on_event_range_report;
     std::function<void(const NanDataPathScheduleUpdateInd&)> on_event_schedule_update;
+    std::function<void(const NanPairingRequestInd&)> on_event_pairing_request;
+    std::function<void(const NanPairingConfirmInd&)> on_event_pairing_confirm;
+    std::function<void(const NanBootstrappingRequestInd&)> on_event_bootstrapping_request;
+    std::function<void(const NanBootstrappingConfirmInd&)> on_event_bootstrapping_confirm;
 };
 
 // Full scan results contain IE info and are hence passed by reference, to
@@ -434,6 +467,8 @@
 // the pointer.
 using on_rtt_results_callback =
         std::function<void(wifi_request_id, const std::vector<const wifi_rtt_result*>&)>;
+using on_rtt_results_callback_v2 =
+        std::function<void(wifi_request_id, const std::vector<const wifi_rtt_result_v2*>&)>;
 
 // Callback for ring buffer data.
 using on_ring_buffer_data_callback = std::function<void(
@@ -606,7 +641,8 @@
     // RTT functions.
     wifi_error startRttRangeRequest(const std::string& iface_name, wifi_request_id id,
                                     const std::vector<wifi_rtt_config>& rtt_configs,
-                                    const on_rtt_results_callback& on_results_callback);
+                                    const on_rtt_results_callback& on_results_callback,
+                                    const on_rtt_results_callback_v2& on_results_callback_v2);
     wifi_error cancelRttRangeRequest(const std::string& iface_name, wifi_request_id id,
                                      const std::vector<std::array<uint8_t, ETH_ALEN>>& mac_addrs);
     std::pair<wifi_error, wifi_rtt_capabilities> getRttCapabilities(const std::string& iface_name);
@@ -653,6 +689,14 @@
                                        const NanDataPathInitiatorRequest& msg);
     wifi_error nanDataIndicationResponse(const std::string& iface_name, transaction_id id,
                                          const NanDataPathIndicationResponse& msg);
+    wifi_error nanPairingRequest(const std::string& iface_name, transaction_id id,
+                                 const NanPairingRequest& msg);
+    wifi_error nanPairingIndicationResponse(const std::string& iface_name, transaction_id id,
+                                            const NanPairingIndicationResponse& msg);
+    wifi_error nanBootstrappingRequest(const std::string& iface_name, transaction_id id,
+                                       const NanBootstrappingRequest& msg);
+    wifi_error nanBootstrappingIndicationResponse(const std::string& iface_name, transaction_id id,
+                                                  const NanBootstrappingIndicationResponse& msg);
     wifi_error nanDataEnd(const std::string& iface_name, transaction_id id, uint32_t ndpInstanceId);
     // AP functions.
     wifi_error setCountryCode(const std::string& iface_name, const std::array<uint8_t, 2> code);
diff --git a/wifi/aidl/default/wifi_legacy_hal_stubs.cpp b/wifi/aidl/default/wifi_legacy_hal_stubs.cpp
index 7777894..a0cb2c0 100644
--- a/wifi/aidl/default/wifi_legacy_hal_stubs.cpp
+++ b/wifi/aidl/default/wifi_legacy_hal_stubs.cpp
@@ -126,6 +126,10 @@
     populateStubFor(&hal_fn->wifi_nan_data_interface_delete);
     populateStubFor(&hal_fn->wifi_nan_data_request_initiator);
     populateStubFor(&hal_fn->wifi_nan_data_indication_response);
+    populateStubFor(&hal_fn->wifi_nan_pairing_request);
+    populateStubFor(&hal_fn->wifi_nan_pairing_indication_response);
+    populateStubFor(&hal_fn->wifi_nan_bootstrapping_request);
+    populateStubFor(&hal_fn->wifi_nan_bootstrapping_indication_response);
     populateStubFor(&hal_fn->wifi_nan_data_end);
     populateStubFor(&hal_fn->wifi_get_packet_filter_capabilities);
     populateStubFor(&hal_fn->wifi_set_packet_filter);
diff --git a/wifi/aidl/default/wifi_nan_iface.cpp b/wifi/aidl/default/wifi_nan_iface.cpp
index 9edef09..ce6902d 100644
--- a/wifi/aidl/default/wifi_nan_iface.cpp
+++ b/wifi/aidl/default/wifi_nan_iface.cpp
@@ -205,6 +205,46 @@
                 }
                 break;
             }
+            case legacy_hal::NAN_PAIRING_INITIATOR_RESPONSE: {
+                for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+                    if (!callback->notifyInitiatePairingResponse(
+                                         id, nanStatus,
+                                         msg.body.pairing_request_response.paring_instance_id)
+                                 .isOk()) {
+                        LOG(ERROR) << "Failed to invoke the callback";
+                    }
+                }
+                break;
+            }
+            case legacy_hal::NAN_PAIRING_RESPONDER_RESPONSE: {
+                for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+                    if (!callback->notifyRespondToPairingIndicationResponse(id, nanStatus).isOk()) {
+                        LOG(ERROR) << "Failed to invoke the callback";
+                    }
+                }
+                break;
+            }
+            case legacy_hal::NAN_BOOTSTRAPPING_INITIATOR_RESPONSE: {
+                for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+                    if (!callback->notifyInitiateBootstrappingResponse(
+                                         id, nanStatus,
+                                         msg.body.bootstrapping_request_response
+                                                 .bootstrapping_instance_id)
+                                 .isOk()) {
+                        LOG(ERROR) << "Failed to invoke the callback";
+                    }
+                }
+                break;
+            }
+            case legacy_hal::NAN_BOOTSTRAPPING_RESPONDER_RESPONSE: {
+                for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+                    if (!callback->notifyRespondToBootstrappingIndicationResponse(id, nanStatus)
+                                 .isOk()) {
+                        LOG(ERROR) << "Failed to invoke the callback";
+                    }
+                }
+                break;
+            }
             case legacy_hal::NAN_RESPONSE_BEACON_SDF_PAYLOAD:
             /* fall through */
             case legacy_hal::NAN_RESPONSE_TCA:
@@ -421,6 +461,85 @@
                 }
             };
 
+    callback_handlers.on_event_pairing_request =
+            [weak_ptr_this](const legacy_hal::NanPairingRequestInd& msg) {
+                const auto shared_ptr_this = weak_ptr_this.lock();
+                if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+                    LOG(ERROR) << "Callback invoked on an invalid object";
+                    return;
+                }
+                NanPairingRequestInd aidl_struct;
+                if (!aidl_struct_util::convertLegacyNanPairingRequestIndToAidl(msg, &aidl_struct)) {
+                    LOG(ERROR) << "Failed to convert nan capabilities response";
+                    return;
+                }
+
+                for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+                    if (!callback->eventPairingRequest(aidl_struct).isOk()) {
+                        LOG(ERROR) << "Failed to invoke the callback";
+                    }
+                }
+            };
+    callback_handlers.on_event_pairing_confirm =
+            [weak_ptr_this](const legacy_hal::NanPairingConfirmInd& msg) {
+                const auto shared_ptr_this = weak_ptr_this.lock();
+                if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+                    LOG(ERROR) << "Callback invoked on an invalid object";
+                    return;
+                }
+                NanPairingConfirmInd aidl_struct;
+                if (!aidl_struct_util::convertLegacyNanPairingConfirmIndToAidl(msg, &aidl_struct)) {
+                    LOG(ERROR) << "Failed to convert nan capabilities response";
+                    return;
+                }
+
+                for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+                    if (!callback->eventPairingConfirm(aidl_struct).isOk()) {
+                        LOG(ERROR) << "Failed to invoke the callback";
+                    }
+                }
+            };
+    callback_handlers.on_event_bootstrapping_request =
+            [weak_ptr_this](const legacy_hal::NanBootstrappingRequestInd& msg) {
+                const auto shared_ptr_this = weak_ptr_this.lock();
+                if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+                    LOG(ERROR) << "Callback invoked on an invalid object";
+                    return;
+                }
+                NanBootstrappingRequestInd aidl_struct;
+                if (!aidl_struct_util::convertLegacyNanBootstrappingRequestIndToAidl(
+                            msg, &aidl_struct)) {
+                    LOG(ERROR) << "Failed to convert nan capabilities response";
+                    return;
+                }
+
+                for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+                    if (!callback->eventBootstrappingRequest(aidl_struct).isOk()) {
+                        LOG(ERROR) << "Failed to invoke the callback";
+                    }
+                }
+            };
+    callback_handlers.on_event_bootstrapping_confirm =
+            [weak_ptr_this](const legacy_hal::NanBootstrappingConfirmInd& msg) {
+                const auto shared_ptr_this = weak_ptr_this.lock();
+                if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+                    LOG(ERROR) << "Callback invoked on an invalid object";
+                    return;
+                }
+                NanBootstrappingConfirmInd aidl_struct;
+                if (!aidl_struct_util::convertLegacyNanBootstrappingConfirmIndToAidl(
+                            msg, &aidl_struct)) {
+                    LOG(ERROR) << "Failed to convert nan capabilities response";
+                    return;
+                }
+
+                for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+                    if (!callback->eventBootstrappingConfirm(aidl_struct).isOk()) {
+                        LOG(ERROR) << "Failed to invoke the callback";
+                    }
+                }
+            };
+
     callback_handlers.on_event_beacon_sdf_payload =
             [](const legacy_hal::NanBeaconSdfPayloadInd& /* msg */) {
                 LOG(ERROR) << "on_event_beacon_sdf_payload - should not be called";
@@ -611,6 +730,32 @@
                            in_ndpInstanceId);
 }
 
+ndk::ScopedAStatus WifiNanIface::initiatePairingRequest(char16_t in_cmdId,
+                                                        const NanPairingRequest& in_msg) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiNanIface::initiatePairingRequestInternal, in_cmdId, in_msg);
+}
+
+ndk::ScopedAStatus WifiNanIface::respondToPairingIndicationRequest(
+        char16_t in_cmdId, const NanRespondToPairingIndicationRequest& in_msg) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiNanIface::respondToPairingIndicationRequestInternal, in_cmdId,
+                           in_msg);
+}
+
+ndk::ScopedAStatus WifiNanIface::initiateBootstrappingRequest(
+        char16_t in_cmdId, const NanBootstrappingRequest& in_msg) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiNanIface::initiateBootstrappingRequestInternal, in_cmdId, in_msg);
+}
+
+ndk::ScopedAStatus WifiNanIface::respondToBootstrappingIndicationRequest(
+        char16_t in_cmdId, const NanBootstrappingResponse& in_msg) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiNanIface::respondToBootstrappingIndicationRequestInternal, in_cmdId,
+                           in_msg);
+}
+
 std::pair<std::string, ndk::ScopedAStatus> WifiNanIface::getNameInternal() {
     return {ifname_, ndk::ScopedAStatus::ok()};
 }
@@ -744,6 +889,47 @@
             legacy_hal_.lock()->nanDataEnd(ifname_, cmd_id, ndpInstanceId);
     return createWifiStatusFromLegacyError(legacy_status);
 }
+ndk::ScopedAStatus WifiNanIface::initiatePairingRequestInternal(char16_t cmd_id,
+                                                                const NanPairingRequest& msg) {
+    legacy_hal::NanPairingRequest legacy_msg;
+    if (!aidl_struct_util::convertAidlNanPairingInitiatorRequestToLegacy(msg, &legacy_msg)) {
+        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+    }
+    legacy_hal::wifi_error legacy_status =
+            legacy_hal_.lock()->nanPairingRequest(ifname_, cmd_id, legacy_msg);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+ndk::ScopedAStatus WifiNanIface::respondToPairingIndicationRequestInternal(
+        char16_t cmd_id, const NanRespondToPairingIndicationRequest& msg) {
+    legacy_hal::NanPairingIndicationResponse legacy_msg;
+    if (!aidl_struct_util::convertAidlNanPairingIndicationResponseToLegacy(msg, &legacy_msg)) {
+        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+    }
+    legacy_hal::wifi_error legacy_status =
+            legacy_hal_.lock()->nanPairingIndicationResponse(ifname_, cmd_id, legacy_msg);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+ndk::ScopedAStatus WifiNanIface::initiateBootstrappingRequestInternal(
+        char16_t cmd_id, const NanBootstrappingRequest& msg) {
+    legacy_hal::NanBootstrappingRequest legacy_msg;
+    if (!aidl_struct_util::convertAidlNanBootstrappingInitiatorRequestToLegacy(msg, &legacy_msg)) {
+        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+    }
+    legacy_hal::wifi_error legacy_status =
+            legacy_hal_.lock()->nanBootstrappingRequest(ifname_, cmd_id, legacy_msg);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+ndk::ScopedAStatus WifiNanIface::respondToBootstrappingIndicationRequestInternal(
+        char16_t cmd_id, const NanBootstrappingResponse& msg) {
+    legacy_hal::NanBootstrappingIndicationResponse legacy_msg;
+    if (!aidl_struct_util::convertAidlNanBootstrappingIndicationResponseToLegacy(msg,
+                                                                                 &legacy_msg)) {
+        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+    }
+    legacy_hal::wifi_error legacy_status =
+            legacy_hal_.lock()->nanBootstrappingIndicationResponse(ifname_, cmd_id, legacy_msg);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
 
 }  // namespace wifi
 }  // namespace hardware
diff --git a/wifi/aidl/default/wifi_nan_iface.h b/wifi/aidl/default/wifi_nan_iface.h
index 1018905..591eca9 100644
--- a/wifi/aidl/default/wifi_nan_iface.h
+++ b/wifi/aidl/default/wifi_nan_iface.h
@@ -78,6 +78,14 @@
             char16_t in_cmdId, const NanRespondToDataPathIndicationRequest& in_msg) override;
     ndk::ScopedAStatus terminateDataPathRequest(char16_t in_cmdId,
                                                 int32_t in_ndpInstanceId) override;
+    ndk::ScopedAStatus initiatePairingRequest(char16_t in_cmdId,
+                                              const NanPairingRequest& in_msg) override;
+    ndk::ScopedAStatus respondToPairingIndicationRequest(
+            char16_t in_cmdId, const NanRespondToPairingIndicationRequest& in_msg) override;
+    ndk::ScopedAStatus initiateBootstrappingRequest(char16_t in_cmdId,
+                                                    const NanBootstrappingRequest& in_msg) override;
+    ndk::ScopedAStatus respondToBootstrappingIndicationRequest(
+            char16_t in_cmdId, const NanBootstrappingResponse& in_msg) override;
 
   protected:
     // Accessible to child class in the gTest suite.
@@ -111,6 +119,14 @@
     ndk::ScopedAStatus respondToDataPathIndicationRequestInternal(
             char16_t cmd_id, const NanRespondToDataPathIndicationRequest& msg);
     ndk::ScopedAStatus terminateDataPathRequestInternal(char16_t cmd_id, int32_t ndpInstanceId);
+    ndk::ScopedAStatus initiatePairingRequestInternal(char16_t cmd_id,
+                                                      const NanPairingRequest& msg);
+    ndk::ScopedAStatus respondToPairingIndicationRequestInternal(
+            char16_t cmd_id, const NanRespondToPairingIndicationRequest& msg);
+    ndk::ScopedAStatus initiateBootstrappingRequestInternal(char16_t cmd_id,
+                                                            const NanBootstrappingRequest& msg);
+    ndk::ScopedAStatus respondToBootstrappingIndicationRequestInternal(
+            char16_t cmd_id, const NanBootstrappingResponse& msg);
 
     // Overridden in the gTest suite.
     virtual std::set<std::shared_ptr<IWifiNanIfaceEventCallback>> getEventCallbacks();
diff --git a/wifi/aidl/default/wifi_rtt_controller.cpp b/wifi/aidl/default/wifi_rtt_controller.cpp
index 856c3cd..a5f6768 100644
--- a/wifi/aidl/default/wifi_rtt_controller.cpp
+++ b/wifi/aidl/default/wifi_rtt_controller.cpp
@@ -161,8 +161,28 @@
                     }
                 }
             };
+    const auto& on_results_callback_v2 =
+            [weak_ptr_this](legacy_hal::wifi_request_id id,
+                            const std::vector<const legacy_hal::wifi_rtt_result_v2*>& results) {
+                const auto shared_ptr_this = weak_ptr_this.lock();
+                if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+                    LOG(ERROR) << "v2 Callback invoked on an invalid object";
+                    return;
+                }
+                std::vector<RttResult> aidl_results;
+                if (!aidl_struct_util::convertLegacyVectorOfRttResultV2ToAidl(results,
+                                                                              &aidl_results)) {
+                    LOG(ERROR) << "Failed to convert rtt results v2 to AIDL structs";
+                    return;
+                }
+                for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+                    if (!callback->onResults(id, aidl_results).isOk()) {
+                        LOG(ERROR) << "Failed to invoke the v2 callback";
+                    }
+                }
+            };
     legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->startRttRangeRequest(
-            ifname_, cmd_id, legacy_configs, on_results_callback);
+            ifname_, cmd_id, legacy_configs, on_results_callback, on_results_callback_v2);
     return createWifiStatusFromLegacyError(legacy_status);
 }
 
diff --git a/wifi/aidl/vts/functional/wifi_nan_iface_aidl_test.cpp b/wifi/aidl/vts/functional/wifi_nan_iface_aidl_test.cpp
index 457d57a..654eb02 100644
--- a/wifi/aidl/vts/functional/wifi_nan_iface_aidl_test.cpp
+++ b/wifi/aidl/vts/functional/wifi_nan_iface_aidl_test.cpp
@@ -33,6 +33,8 @@
 using aidl::android::hardware::wifi::IWifiNanIface;
 using aidl::android::hardware::wifi::NanBandIndex;
 using aidl::android::hardware::wifi::NanBandSpecificConfig;
+using aidl::android::hardware::wifi::NanBootstrappingConfirmInd;
+using aidl::android::hardware::wifi::NanBootstrappingRequestInd;
 using aidl::android::hardware::wifi::NanCapabilities;
 using aidl::android::hardware::wifi::NanClusterEventInd;
 using aidl::android::hardware::wifi::NanConfigRequest;
@@ -46,6 +48,8 @@
 using aidl::android::hardware::wifi::NanInitiateDataPathRequest;
 using aidl::android::hardware::wifi::NanMatchAlg;
 using aidl::android::hardware::wifi::NanMatchInd;
+using aidl::android::hardware::wifi::NanPairingConfirmInd;
+using aidl::android::hardware::wifi::NanPairingRequestInd;
 using aidl::android::hardware::wifi::NanPublishRequest;
 using aidl::android::hardware::wifi::NanPublishType;
 using aidl::android::hardware::wifi::NanRespondToDataPathIndicationRequest;
@@ -96,6 +100,10 @@
         NOTIFY_INITIATE_DATA_PATH_RESPONSE,
         NOTIFY_RESPOND_TO_DATA_PATH_INDICATION_RESPONSE,
         NOTIFY_TERMINATE_DATA_PATH_RESPONSE,
+        NOTIFY_INITIATE_PAIRING_RESPONSE,
+        NOTIFY_RESPOND_TO_PAIRING_INDICATION_RESPONSE,
+        NOTIFY_INITIATE_BOOTSTRAPPING_RESPONSE,
+        NOTIFY_RESPOND_TO_BOOTSTRAPPING_INDICATION_RESPONSE,
 
         EVENT_CLUSTER_EVENT,
         EVENT_DISABLED,
@@ -109,6 +117,10 @@
         EVENT_DATA_PATH_CONFIRM,
         EVENT_DATA_PATH_TERMINATED,
         EVENT_DATA_PATH_SCHEDULE_UPDATE,
+        EVENT_PAIRING_REQUEST,
+        EVENT_PAIRING_CONFIRM,
+        EVENT_BOOTSTRAPPING_REQUEST,
+        EVENT_BOOTSTRAPPING_CONFIRM,
     };
 
     // Test code calls this function to wait for data/event callback.
@@ -214,6 +226,32 @@
             parent_.notify();
             return ndk::ScopedAStatus::ok();
         }
+        ::ndk::ScopedAStatus eventPairingConfirm(const NanPairingConfirmInd& event) override {
+            parent_.callback_type_ = EVENT_PAIRING_CONFIRM;
+            parent_.nan_pairing_confirm_ind_ = event;
+            parent_.notify();
+            return ndk::ScopedAStatus::ok();
+        }
+        ::ndk::ScopedAStatus eventPairingRequest(const NanPairingRequestInd& event) override {
+            parent_.callback_type_ = EVENT_PAIRING_REQUEST;
+            parent_.nan_pairing_request_ind_ = event;
+            parent_.notify();
+            return ndk::ScopedAStatus::ok();
+        }
+        ::ndk::ScopedAStatus eventBootstrappingConfirm(
+                const NanBootstrappingConfirmInd& event) override {
+            parent_.callback_type_ = EVENT_BOOTSTRAPPING_CONFIRM;
+            parent_.nan_bootstrapping_confirm_ind_ = event;
+            parent_.notify();
+            return ndk::ScopedAStatus::ok();
+        }
+        ::ndk::ScopedAStatus eventBootstrappingRequest(
+                const NanBootstrappingRequestInd& event) override {
+            parent_.callback_type_ = EVENT_BOOTSTRAPPING_REQUEST;
+            parent_.nan_bootstrapping_request_ind_ = event;
+            parent_.notify();
+            return ndk::ScopedAStatus::ok();
+        }
         ::ndk::ScopedAStatus notifyCapabilitiesResponse(
                 char16_t id, const NanStatus& status,
                 const NanCapabilities& capabilities) override {
@@ -328,6 +366,40 @@
             parent_.notify();
             return ndk::ScopedAStatus::ok();
         }
+        ::ndk::ScopedAStatus notifyInitiatePairingResponse(char16_t id, const NanStatus& status,
+                                                           int32_t pairingInstanceId) override {
+            parent_.callback_type_ = NOTIFY_INITIATE_PAIRING_RESPONSE;
+            parent_.id_ = id;
+            parent_.status_ = status;
+            parent_.pairing_instance_id_ = pairingInstanceId;
+            parent_.notify();
+            return ndk::ScopedAStatus::ok();
+        }
+        ::ndk::ScopedAStatus notifyRespondToPairingIndicationResponse(
+                char16_t id, const NanStatus& status) override {
+            parent_.callback_type_ = NOTIFY_RESPOND_TO_PAIRING_INDICATION_RESPONSE;
+            parent_.id_ = id;
+            parent_.status_ = status;
+            parent_.notify();
+            return ndk::ScopedAStatus::ok();
+        }
+        ::ndk::ScopedAStatus notifyInitiateBootstrappingResponse(
+                char16_t id, const NanStatus& status, int32_t bootstrapppingInstanceId) override {
+            parent_.callback_type_ = NOTIFY_INITIATE_BOOTSTRAPPING_RESPONSE;
+            parent_.id_ = id;
+            parent_.status_ = status;
+            parent_.bootstrappping_instance_id_ = bootstrapppingInstanceId;
+            parent_.notify();
+            return ndk::ScopedAStatus::ok();
+        }
+        ::ndk::ScopedAStatus notifyRespondToBootstrappingIndicationResponse(
+                char16_t id, const NanStatus& status) override {
+            parent_.callback_type_ = NOTIFY_RESPOND_TO_BOOTSTRAPPING_INDICATION_RESPONSE;
+            parent_.id_ = id;
+            parent_.status_ = status;
+            parent_.notify();
+            return ndk::ScopedAStatus::ok();
+        }
 
       private:
         WifiNanIfaceAidlTest& parent_;
@@ -339,6 +411,8 @@
     uint16_t id_;
     uint8_t session_id_;
     uint32_t ndp_instance_id_;
+    uint32_t pairing_instance_id_;
+    uint32_t bootstrappping_instance_id_;
     uint32_t peer_id_;
     NanCapabilities capabilities_;
     NanClusterEventInd nan_cluster_event_ind_;
@@ -348,6 +422,10 @@
     NanFollowupReceivedInd nan_followup_received_ind_;
     NanMatchInd nan_match_ind_;
     NanStatus status_;
+    NanPairingRequestInd nan_pairing_request_ind_;
+    NanPairingConfirmInd nan_pairing_confirm_ind_;
+    NanBootstrappingRequestInd nan_bootstrapping_request_ind_;
+    NanBootstrappingConfirmInd nan_bootstrapping_confirm_ind_;
 
     const char* getInstanceName() { return GetParam().c_str(); }