Merge "wifi: Correct document for SAP 11AX mode" into sc-dev
diff --git a/audio/effect/all-versions/default/OWNERS b/audio/common/7.0/enums/OWNERS
similarity index 67%
rename from audio/effect/all-versions/default/OWNERS
rename to audio/common/7.0/enums/OWNERS
index 6fdc97c..24071af 100644
--- a/audio/effect/all-versions/default/OWNERS
+++ b/audio/common/7.0/enums/OWNERS
@@ -1,3 +1,2 @@
 elaurent@google.com
-krocard@google.com
 mnaganov@google.com
diff --git a/audio/common/7.0/enums/include/android_audio_policy_configuration_V7_0-enums.h b/audio/common/7.0/enums/include/android_audio_policy_configuration_V7_0-enums.h
index fe8eee1..88dd12e 100644
--- a/audio/common/7.0/enums/include/android_audio_policy_configuration_V7_0-enums.h
+++ b/audio/common/7.0/enums/include/android_audio_policy_configuration_V7_0-enums.h
@@ -212,6 +212,15 @@
     return isOutputDevice(stringToAudioDevice(device));
 }
 
+static inline bool isTelephonyDevice(AudioDevice device) {
+    return device == AudioDevice::AUDIO_DEVICE_OUT_TELEPHONY_TX ||
+           device == AudioDevice::AUDIO_DEVICE_IN_TELEPHONY_RX;
+}
+
+static inline bool isTelephonyDevice(const std::string& device) {
+    return isTelephonyDevice(stringToAudioDevice(device));
+}
+
 static inline bool maybeVendorExtension(const std::string& s) {
     // Only checks whether the string starts with the "vendor prefix".
     static const std::string vendorPrefix = "VX_";
@@ -260,6 +269,24 @@
     return stringToAudioUsage(usage) == AudioUsage::UNKNOWN;
 }
 
+static inline bool isLinearPcm(AudioFormat format) {
+    switch (format) {
+        case AudioFormat::AUDIO_FORMAT_PCM_16_BIT:
+        case AudioFormat::AUDIO_FORMAT_PCM_8_BIT:
+        case AudioFormat::AUDIO_FORMAT_PCM_32_BIT:
+        case AudioFormat::AUDIO_FORMAT_PCM_8_24_BIT:
+        case AudioFormat::AUDIO_FORMAT_PCM_FLOAT:
+        case AudioFormat::AUDIO_FORMAT_PCM_24_BIT_PACKED:
+            return true;
+        default:
+            return false;
+    }
+}
+
+static inline bool isLinearPcm(const std::string& format) {
+    return isLinearPcm(stringToAudioFormat(format));
+}
+
 }  // namespace android::audio::policy::configuration::V7_0
 
 #endif  // ANDROID_AUDIO_POLICY_CONFIGURATION_V7_0__ENUMS_H
diff --git a/audio/effect/all-versions/default/OWNERS b/audio/common/7.0/example/OWNERS
similarity index 67%
copy from audio/effect/all-versions/default/OWNERS
copy to audio/common/7.0/example/OWNERS
index 6fdc97c..24071af 100644
--- a/audio/effect/all-versions/default/OWNERS
+++ b/audio/common/7.0/example/OWNERS
@@ -1,3 +1,2 @@
 elaurent@google.com
-krocard@google.com
 mnaganov@google.com
diff --git a/audio/common/all-versions/OWNERS b/audio/common/all-versions/OWNERS
index 6fdc97c..24071af 100644
--- a/audio/common/all-versions/OWNERS
+++ b/audio/common/all-versions/OWNERS
@@ -1,3 +1,2 @@
 elaurent@google.com
-krocard@google.com
 mnaganov@google.com
diff --git a/audio/common/all-versions/default/OWNERS b/audio/common/all-versions/default/OWNERS
index 6fdc97c..24071af 100644
--- a/audio/common/all-versions/default/OWNERS
+++ b/audio/common/all-versions/default/OWNERS
@@ -1,3 +1,2 @@
 elaurent@google.com
-krocard@google.com
 mnaganov@google.com
diff --git a/audio/common/all-versions/test/OWNERS b/audio/common/all-versions/test/OWNERS
deleted file mode 100644
index 6a26ae7..0000000
--- a/audio/common/all-versions/test/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-yim@google.com
-zhuoyao@google.com
diff --git a/audio/core/all-versions/default/OWNERS b/audio/core/all-versions/OWNERS
similarity index 100%
rename from audio/core/all-versions/default/OWNERS
rename to audio/core/all-versions/OWNERS
diff --git a/audio/core/all-versions/vts/OWNERS b/audio/core/all-versions/vts/OWNERS
deleted file mode 100644
index 0ea4666..0000000
--- a/audio/core/all-versions/vts/OWNERS
+++ /dev/null
@@ -1,5 +0,0 @@
-elaurent@google.com
-krocard@google.com
-mnaganov@google.com
-yim@google.com
-zhuoyao@google.com
diff --git a/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp b/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp
index f87e5ed..b96cc83 100644
--- a/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp
@@ -77,7 +77,6 @@
                   .tags = {},
                   .channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_IN_MONO)}}};
 #endif
-        EventFlag* efGroup;
         for (auto microphone : microphones) {
 #if MAJOR_VERSION <= 6
             if (microphone.deviceAddress.device != AudioDevice::IN_BUILTIN_MIC) {
@@ -96,44 +95,15 @@
                                                             config, flags, initMetadata, cb);
                     },
                     config, &res, &suggestedConfig));
+            StreamReader reader(stream.get(), stream->getBufferSize());
+            ASSERT_TRUE(reader.start());
+            reader.pause();  // This ensures that at least one read has happened.
+            EXPECT_FALSE(reader.hasError());
+
             hidl_vec<MicrophoneInfo> activeMicrophones;
-            Result readRes;
-            typedef MessageQueue<IStreamIn::ReadParameters, kSynchronizedReadWrite> CommandMQ;
-            typedef MessageQueue<uint8_t, kSynchronizedReadWrite> DataMQ;
-            std::unique_ptr<CommandMQ> commandMQ;
-            std::unique_ptr<DataMQ> dataMQ;
-            size_t frameSize = stream->getFrameSize();
-            size_t frameCount = stream->getBufferSize() / frameSize;
-            ASSERT_OK(stream->prepareForReading(
-                    frameSize, frameCount, [&](auto r, auto& c, auto& d, auto&, auto) {
-                        readRes = r;
-                        if (readRes == Result::OK) {
-                            commandMQ.reset(new CommandMQ(c));
-                            dataMQ.reset(new DataMQ(d));
-                            if (dataMQ->isValid() && dataMQ->getEventFlagWord()) {
-                                EventFlag::createEventFlag(dataMQ->getEventFlagWord(), &efGroup);
-                            }
-                        }
-                    }));
-            ASSERT_OK(readRes);
-            IStreamIn::ReadParameters params;
-            params.command = IStreamIn::ReadCommand::READ;
-            ASSERT_TRUE(commandMQ != nullptr);
-            ASSERT_TRUE(commandMQ->isValid());
-            ASSERT_TRUE(commandMQ->write(&params));
-            efGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL));
-            uint32_t efState = 0;
-            efGroup->wait(static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY), &efState);
-            if (efState & static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY)) {
-                ASSERT_OK(stream->getActiveMicrophones(returnIn(res, activeMicrophones)));
-                ASSERT_OK(res);
-                ASSERT_NE(0U, activeMicrophones.size());
-            }
-            helper.close(true /*clear*/, &res);
+            ASSERT_OK(stream->getActiveMicrophones(returnIn(res, activeMicrophones)));
             ASSERT_OK(res);
-            if (efGroup) {
-                EventFlag::deleteEventFlag(&efGroup);
-            }
+            EXPECT_NE(0U, activeMicrophones.size());
         }
     }
 }
diff --git a/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp b/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp
index c1923f1..657b42d 100644
--- a/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#include <android-base/chrono_utils.h>
+
 #include "Generators.h"
 
 // pull in all the <= 6.0 tests
@@ -487,3 +489,305 @@
                 << ::testing::PrintToString(metadata);
     }
 }
+
+static const std::vector<DeviceConfigParameter>& getOutputDevicePcmOnlyConfigParameters() {
+    static const std::vector<DeviceConfigParameter> parameters = [] {
+        auto allParams = getOutputDeviceConfigParameters();
+        std::vector<DeviceConfigParameter> pcmParams;
+        std::copy_if(allParams.begin(), allParams.end(), std::back_inserter(pcmParams), [](auto cfg) {
+            const auto& flags = std::get<PARAM_FLAGS>(cfg);
+            return xsd::isLinearPcm(std::get<PARAM_CONFIG>(cfg).base.format)
+                   // MMAP NOIRQ and HW A/V Sync profiles use special writing protocols.
+                   &&
+                   std::find_if(flags.begin(), flags.end(),
+                                [](const auto& flag) {
+                                    return flag == toString(xsd::AudioInOutFlag::
+                                                                    AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) ||
+                                           flag == toString(xsd::AudioInOutFlag::
+                                                                    AUDIO_OUTPUT_FLAG_HW_AV_SYNC);
+                                }) == flags.end() &&
+                   !getCachedPolicyConfig()
+                            .getAttachedSinkDeviceForMixPort(
+                                    std::get<PARAM_DEVICE_NAME>(std::get<PARAM_DEVICE>(cfg)),
+                                    std::get<PARAM_PORT_NAME>(cfg))
+                            .empty();
+        });
+        return pcmParams;
+    }();
+    return parameters;
+}
+
+class PcmOnlyConfigOutputStreamTest : public OutputStreamTest {
+  public:
+    void TearDown() override {
+        releasePatchIfNeeded();
+        OutputStreamTest::TearDown();
+    }
+
+    bool canQueryPresentationPosition() const {
+        auto maybeSinkAddress =
+                getCachedPolicyConfig().getSinkDeviceForMixPort(getDeviceName(), getMixPortName());
+        // Returning 'true' when no sink is found so the test can fail later with a more clear
+        // problem description.
+        return !maybeSinkAddress.has_value() ||
+               !xsd::isTelephonyDevice(maybeSinkAddress.value().deviceType);
+    }
+
+    void createPatchIfNeeded() {
+        auto maybeSinkAddress =
+                getCachedPolicyConfig().getSinkDeviceForMixPort(getDeviceName(), getMixPortName());
+        ASSERT_TRUE(maybeSinkAddress.has_value())
+                << "No sink device found for mix port " << getMixPortName() << " (module "
+                << getDeviceName() << ")";
+        if (areAudioPatchesSupported()) {
+            AudioPortConfig source;
+            source.base.format.value(getConfig().base.format);
+            source.base.sampleRateHz.value(getConfig().base.sampleRateHz);
+            source.base.channelMask.value(getConfig().base.channelMask);
+            source.ext.mix({});
+            source.ext.mix().ioHandle = helper.getIoHandle();
+            source.ext.mix().useCase.stream({});
+            AudioPortConfig sink;
+            sink.ext.device(maybeSinkAddress.value());
+            EXPECT_OK(getDevice()->createAudioPatch(hidl_vec<AudioPortConfig>{source},
+                                                    hidl_vec<AudioPortConfig>{sink},
+                                                    returnIn(res, mPatchHandle)));
+            mHasPatch = res == Result::OK;
+        } else {
+            EXPECT_OK(stream->setDevices({maybeSinkAddress.value()}));
+        }
+    }
+
+    void releasePatchIfNeeded() {
+        if (areAudioPatchesSupported()) {
+            if (mHasPatch) {
+                EXPECT_OK(getDevice()->releaseAudioPatch(mPatchHandle));
+                mHasPatch = false;
+            }
+        } else {
+            EXPECT_OK(stream->setDevices({address}));
+        }
+    }
+
+    const std::string& getMixPortName() const { return std::get<PARAM_PORT_NAME>(GetParam()); }
+
+    void waitForPresentationPositionAdvance(StreamWriter& writer, uint64_t* firstPosition = nullptr,
+                                            uint64_t* lastPosition = nullptr) {
+        static constexpr int kWriteDurationUs = 50 * 1000;
+        static constexpr std::chrono::milliseconds kPositionChangeTimeout{10000};
+        uint64_t framesInitial;
+        TimeSpec ts;
+        // Starting / resuming of streams is asynchronous at HAL level.
+        // Sometimes HAL doesn't have enough information until the audio data actually gets
+        // consumed by the hardware.
+        do {
+            ASSERT_OK(stream->getPresentationPosition(returnIn(res, framesInitial, ts)));
+            ASSERT_RESULT(okOrInvalidState, res);
+        } while (res != Result::OK);
+        uint64_t frames = framesInitial;
+        bool timedOut = false;
+        for (android::base::Timer elapsed;
+             frames <= framesInitial && !writer.hasError() &&
+             !(timedOut = (elapsed.duration() >= kPositionChangeTimeout));) {
+            usleep(kWriteDurationUs);
+            ASSERT_OK(stream->getPresentationPosition(returnIn(res, frames, ts)));
+            ASSERT_RESULT(Result::OK, res);
+        }
+        EXPECT_FALSE(timedOut);
+        EXPECT_FALSE(writer.hasError());
+        EXPECT_GT(frames, framesInitial);
+        if (firstPosition) *firstPosition = framesInitial;
+        if (lastPosition) *lastPosition = frames;
+    }
+
+  private:
+    AudioPatchHandle mPatchHandle = {};
+    bool mHasPatch = false;
+};
+
+TEST_P(PcmOnlyConfigOutputStreamTest, Write) {
+    doc::test("Check that output streams opened for PCM output accepts audio data");
+    StreamWriter writer(stream.get(), stream->getBufferSize());
+    ASSERT_TRUE(writer.start());
+    EXPECT_TRUE(writer.waitForAtLeastOneCycle());
+}
+
+TEST_P(PcmOnlyConfigOutputStreamTest, PresentationPositionAdvancesWithWrites) {
+    doc::test("Check that the presentation position advances with writes");
+    if (!canQueryPresentationPosition()) {
+        GTEST_SKIP() << "Presentation position retrieval is not possible";
+    }
+
+    ASSERT_NO_FATAL_FAILURE(createPatchIfNeeded());
+    StreamWriter writer(stream.get(), stream->getBufferSize());
+    ASSERT_TRUE(writer.start());
+    ASSERT_TRUE(writer.waitForAtLeastOneCycle());
+    ASSERT_NO_FATAL_FAILURE(waitForPresentationPositionAdvance(writer));
+
+    writer.stop();
+    releasePatchIfNeeded();
+}
+
+TEST_P(PcmOnlyConfigOutputStreamTest, PresentationPositionPreservedOnStandby) {
+    doc::test("Check that the presentation position does not reset on standby");
+    if (!canQueryPresentationPosition()) {
+        GTEST_SKIP() << "Presentation position retrieval is not possible";
+    }
+
+    ASSERT_NO_FATAL_FAILURE(createPatchIfNeeded());
+    StreamWriter writer(stream.get(), stream->getBufferSize());
+    ASSERT_TRUE(writer.start());
+    ASSERT_TRUE(writer.waitForAtLeastOneCycle());
+
+    uint64_t framesInitial;
+    ASSERT_NO_FATAL_FAILURE(waitForPresentationPositionAdvance(writer, nullptr, &framesInitial));
+    writer.pause();
+    ASSERT_OK(stream->standby());
+    writer.resume();
+
+    uint64_t frames;
+    ASSERT_NO_FATAL_FAILURE(waitForPresentationPositionAdvance(writer, &frames));
+    EXPECT_GT(frames, framesInitial);
+
+    writer.stop();
+    releasePatchIfNeeded();
+}
+
+INSTANTIATE_TEST_CASE_P(PcmOnlyConfigOutputStream, PcmOnlyConfigOutputStreamTest,
+                        ::testing::ValuesIn(getOutputDevicePcmOnlyConfigParameters()),
+                        &DeviceConfigParameterToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(PcmOnlyConfigOutputStreamTest);
+
+static const std::vector<DeviceConfigParameter>& getInputDevicePcmOnlyConfigParameters() {
+    static const std::vector<DeviceConfigParameter> parameters = [] {
+        auto allParams = getInputDeviceConfigParameters();
+        std::vector<DeviceConfigParameter> pcmParams;
+        std::copy_if(
+                allParams.begin(), allParams.end(), std::back_inserter(pcmParams), [](auto cfg) {
+                    const auto& flags = std::get<PARAM_FLAGS>(cfg);
+                    return xsd::isLinearPcm(std::get<PARAM_CONFIG>(cfg).base.format)
+                           // MMAP NOIRQ profiles use different reading protocol.
+                           &&
+                           std::find(flags.begin(), flags.end(),
+                                     toString(xsd::AudioInOutFlag::AUDIO_INPUT_FLAG_MMAP_NOIRQ)) ==
+                                   flags.end() &&
+                           !getCachedPolicyConfig()
+                                    .getAttachedSourceDeviceForMixPort(
+                                            std::get<PARAM_DEVICE_NAME>(
+                                                    std::get<PARAM_DEVICE>(cfg)),
+                                            std::get<PARAM_PORT_NAME>(cfg))
+                                    .empty();
+                });
+        return pcmParams;
+    }();
+    return parameters;
+}
+
+class PcmOnlyConfigInputStreamTest : public InputStreamTest {
+  public:
+    void TearDown() override {
+        releasePatchIfNeeded();
+        InputStreamTest::TearDown();
+    }
+
+    void createPatchIfNeeded() {
+        auto maybeSourceAddress = getCachedPolicyConfig().getSourceDeviceForMixPort(
+                getDeviceName(), getMixPortName());
+        ASSERT_TRUE(maybeSourceAddress.has_value())
+                << "No source device found for mix port " << getMixPortName() << " (module "
+                << getDeviceName() << ")";
+        if (areAudioPatchesSupported()) {
+            AudioPortConfig source;
+            source.ext.device(maybeSourceAddress.value());
+            AudioPortConfig sink;
+            sink.base.format.value(getConfig().base.format);
+            sink.base.sampleRateHz.value(getConfig().base.sampleRateHz);
+            sink.base.channelMask.value(getConfig().base.channelMask);
+            sink.ext.mix({});
+            sink.ext.mix().ioHandle = helper.getIoHandle();
+            sink.ext.mix().useCase.source(toString(xsd::AudioSource::AUDIO_SOURCE_MIC));
+            EXPECT_OK(getDevice()->createAudioPatch(hidl_vec<AudioPortConfig>{source},
+                                                    hidl_vec<AudioPortConfig>{sink},
+                                                    returnIn(res, mPatchHandle)));
+            mHasPatch = res == Result::OK;
+        } else {
+            EXPECT_OK(stream->setDevices({maybeSourceAddress.value()}));
+        }
+    }
+    void releasePatchIfNeeded() {
+        if (areAudioPatchesSupported()) {
+            if (mHasPatch) {
+                EXPECT_OK(getDevice()->releaseAudioPatch(mPatchHandle));
+                mHasPatch = false;
+            }
+        } else {
+            EXPECT_OK(stream->setDevices({address}));
+        }
+    }
+    const std::string& getMixPortName() const { return std::get<PARAM_PORT_NAME>(GetParam()); }
+
+  private:
+    AudioPatchHandle mPatchHandle = {};
+    bool mHasPatch = false;
+};
+
+TEST_P(PcmOnlyConfigInputStreamTest, Read) {
+    doc::test("Check that input streams opened for PCM input retrieve audio data");
+    StreamReader reader(stream.get(), stream->getBufferSize());
+    ASSERT_TRUE(reader.start());
+    EXPECT_TRUE(reader.waitForAtLeastOneCycle());
+}
+
+TEST_P(PcmOnlyConfigInputStreamTest, CapturePositionAdvancesWithReads) {
+    doc::test("Check that the capture position advances with reads");
+
+    ASSERT_NO_FATAL_FAILURE(createPatchIfNeeded());
+    StreamReader reader(stream.get(), stream->getBufferSize());
+    ASSERT_TRUE(reader.start());
+    EXPECT_TRUE(reader.waitForAtLeastOneCycle());
+
+    uint64_t framesInitial, ts;
+    ASSERT_OK(stream->getCapturePosition(returnIn(res, framesInitial, ts)));
+    ASSERT_RESULT(Result::OK, res);
+
+    EXPECT_TRUE(reader.waitForAtLeastOneCycle());
+
+    uint64_t frames;
+    ASSERT_OK(stream->getCapturePosition(returnIn(res, frames, ts)));
+    ASSERT_RESULT(Result::OK, res);
+    EXPECT_GT(frames, framesInitial);
+
+    reader.stop();
+    releasePatchIfNeeded();
+}
+
+TEST_P(PcmOnlyConfigInputStreamTest, CapturePositionPreservedOnStandby) {
+    doc::test("Check that the capture position does not reset on standby");
+
+    ASSERT_NO_FATAL_FAILURE(createPatchIfNeeded());
+    StreamReader reader(stream.get(), stream->getBufferSize());
+    ASSERT_TRUE(reader.start());
+    EXPECT_TRUE(reader.waitForAtLeastOneCycle());
+
+    uint64_t framesInitial, ts;
+    ASSERT_OK(stream->getCapturePosition(returnIn(res, framesInitial, ts)));
+    ASSERT_RESULT(Result::OK, res);
+
+    reader.pause();
+    ASSERT_OK(stream->standby());
+    reader.resume();
+    EXPECT_FALSE(reader.hasError());
+
+    uint64_t frames;
+    ASSERT_OK(stream->getCapturePosition(returnIn(res, frames, ts)));
+    ASSERT_RESULT(Result::OK, res);
+    EXPECT_GT(frames, framesInitial);
+
+    reader.stop();
+    releasePatchIfNeeded();
+}
+
+INSTANTIATE_TEST_CASE_P(PcmOnlyConfigInputStream, PcmOnlyConfigInputStreamTest,
+                        ::testing::ValuesIn(getInputDevicePcmOnlyConfigParameters()),
+                        &DeviceConfigParameterToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(PcmOnlyConfigInputStreamTest);
diff --git a/audio/core/all-versions/vts/functional/7.0/Generators.cpp b/audio/core/all-versions/vts/functional/7.0/Generators.cpp
index eafc813..d2ba339 100644
--- a/audio/core/all-versions/vts/functional/7.0/Generators.cpp
+++ b/audio/core/all-versions/vts/functional/7.0/Generators.cpp
@@ -110,7 +110,7 @@
                     if (isOffload) {
                         config.offloadInfo.info(generateOffloadInfo(config.base));
                     }
-                    result.emplace_back(device, config, flags);
+                    result.emplace_back(device, mixPort.getName(), config, flags);
                     if (oneProfilePerDevice) break;
                 }
                 if (oneProfilePerDevice) break;
@@ -160,7 +160,7 @@
                         if (isOffload) {
                             config.offloadInfo.info(generateOffloadInfo(validBase));
                         }
-                        result.emplace_back(device, config, validFlags);
+                        result.emplace_back(device, mixPort.getName(), config, validFlags);
                     }
                     {
                         AudioConfig config{.base = validBase};
@@ -168,7 +168,7 @@
                         if (isOffload) {
                             config.offloadInfo.info(generateOffloadInfo(validBase));
                         }
-                        result.emplace_back(device, config, validFlags);
+                        result.emplace_back(device, mixPort.getName(), config, validFlags);
                     }
                     if (generateInvalidFlags) {
                         AudioConfig config{.base = validBase};
@@ -176,32 +176,32 @@
                             config.offloadInfo.info(generateOffloadInfo(validBase));
                         }
                         std::vector<AudioInOutFlag> flags = {"random_string", ""};
-                        result.emplace_back(device, config, flags);
+                        result.emplace_back(device, mixPort.getName(), config, flags);
                     }
                     if (isOffload) {
                         {
                             AudioConfig config{.base = validBase};
                             config.offloadInfo.info(generateOffloadInfo(validBase));
                             config.offloadInfo.info().base.channelMask = "random_string";
-                            result.emplace_back(device, config, validFlags);
+                            result.emplace_back(device, mixPort.getName(), config, validFlags);
                         }
                         {
                             AudioConfig config{.base = validBase};
                             config.offloadInfo.info(generateOffloadInfo(validBase));
                             config.offloadInfo.info().base.format = "random_string";
-                            result.emplace_back(device, config, validFlags);
+                            result.emplace_back(device, mixPort.getName(), config, validFlags);
                         }
                         {
                             AudioConfig config{.base = validBase};
                             config.offloadInfo.info(generateOffloadInfo(validBase));
                             config.offloadInfo.info().streamType = "random_string";
-                            result.emplace_back(device, config, validFlags);
+                            result.emplace_back(device, mixPort.getName(), config, validFlags);
                         }
                         {
                             AudioConfig config{.base = validBase};
                             config.offloadInfo.info(generateOffloadInfo(validBase));
                             config.offloadInfo.info().usage = "random_string";
-                            result.emplace_back(device, config, validFlags);
+                            result.emplace_back(device, mixPort.getName(), config, validFlags);
                         }
                         hasOffloadConfig = true;
                     } else {
@@ -234,7 +234,7 @@
                 auto configs = combineAudioConfig(profile.getChannelMasks(),
                                                   profile.getSamplingRates(), profile.getFormat());
                 for (const auto& config : configs) {
-                    result.emplace_back(device, config, flags);
+                    result.emplace_back(device, mixPort.getName(), config, flags);
                     if (oneProfilePerDevice) break;
                 }
                 if (oneProfilePerDevice) break;
@@ -285,17 +285,17 @@
                     {
                         AudioConfig config{.base = validBase};
                         config.base.channelMask = "random_string";
-                        result.emplace_back(device, config, validFlags);
+                        result.emplace_back(device, mixPort.getName(), config, validFlags);
                     }
                     {
                         AudioConfig config{.base = validBase};
                         config.base.format = "random_string";
-                        result.emplace_back(device, config, validFlags);
+                        result.emplace_back(device, mixPort.getName(), config, validFlags);
                     }
                     if (generateInvalidFlags) {
                         AudioConfig config{.base = validBase};
                         std::vector<AudioInOutFlag> flags = {"random_string", ""};
-                        result.emplace_back(device, config, flags);
+                        result.emplace_back(device, mixPort.getName(), config, flags);
                     }
                     hasConfig = true;
                     break;
diff --git a/audio/core/all-versions/vts/functional/7.0/PolicyConfig.cpp b/audio/core/all-versions/vts/functional/7.0/PolicyConfig.cpp
new file mode 100644
index 0000000..2988207
--- /dev/null
+++ b/audio/core/all-versions/vts/functional/7.0/PolicyConfig.cpp
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <fcntl.h>
+#include <unistd.h>
+
+#include <algorithm>
+
+#include <HidlUtils.h>
+#include <system/audio.h>
+#include <system/audio_config.h>
+
+#include "DeviceManager.h"
+#include "PolicyConfig.h"
+#include "common/all-versions/HidlSupport.h"
+
+using ::android::NO_ERROR;
+using ::android::OK;
+
+using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::CPP_VERSION;
+using ::android::hardware::audio::common::CPP_VERSION::implementation::HidlUtils;
+using ::android::hardware::audio::common::utils::splitString;
+namespace xsd {
+using namespace ::android::audio::policy::configuration::CPP_VERSION;
+using Module = Modules::Module;
+}  // namespace xsd
+
+std::string PolicyConfig::getError() const {
+    if (mFilePath.empty()) {
+        return "Could not find " + mConfigFileName +
+               " file in: " + testing::PrintToString(android::audio_get_configuration_paths());
+    } else {
+        return "Invalid config file: " + mFilePath;
+    }
+}
+
+const xsd::Module* PolicyConfig::getModuleFromName(const std::string& name) const {
+    if (mConfig && mConfig->getFirstModules()) {
+        for (const auto& module : mConfig->getFirstModules()->get_module()) {
+            if (module.getName() == name) return &module;
+        }
+    }
+    return nullptr;
+}
+
+std::optional<DeviceAddress> PolicyConfig::getSinkDeviceForMixPort(
+        const std::string& moduleName, const std::string& mixPortName) const {
+    std::string device;
+    if (auto module = getModuleFromName(moduleName); module) {
+        auto possibleDevices = getSinkDevicesForMixPort(moduleName, mixPortName);
+        if (module->hasDefaultOutputDevice() &&
+            possibleDevices.count(module->getDefaultOutputDevice())) {
+            device = module->getDefaultOutputDevice();
+        } else {
+            device = getAttachedSinkDeviceForMixPort(moduleName, mixPortName);
+        }
+    }
+    if (!device.empty()) {
+        return getDeviceAddressOfDevicePort(moduleName, device);
+    }
+    ALOGE("Could not find a route for the mix port \"%s\" in module \"%s\"", mixPortName.c_str(),
+          moduleName.c_str());
+    return std::optional<DeviceAddress>{};
+}
+
+std::optional<DeviceAddress> PolicyConfig::getSourceDeviceForMixPort(
+        const std::string& moduleName, const std::string& mixPortName) const {
+    const std::string device = getAttachedSourceDeviceForMixPort(moduleName, mixPortName);
+    if (!device.empty()) {
+        return getDeviceAddressOfDevicePort(moduleName, device);
+    }
+    ALOGE("Could not find a route for the mix port \"%s\" in module \"%s\"", mixPortName.c_str(),
+          moduleName.c_str());
+    return std::optional<DeviceAddress>{};
+}
+
+bool PolicyConfig::haveInputProfilesInModule(const std::string& name) const {
+    auto module = getModuleFromName(name);
+    if (module && module->getFirstMixPorts()) {
+        for (const auto& mixPort : module->getFirstMixPorts()->getMixPort()) {
+            if (mixPort.getRole() == xsd::Role::sink) return true;
+        }
+    }
+    return false;
+}
+
+// static
+std::string PolicyConfig::findExistingConfigurationFile(const std::string& fileName) {
+    for (const auto& location : android::audio_get_configuration_paths()) {
+        std::string path = location + '/' + fileName;
+        if (access(path.c_str(), F_OK) == 0) {
+            return path;
+        }
+    }
+    return {};
+}
+
+std::string PolicyConfig::findAttachedDevice(const std::vector<std::string>& attachedDevices,
+                                             const std::set<std::string>& possibleDevices) const {
+    for (const auto& device : attachedDevices) {
+        if (possibleDevices.count(device)) return device;
+    }
+    return {};
+}
+
+const std::vector<std::string>& PolicyConfig::getAttachedDevices(
+        const std::string& moduleName) const {
+    static const std::vector<std::string> empty;
+    auto module = getModuleFromName(moduleName);
+    if (module && module->getFirstAttachedDevices()) {
+        return module->getFirstAttachedDevices()->getItem();
+    }
+    return empty;
+}
+
+std::optional<DeviceAddress> PolicyConfig::getDeviceAddressOfDevicePort(
+        const std::string& moduleName, const std::string& devicePortName) const {
+    auto module = getModuleFromName(moduleName);
+    if (module->getFirstDevicePorts()) {
+        const auto& devicePorts = module->getFirstDevicePorts()->getDevicePort();
+        const auto& devicePort = std::find_if(
+                devicePorts.begin(), devicePorts.end(),
+                [&devicePortName](auto dp) { return dp.getTagName() == devicePortName; });
+        if (devicePort != devicePorts.end()) {
+            audio_devices_t halDeviceType;
+            if (HidlUtils::audioDeviceTypeToHal(devicePort->getType(), &halDeviceType) ==
+                NO_ERROR) {
+                // For AOSP device types use the standard parser for the device address.
+                const std::string address =
+                        devicePort->hasAddress() ? devicePort->getAddress() : "";
+                DeviceAddress result;
+                if (HidlUtils::deviceAddressFromHal(halDeviceType, address.c_str(), &result) ==
+                    NO_ERROR) {
+                    return result;
+                }
+            } else if (xsd::isVendorExtension(devicePort->getType())) {
+                DeviceAddress result;
+                result.deviceType = devicePort->getType();
+                if (devicePort->hasAddress()) {
+                    result.address.id(devicePort->getAddress());
+                }
+                return result;
+            }
+        } else {
+            ALOGE("Device port \"%s\" not found in module \"%s\"", devicePortName.c_str(),
+                  moduleName.c_str());
+        }
+    } else {
+        ALOGE("Module \"%s\" has no device ports", moduleName.c_str());
+    }
+    return std::optional<DeviceAddress>{};
+}
+
+std::set<std::string> PolicyConfig::getSinkDevicesForMixPort(const std::string& moduleName,
+                                                             const std::string& mixPortName) const {
+    std::set<std::string> result;
+    auto module = getModuleFromName(moduleName);
+    if (module && module->getFirstRoutes()) {
+        for (const auto& route : module->getFirstRoutes()->getRoute()) {
+            const auto sources = splitString(route.getSources(), ',');
+            if (std::find(sources.begin(), sources.end(), mixPortName) != sources.end()) {
+                result.insert(route.getSink());
+            }
+        }
+    }
+    return result;
+}
+
+std::set<std::string> PolicyConfig::getSourceDevicesForMixPort(
+        const std::string& moduleName, const std::string& mixPortName) const {
+    std::set<std::string> result;
+    auto module = getModuleFromName(moduleName);
+    if (module && module->getFirstRoutes()) {
+        const auto& routes = module->getFirstRoutes()->getRoute();
+        const auto route = std::find_if(routes.begin(), routes.end(), [&mixPortName](auto rte) {
+            return rte.getSink() == mixPortName;
+        });
+        if (route != routes.end()) {
+            const auto sources = splitString(route->getSources(), ',');
+            std::copy(sources.begin(), sources.end(), std::inserter(result, result.end()));
+        }
+    }
+    return result;
+}
+
+void PolicyConfig::init() {
+    if (mConfig) {
+        mStatus = OK;
+        mPrimaryModule = getModuleFromName(DeviceManager::kPrimaryDevice);
+        if (mConfig->getFirstModules()) {
+            for (const auto& module : mConfig->getFirstModules()->get_module()) {
+                if (module.getFirstAttachedDevices()) {
+                    auto attachedDevices = module.getFirstAttachedDevices()->getItem();
+                    if (!attachedDevices.empty()) {
+                        mModulesWithDevicesNames.insert(module.getName());
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/audio/core/all-versions/vts/functional/7.0/PolicyConfig.h b/audio/core/all-versions/vts/functional/7.0/PolicyConfig.h
index feb4d4b..f798839 100644
--- a/audio/core/all-versions/vts/functional/7.0/PolicyConfig.h
+++ b/audio/core/all-versions/vts/functional/7.0/PolicyConfig.h
@@ -16,15 +16,12 @@
 
 #pragma once
 
-#include <fcntl.h>
-#include <unistd.h>
-
 #include <optional>
 #include <set>
 #include <string>
+#include <vector>
 
 #include <gtest/gtest.h>
-#include <system/audio_config.h>
 #include <utils/Errors.h>
 
 // clang-format off
@@ -35,12 +32,6 @@
 #include <android_audio_policy_configuration_V7_0-enums.h>
 #include <android_audio_policy_configuration_V7_0.h>
 
-#include "DeviceManager.h"
-
-using ::android::NO_INIT;
-using ::android::OK;
-using ::android::status_t;
-
 using namespace ::android::hardware::audio::common::CPP_VERSION;
 using namespace ::android::hardware::audio::CPP_VERSION;
 namespace xsd {
@@ -62,69 +53,49 @@
           mConfig{xsd::read(mFilePath.c_str())} {
         init();
     }
-    status_t getStatus() const { return mStatus; }
-    std::string getError() const {
-        if (mFilePath.empty()) {
-            return std::string{"Could not find "} + mConfigFileName +
-                   " file in: " + testing::PrintToString(android::audio_get_configuration_paths());
-        } else {
-            return "Invalid config file: " + mFilePath;
-        }
-    }
+    android::status_t getStatus() const { return mStatus; }
+    std::string getError() const;
     const std::string& getFilePath() const { return mFilePath; }
-    const xsd::Module* getModuleFromName(const std::string& name) const {
-        if (mConfig && mConfig->getFirstModules()) {
-            for (const auto& module : mConfig->getFirstModules()->get_module()) {
-                if (module.getName() == name) return &module;
-            }
-        }
-        return nullptr;
-    }
+    const xsd::Module* getModuleFromName(const std::string& name) const;
     const xsd::Module* getPrimaryModule() const { return mPrimaryModule; }
     const std::set<std::string>& getModulesWithDevicesNames() const {
         return mModulesWithDevicesNames;
     }
-    bool haveInputProfilesInModule(const std::string& name) const {
-        auto module = getModuleFromName(name);
-        if (module && module->getFirstMixPorts()) {
-            for (const auto& mixPort : module->getFirstMixPorts()->getMixPort()) {
-                if (mixPort.getRole() == xsd::Role::sink) return true;
-            }
-        }
-        return false;
+    std::string getAttachedSinkDeviceForMixPort(const std::string& moduleName,
+                                                const std::string& mixPortName) const {
+        return findAttachedDevice(getAttachedDevices(moduleName),
+                                  getSinkDevicesForMixPort(moduleName, mixPortName));
     }
+    std::string getAttachedSourceDeviceForMixPort(const std::string& moduleName,
+                                                  const std::string& mixPortName) const {
+        return findAttachedDevice(getAttachedDevices(moduleName),
+                                  getSourceDevicesForMixPort(moduleName, mixPortName));
+    }
+    std::optional<DeviceAddress> getSinkDeviceForMixPort(const std::string& moduleName,
+                                                         const std::string& mixPortName) const;
+    std::optional<DeviceAddress> getSourceDeviceForMixPort(const std::string& moduleName,
+                                                           const std::string& mixPortName) const;
+    bool haveInputProfilesInModule(const std::string& name) const;
 
   private:
-    static std::string findExistingConfigurationFile(const std::string& fileName) {
-        for (const auto& location : android::audio_get_configuration_paths()) {
-            std::string path = location + '/' + fileName;
-            if (access(path.c_str(), F_OK) == 0) {
-                return path;
-            }
-        }
-        return std::string{};
-    }
-    void init() {
-        if (mConfig) {
-            mStatus = OK;
-            mPrimaryModule = getModuleFromName(DeviceManager::kPrimaryDevice);
-            if (mConfig->getFirstModules()) {
-                for (const auto& module : mConfig->getFirstModules()->get_module()) {
-                    if (module.getFirstAttachedDevices()) {
-                        auto attachedDevices = module.getFirstAttachedDevices()->getItem();
-                        if (!attachedDevices.empty()) {
-                            mModulesWithDevicesNames.insert(module.getName());
-                        }
-                    }
-                }
-            }
-        }
-    }
+    static std::string findExistingConfigurationFile(const std::string& fileName);
+    std::string findAttachedDevice(const std::vector<std::string>& attachedDevices,
+                                   const std::set<std::string>& possibleDevices) const;
+    const std::vector<std::string>& getAttachedDevices(const std::string& moduleName) const;
+    std::optional<DeviceAddress> getDeviceAddressOfDevicePort(
+            const std::string& moduleName, const std::string& devicePortName) const;
+    std::string getDevicePortTagNameFromType(const std::string& moduleName,
+                                             const AudioDevice& deviceType) const;
+    std::set<std::string> getSinkDevicesForMixPort(const std::string& moduleName,
+                                                   const std::string& mixPortName) const;
+    std::set<std::string> getSourceDevicesForMixPort(const std::string& moduleName,
+                                                     const std::string& mixPortName) const;
+    void init();
 
     const std::string mConfigFileName;
     const std::string mFilePath;
     std::optional<xsd::AudioPolicyConfiguration> mConfig;
-    status_t mStatus = NO_INIT;
+    android::status_t mStatus = android::NO_INIT;
     const xsd::Module* mPrimaryModule;
     std::set<std::string> mModulesWithDevicesNames;
 };
diff --git a/audio/core/all-versions/vts/functional/Android.bp b/audio/core/all-versions/vts/functional/Android.bp
index 926a791..e446a7f 100644
--- a/audio/core/all-versions/vts/functional/Android.bp
+++ b/audio/core/all-versions/vts/functional/Android.bp
@@ -156,6 +156,7 @@
     srcs: [
         "7.0/AudioPrimaryHidlHalTest.cpp",
         "7.0/Generators.cpp",
+        "7.0/PolicyConfig.cpp",
     ],
     generated_headers: ["audio_policy_configuration_V7_0_parser"],
     generated_sources: ["audio_policy_configuration_V7_0_parser"],
@@ -163,6 +164,7 @@
         "android.hardware.audio@7.0",
         "android.hardware.audio.common@7.0",
         "android.hardware.audio.common@7.0-enums",
+        "android.hardware.audio.common@7.0-util",
     ],
     cflags: [
         "-DMAJOR_VERSION=7",
@@ -178,7 +180,15 @@
 }
 
 // Note: the following aren't VTS tests, but rather unit tests
-// to verify correctness of test parameter generator utilities.
+// to verify correctness of test utilities.
+cc_test {
+    name: "HalAudioStreamWorkerTest",
+    host_supported: true,
+    srcs: [
+        "tests/streamworker_tests.cpp",
+    ],
+}
+
 cc_test {
     name: "HalAudioV6_0GeneratorTest",
     defaults: ["VtsHalAudioTargetTest_defaults"],
@@ -210,6 +220,7 @@
     defaults: ["VtsHalAudioTargetTest_defaults"],
     srcs: [
         "7.0/Generators.cpp",
+        "7.0/PolicyConfig.cpp",
         "tests/generators_tests.cpp",
     ],
     generated_headers: ["audio_policy_configuration_V7_0_parser"],
@@ -218,6 +229,7 @@
         "android.hardware.audio@7.0",
         "android.hardware.audio.common@7.0",
         "android.hardware.audio.common@7.0-enums",
+        "android.hardware.audio.common@7.0-util",
     ],
     cflags: [
         "-DMAJOR_VERSION=7",
diff --git a/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h b/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
index 56939fe..ae1467d 100644
--- a/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
+++ b/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
@@ -89,6 +89,10 @@
 using namespace ::android::hardware::audio::common::CPP_VERSION;
 using namespace ::android::hardware::audio::common::test::utility;
 using namespace ::android::hardware::audio::CPP_VERSION;
+using ReadParameters = ::android::hardware::audio::CPP_VERSION::IStreamIn::ReadParameters;
+using ReadStatus = ::android::hardware::audio::CPP_VERSION::IStreamIn::ReadStatus;
+using WriteCommand = ::android::hardware::audio::CPP_VERSION::IStreamOut::WriteCommand;
+using WriteStatus = ::android::hardware::audio::CPP_VERSION::IStreamOut::WriteStatus;
 #if MAJOR_VERSION >= 7
 // Make an alias for enumerations generated from the APM config XSD.
 namespace xsd {
@@ -100,6 +104,7 @@
 static auto okOrNotSupported = {Result::OK, Result::NOT_SUPPORTED};
 static auto okOrNotSupportedOrInvalidArgs = {Result::OK, Result::NOT_SUPPORTED,
                                              Result::INVALID_ARGUMENTS};
+static auto okOrInvalidState = {Result::OK, Result::INVALID_STATE};
 static auto okOrInvalidStateOrNotSupported = {Result::OK, Result::INVALID_STATE,
                                               Result::NOT_SUPPORTED};
 static auto invalidArgsOrNotSupported = {Result::INVALID_ARGUMENTS, Result::NOT_SUPPORTED};
@@ -115,6 +120,7 @@
 #include "7.0/Generators.h"
 #include "7.0/PolicyConfig.h"
 #endif
+#include "StreamWorker.h"
 
 class HidlTest : public ::testing::Test {
   public:
@@ -778,6 +784,11 @@
 ////////////////////////// open{Output,Input}Stream //////////////////////////
 //////////////////////////////////////////////////////////////////////////////
 
+static inline AudioIoHandle getNextIoHandle() {
+    static AudioIoHandle lastHandle{};
+    return ++lastHandle;
+}
+
 // This class is also used by some device tests.
 template <class Stream>
 class StreamHelper {
@@ -787,16 +798,13 @@
     template <class Open>
     void open(Open openStream, const AudioConfig& config, Result* res,
               AudioConfig* suggestedConfigPtr) {
-        // FIXME: Open a stream without an IOHandle
-        //        This is not required to be accepted by hal implementations
-        AudioIoHandle ioHandle{};
         AudioConfig suggestedConfig{};
         bool retryWithSuggestedConfig = true;
         if (suggestedConfigPtr == nullptr) {
             suggestedConfigPtr = &suggestedConfig;
             retryWithSuggestedConfig = false;
         }
-        ASSERT_OK(openStream(ioHandle, config, returnIn(*res, mStream, *suggestedConfigPtr)));
+        ASSERT_OK(openStream(mIoHandle, config, returnIn(*res, mStream, *suggestedConfigPtr)));
         switch (*res) {
             case Result::OK:
                 ASSERT_TRUE(mStream != nullptr);
@@ -806,7 +814,7 @@
                 ASSERT_TRUE(mStream == nullptr);
                 if (retryWithSuggestedConfig) {
                     AudioConfig suggestedConfigRetry;
-                    ASSERT_OK(openStream(ioHandle, *suggestedConfigPtr,
+                    ASSERT_OK(openStream(mIoHandle, *suggestedConfigPtr,
                                          returnIn(*res, mStream, suggestedConfigRetry)));
                     ASSERT_OK(*res);
                     ASSERT_TRUE(mStream != nullptr);
@@ -834,8 +842,10 @@
 #endif
         }
     }
+    AudioIoHandle getIoHandle() const { return mIoHandle; }
 
   private:
+    const AudioIoHandle mIoHandle = getNextIoHandle();
     sp<Stream>& mStream;
 };
 
@@ -861,7 +871,6 @@
         return res;
     }
 
-  private:
     void TearDown() override {
         if (open) {
             ASSERT_OK(closeStream());
@@ -879,6 +888,116 @@
 
 ////////////////////////////// openOutputStream //////////////////////////////
 
+class StreamWriter : public StreamWorker<StreamWriter> {
+  public:
+    StreamWriter(IStreamOut* stream, size_t bufferSize)
+        : mStream(stream), mBufferSize(bufferSize), mData(mBufferSize) {}
+    ~StreamWriter() {
+        stop();
+        if (mEfGroup) {
+            EventFlag::deleteEventFlag(&mEfGroup);
+        }
+    }
+
+    typedef MessageQueue<WriteCommand, ::android::hardware::kSynchronizedReadWrite> CommandMQ;
+    typedef MessageQueue<uint8_t, ::android::hardware::kSynchronizedReadWrite> DataMQ;
+    typedef MessageQueue<WriteStatus, ::android::hardware::kSynchronizedReadWrite> StatusMQ;
+
+    bool workerInit() {
+        std::unique_ptr<CommandMQ> tempCommandMQ;
+        std::unique_ptr<DataMQ> tempDataMQ;
+        std::unique_ptr<StatusMQ> tempStatusMQ;
+        Result retval;
+        Return<void> ret = mStream->prepareForWriting(
+                1, mBufferSize,
+                [&](Result r, const CommandMQ::Descriptor& commandMQ,
+                    const DataMQ::Descriptor& dataMQ, const StatusMQ::Descriptor& statusMQ,
+                    const auto& /*halThreadInfo*/) {
+                    retval = r;
+                    if (retval == Result::OK) {
+                        tempCommandMQ.reset(new CommandMQ(commandMQ));
+                        tempDataMQ.reset(new DataMQ(dataMQ));
+                        tempStatusMQ.reset(new StatusMQ(statusMQ));
+                        if (tempDataMQ->isValid() && tempDataMQ->getEventFlagWord()) {
+                            EventFlag::createEventFlag(tempDataMQ->getEventFlagWord(), &mEfGroup);
+                        }
+                    }
+                });
+        if (!ret.isOk()) {
+            ALOGE("Transport error while calling prepareForWriting: %s", ret.description().c_str());
+            return false;
+        }
+        if (retval != Result::OK) {
+            ALOGE("Error from prepareForWriting: %d", retval);
+            return false;
+        }
+        if (!tempCommandMQ || !tempCommandMQ->isValid() || !tempDataMQ || !tempDataMQ->isValid() ||
+            !tempStatusMQ || !tempStatusMQ->isValid() || !mEfGroup) {
+            ALOGE_IF(!tempCommandMQ, "Failed to obtain command message queue for writing");
+            ALOGE_IF(tempCommandMQ && !tempCommandMQ->isValid(),
+                     "Command message queue for writing is invalid");
+            ALOGE_IF(!tempDataMQ, "Failed to obtain data message queue for writing");
+            ALOGE_IF(tempDataMQ && !tempDataMQ->isValid(),
+                     "Data message queue for writing is invalid");
+            ALOGE_IF(!tempStatusMQ, "Failed to obtain status message queue for writing");
+            ALOGE_IF(tempStatusMQ && !tempStatusMQ->isValid(),
+                     "Status message queue for writing is invalid");
+            ALOGE_IF(!mEfGroup, "Event flag creation for writing failed");
+            return false;
+        }
+        mCommandMQ = std::move(tempCommandMQ);
+        mDataMQ = std::move(tempDataMQ);
+        mStatusMQ = std::move(tempStatusMQ);
+        return true;
+    }
+
+    bool workerCycle() {
+        WriteCommand cmd = WriteCommand::WRITE;
+        if (!mCommandMQ->write(&cmd)) {
+            ALOGE("command message queue write failed");
+            return false;
+        }
+        const size_t dataSize = std::min(mData.size(), mDataMQ->availableToWrite());
+        bool success = mDataMQ->write(mData.data(), dataSize);
+        ALOGE_IF(!success, "data message queue write failed");
+        mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY));
+
+        uint32_t efState = 0;
+    retry:
+        status_t ret =
+                mEfGroup->wait(static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL), &efState);
+        if (efState & static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL)) {
+            WriteStatus writeStatus;
+            writeStatus.retval = Result::NOT_INITIALIZED;
+            if (!mStatusMQ->read(&writeStatus)) {
+                ALOGE("status message read failed");
+                success = false;
+            }
+            if (writeStatus.retval != Result::OK) {
+                ALOGE("bad write status: %d", writeStatus.retval);
+                success = false;
+            }
+        }
+        if (ret == -EAGAIN || ret == -EINTR) {
+            // Spurious wakeup. This normally retries no more than once.
+            goto retry;
+        } else if (ret) {
+            ALOGE("bad wait status: %d", ret);
+            success = false;
+        }
+        return success;
+    }
+
+  private:
+    IStreamOut* const mStream;
+    const size_t mBufferSize;
+    std::vector<uint8_t> mData;
+    std::unique_ptr<CommandMQ> mCommandMQ;
+    std::unique_ptr<DataMQ> mDataMQ;
+    std::unique_ptr<StatusMQ> mStatusMQ;
+    EventFlag* mEfGroup = nullptr;
+};
+
 class OutputStreamTest : public OpenStreamTest<IStreamOut> {
     void SetUp() override {
         ASSERT_NO_FATAL_FAILURE(OpenStreamTest::SetUp());  // setup base
@@ -954,6 +1073,121 @@
 
 ////////////////////////////// openInputStream //////////////////////////////
 
+class StreamReader : public StreamWorker<StreamReader> {
+  public:
+    StreamReader(IStreamIn* stream, size_t bufferSize)
+        : mStream(stream), mBufferSize(bufferSize), mData(mBufferSize) {}
+    ~StreamReader() {
+        stop();
+        if (mEfGroup) {
+            EventFlag::deleteEventFlag(&mEfGroup);
+        }
+    }
+
+    typedef MessageQueue<ReadParameters, ::android::hardware::kSynchronizedReadWrite> CommandMQ;
+    typedef MessageQueue<uint8_t, ::android::hardware::kSynchronizedReadWrite> DataMQ;
+    typedef MessageQueue<ReadStatus, ::android::hardware::kSynchronizedReadWrite> StatusMQ;
+
+    bool workerInit() {
+        std::unique_ptr<CommandMQ> tempCommandMQ;
+        std::unique_ptr<DataMQ> tempDataMQ;
+        std::unique_ptr<StatusMQ> tempStatusMQ;
+        Result retval;
+        Return<void> ret = mStream->prepareForReading(
+                1, mBufferSize,
+                [&](Result r, const CommandMQ::Descriptor& commandMQ,
+                    const DataMQ::Descriptor& dataMQ, const StatusMQ::Descriptor& statusMQ,
+                    const auto& /*halThreadInfo*/) {
+                    retval = r;
+                    if (retval == Result::OK) {
+                        tempCommandMQ.reset(new CommandMQ(commandMQ));
+                        tempDataMQ.reset(new DataMQ(dataMQ));
+                        tempStatusMQ.reset(new StatusMQ(statusMQ));
+                        if (tempDataMQ->isValid() && tempDataMQ->getEventFlagWord()) {
+                            EventFlag::createEventFlag(tempDataMQ->getEventFlagWord(), &mEfGroup);
+                        }
+                    }
+                });
+        if (!ret.isOk()) {
+            ALOGE("Transport error while calling prepareForReading: %s", ret.description().c_str());
+            return false;
+        }
+        if (retval != Result::OK) {
+            ALOGE("Error from prepareForReading: %d", retval);
+            return false;
+        }
+        if (!tempCommandMQ || !tempCommandMQ->isValid() || !tempDataMQ || !tempDataMQ->isValid() ||
+            !tempStatusMQ || !tempStatusMQ->isValid() || !mEfGroup) {
+            ALOGE_IF(!tempCommandMQ, "Failed to obtain command message queue for reading");
+            ALOGE_IF(tempCommandMQ && !tempCommandMQ->isValid(),
+                     "Command message queue for reading is invalid");
+            ALOGE_IF(!tempDataMQ, "Failed to obtain data message queue for reading");
+            ALOGE_IF(tempDataMQ && !tempDataMQ->isValid(),
+                     "Data message queue for reading is invalid");
+            ALOGE_IF(!tempStatusMQ, "Failed to obtain status message queue for reading");
+            ALOGE_IF(tempStatusMQ && !tempStatusMQ->isValid(),
+                     "Status message queue for reading is invalid");
+            ALOGE_IF(!mEfGroup, "Event flag creation for reading failed");
+            return false;
+        }
+        mCommandMQ = std::move(tempCommandMQ);
+        mDataMQ = std::move(tempDataMQ);
+        mStatusMQ = std::move(tempStatusMQ);
+        return true;
+    }
+
+    bool workerCycle() {
+        ReadParameters params;
+        params.command = IStreamIn::ReadCommand::READ;
+        params.params.read = mBufferSize;
+        if (!mCommandMQ->write(&params)) {
+            ALOGE("command message queue write failed");
+            return false;
+        }
+        mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL));
+
+        uint32_t efState = 0;
+        bool success = true;
+    retry:
+        status_t ret =
+                mEfGroup->wait(static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY), &efState);
+        if (efState & static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY)) {
+            ReadStatus readStatus;
+            readStatus.retval = Result::NOT_INITIALIZED;
+            if (!mStatusMQ->read(&readStatus)) {
+                ALOGE("status message read failed");
+                success = false;
+            }
+            if (readStatus.retval != Result::OK) {
+                ALOGE("bad read status: %d", readStatus.retval);
+                success = false;
+            }
+            const size_t dataSize = std::min(mData.size(), mDataMQ->availableToRead());
+            if (!mDataMQ->read(mData.data(), dataSize)) {
+                ALOGE("data message queue read failed");
+                success = false;
+            }
+        }
+        if (ret == -EAGAIN || ret == -EINTR) {
+            // Spurious wakeup. This normally retries no more than once.
+            goto retry;
+        } else if (ret) {
+            ALOGE("bad wait status: %d", ret);
+            success = false;
+        }
+        return success;
+    }
+
+  private:
+    IStreamIn* const mStream;
+    const size_t mBufferSize;
+    std::vector<uint8_t> mData;
+    std::unique_ptr<CommandMQ> mCommandMQ;
+    std::unique_ptr<DataMQ> mDataMQ;
+    std::unique_ptr<StatusMQ> mStatusMQ;
+    EventFlag* mEfGroup = nullptr;
+};
+
 class InputStreamTest : public OpenStreamTest<IStreamIn> {
     void SetUp() override {
         ASSERT_NO_FATAL_FAILURE(OpenStreamTest::SetUp());  // setup base
@@ -1377,6 +1611,12 @@
     uint64_t frames;
     uint64_t time;
     ASSERT_OK(stream->getCapturePosition(returnIn(res, frames, time)));
+    // Although 'getCapturePosition' is mandatory in V7, legacy implementations
+    // may return -ENOSYS (which is translated to NOT_SUPPORTED) in cases when
+    // the capture position can't be retrieved, e.g. when the stream isn't
+    // running. Because of this, we don't fail when getting NOT_SUPPORTED
+    // in this test. Behavior of 'getCapturePosition' for running streams is
+    // tested in 'PcmOnlyConfigInputStreamTest' for V7.
     ASSERT_RESULT(okOrInvalidStateOrNotSupported, res);
     if (res == Result::OK) {
         ASSERT_EQ(0U, frames);
@@ -1560,15 +1800,19 @@
         "If supported, a stream should always succeed to retrieve the "
         "presentation position");
     uint64_t frames;
-    TimeSpec mesureTS;
-    ASSERT_OK(stream->getPresentationPosition(returnIn(res, frames, mesureTS)));
+    TimeSpec measureTS;
+    ASSERT_OK(stream->getPresentationPosition(returnIn(res, frames, measureTS)));
+#if MAJOR_VERSION <= 6
     if (res == Result::NOT_SUPPORTED) {
-        doc::partialTest("getpresentationPosition is not supported");
+        doc::partialTest("getPresentationPosition is not supported");
         return;
     }
+#else
+    ASSERT_NE(Result::NOT_SUPPORTED, res) << "getPresentationPosition is mandatory in V7";
+#endif
     ASSERT_EQ(0U, frames);
 
-    if (mesureTS.tvNSec == 0 && mesureTS.tvSec == 0) {
+    if (measureTS.tvNSec == 0 && measureTS.tvSec == 0) {
         // As the stream has never written a frame yet,
         // the timestamp does not really have a meaning, allow to return 0
         return;
@@ -1580,8 +1824,8 @@
 
     auto toMicroSec = [](uint64_t sec, auto nsec) { return sec * 1e+6 + nsec / 1e+3; };
     auto currentTime = toMicroSec(currentTS.tv_sec, currentTS.tv_nsec);
-    auto mesureTime = toMicroSec(mesureTS.tvSec, mesureTS.tvNSec);
-    ASSERT_PRED2([](auto c, auto m) { return c - m < 1e+6; }, currentTime, mesureTime);
+    auto measureTime = toMicroSec(measureTS.tvSec, measureTS.tvNSec);
+    ASSERT_PRED2([](auto c, auto m) { return c - m < 1e+6; }, currentTime, measureTime);
 }
 
 //////////////////////////////////////////////////////////////////////////////
diff --git a/audio/core/all-versions/vts/functional/AudioTestDefinitions.h b/audio/core/all-versions/vts/functional/AudioTestDefinitions.h
index 5b14a21..aa67630 100644
--- a/audio/core/all-versions/vts/functional/AudioTestDefinitions.h
+++ b/audio/core/all-versions/vts/functional/AudioTestDefinitions.h
@@ -31,15 +31,17 @@
 
 // Nesting a tuple in another tuple allows to use GTest Combine function to generate
 // all combinations of devices and configs.
-enum { PARAM_DEVICE, PARAM_CONFIG, PARAM_FLAGS };
 #if MAJOR_VERSION <= 6
+enum { PARAM_DEVICE, PARAM_CONFIG, PARAM_FLAGS };
 enum { INDEX_INPUT, INDEX_OUTPUT };
 using DeviceConfigParameter =
         std::tuple<DeviceParameter, android::hardware::audio::common::CPP_VERSION::AudioConfig,
                    std::variant<android::hardware::audio::common::CPP_VERSION::AudioInputFlag,
                                 android::hardware::audio::common::CPP_VERSION::AudioOutputFlag>>;
 #elif MAJOR_VERSION >= 7
+enum { PARAM_DEVICE, PARAM_PORT_NAME, PARAM_CONFIG, PARAM_FLAGS };
 using DeviceConfigParameter =
-        std::tuple<DeviceParameter, android::hardware::audio::common::CPP_VERSION::AudioConfig,
+        std::tuple<DeviceParameter, std::string,
+                   android::hardware::audio::common::CPP_VERSION::AudioConfig,
                    std::vector<android::hardware::audio::CPP_VERSION::AudioInOutFlag>>;
 #endif
diff --git a/audio/core/all-versions/vts/functional/StreamWorker.h b/audio/core/all-versions/vts/functional/StreamWorker.h
new file mode 100644
index 0000000..68a8024
--- /dev/null
+++ b/audio/core/all-versions/vts/functional/StreamWorker.h
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <sched.h>
+
+#include <condition_variable>
+#include <mutex>
+#include <thread>
+
+template <typename Impl>
+class StreamWorker {
+    enum class WorkerState { STOPPED, RUNNING, PAUSE_REQUESTED, PAUSED, RESUME_REQUESTED, ERROR };
+
+  public:
+    StreamWorker() = default;
+    ~StreamWorker() { stop(); }
+    bool start() {
+        mWorker = std::thread(&StreamWorker::workerThread, this);
+        std::unique_lock<std::mutex> lock(mWorkerLock);
+        mWorkerCv.wait(lock, [&] { return mWorkerState != WorkerState::STOPPED; });
+        return mWorkerState == WorkerState::RUNNING;
+    }
+    void pause() { switchWorkerStateSync(WorkerState::RUNNING, WorkerState::PAUSE_REQUESTED); }
+    void resume() { switchWorkerStateSync(WorkerState::PAUSED, WorkerState::RESUME_REQUESTED); }
+    bool hasError() {
+        std::lock_guard<std::mutex> lock(mWorkerLock);
+        return mWorkerState == WorkerState::ERROR;
+    }
+    void stop() {
+        {
+            std::lock_guard<std::mutex> lock(mWorkerLock);
+            if (mWorkerState == WorkerState::STOPPED) return;
+            mWorkerState = WorkerState::STOPPED;
+        }
+        if (mWorker.joinable()) {
+            mWorker.join();
+        }
+    }
+    bool waitForAtLeastOneCycle() {
+        WorkerState newState;
+        switchWorkerStateSync(WorkerState::RUNNING, WorkerState::PAUSE_REQUESTED, &newState);
+        if (newState != WorkerState::PAUSED) return false;
+        switchWorkerStateSync(newState, WorkerState::RESUME_REQUESTED, &newState);
+        return newState == WorkerState::RUNNING;
+    }
+
+    // Methods that need to be provided by subclasses:
+    //
+    // Called once at the beginning of the thread loop. Must return
+    // 'true' to enter the thread loop, otherwise the thread loop
+    // exits and the worker switches into the 'error' state.
+    // bool workerInit();
+    //
+    // Called for each thread loop unless the thread is in 'paused' state.
+    // Must return 'true' to continue running, otherwise the thread loop
+    // exits and the worker switches into the 'error' state.
+    // bool workerCycle();
+
+  private:
+    void switchWorkerStateSync(WorkerState oldState, WorkerState newState,
+                               WorkerState* finalState = nullptr) {
+        std::unique_lock<std::mutex> lock(mWorkerLock);
+        if (mWorkerState != oldState) {
+            if (finalState) *finalState = mWorkerState;
+            return;
+        }
+        mWorkerState = newState;
+        mWorkerCv.wait(lock, [&] { return mWorkerState != newState; });
+        if (finalState) *finalState = mWorkerState;
+    }
+    void workerThread() {
+        bool success = static_cast<Impl*>(this)->workerInit();
+        {
+            std::lock_guard<std::mutex> lock(mWorkerLock);
+            mWorkerState = success ? WorkerState::RUNNING : WorkerState::ERROR;
+        }
+        mWorkerCv.notify_one();
+        if (!success) return;
+
+        for (WorkerState state = WorkerState::RUNNING; state != WorkerState::STOPPED;) {
+            bool needToNotify = false;
+            if (state != WorkerState::PAUSED ? static_cast<Impl*>(this)->workerCycle()
+                                             : (sched_yield(), true)) {
+                //
+                // Pause and resume are synchronous. One worker cycle must complete
+                // before the worker indicates a state change. This is how 'mWorkerState' and
+                // 'state' interact:
+                //
+                // mWorkerState == RUNNING
+                // client sets mWorkerState := PAUSE_REQUESTED
+                // last workerCycle gets executed, state := mWorkerState := PAUSED by us
+                //   (or the workers enters the 'error' state if workerCycle fails)
+                // client gets notified about state change in any case
+                // thread is doing a busy wait while 'state == PAUSED'
+                // client sets mWorkerState := RESUME_REQUESTED
+                // state := mWorkerState (RESUME_REQUESTED)
+                // mWorkerState := RUNNING, but we don't notify the client yet
+                // first workerCycle gets executed, the code below triggers a client notification
+                //   (or if workerCycle fails, worker enters 'error' state and also notifies)
+                // state := mWorkerState (RUNNING)
+                if (state == WorkerState::RESUME_REQUESTED) {
+                    needToNotify = true;
+                }
+                std::lock_guard<std::mutex> lock(mWorkerLock);
+                state = mWorkerState;
+                if (mWorkerState == WorkerState::PAUSE_REQUESTED) {
+                    state = mWorkerState = WorkerState::PAUSED;
+                    needToNotify = true;
+                } else if (mWorkerState == WorkerState::RESUME_REQUESTED) {
+                    mWorkerState = WorkerState::RUNNING;
+                }
+            } else {
+                std::lock_guard<std::mutex> lock(mWorkerLock);
+                if (state == WorkerState::RESUME_REQUESTED ||
+                    mWorkerState == WorkerState::PAUSE_REQUESTED) {
+                    needToNotify = true;
+                }
+                mWorkerState = WorkerState::ERROR;
+                state = WorkerState::STOPPED;
+            }
+            if (needToNotify) {
+                mWorkerCv.notify_one();
+            }
+        }
+    }
+
+    std::thread mWorker;
+    std::mutex mWorkerLock;
+    std::condition_variable mWorkerCv;
+    WorkerState mWorkerState = WorkerState::STOPPED;  // GUARDED_BY(mWorkerLock);
+};
diff --git a/audio/core/all-versions/vts/functional/tests/streamworker_tests.cpp b/audio/core/all-versions/vts/functional/tests/streamworker_tests.cpp
new file mode 100644
index 0000000..75116af
--- /dev/null
+++ b/audio/core/all-versions/vts/functional/tests/streamworker_tests.cpp
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "StreamWorker.h"
+
+#include <sched.h>
+#include <unistd.h>
+#include <atomic>
+
+#include <gtest/gtest.h>
+#define LOG_TAG "StreamWorker_Test"
+#include <log/log.h>
+
+struct TestStream {
+    std::atomic<bool> error = false;
+};
+
+class TestWorker : public StreamWorker<TestWorker> {
+  public:
+    // Use nullptr to test error reporting from the worker thread.
+    explicit TestWorker(TestStream* stream) : mStream(stream) {}
+
+    void ensureWorkerCycled() {
+        const size_t cyclesBefore = mWorkerCycles;
+        while (mWorkerCycles == cyclesBefore && !hasError()) {
+            sched_yield();
+        }
+    }
+    size_t getWorkerCycles() const { return mWorkerCycles; }
+    bool hasWorkerCycleCalled() const { return mWorkerCycles != 0; }
+    bool hasNoWorkerCycleCalled(useconds_t usec) {
+        const size_t cyclesBefore = mWorkerCycles;
+        usleep(usec);
+        return mWorkerCycles == cyclesBefore;
+    }
+
+    bool workerInit() { return mStream; }
+    bool workerCycle() {
+        do {
+            mWorkerCycles++;
+        } while (mWorkerCycles == 0);
+        return !mStream->error;
+    }
+
+  private:
+    TestStream* const mStream;
+    std::atomic<size_t> mWorkerCycles = 0;
+};
+
+// The parameter specifies whether an extra call to 'stop' is made at the end.
+class StreamWorkerInvalidTest : public testing::TestWithParam<bool> {
+  public:
+    StreamWorkerInvalidTest() : StreamWorkerInvalidTest(nullptr) {}
+    void TearDown() override {
+        if (GetParam()) {
+            worker.stop();
+        }
+    }
+
+  protected:
+    StreamWorkerInvalidTest(TestStream* stream) : testing::TestWithParam<bool>(), worker(stream) {}
+    TestWorker worker;
+};
+
+TEST_P(StreamWorkerInvalidTest, Uninitialized) {
+    EXPECT_FALSE(worker.hasWorkerCycleCalled());
+    EXPECT_FALSE(worker.hasError());
+}
+
+TEST_P(StreamWorkerInvalidTest, UninitializedPauseIgnored) {
+    EXPECT_FALSE(worker.hasError());
+    worker.pause();
+    EXPECT_FALSE(worker.hasError());
+}
+
+TEST_P(StreamWorkerInvalidTest, UninitializedResumeIgnored) {
+    EXPECT_FALSE(worker.hasError());
+    worker.resume();
+    EXPECT_FALSE(worker.hasError());
+}
+
+TEST_P(StreamWorkerInvalidTest, Start) {
+    EXPECT_FALSE(worker.start());
+    EXPECT_FALSE(worker.hasWorkerCycleCalled());
+    EXPECT_TRUE(worker.hasError());
+}
+
+TEST_P(StreamWorkerInvalidTest, PauseIgnored) {
+    EXPECT_FALSE(worker.start());
+    EXPECT_TRUE(worker.hasError());
+    worker.pause();
+    EXPECT_TRUE(worker.hasError());
+}
+
+TEST_P(StreamWorkerInvalidTest, ResumeIgnored) {
+    EXPECT_FALSE(worker.start());
+    EXPECT_TRUE(worker.hasError());
+    worker.resume();
+    EXPECT_TRUE(worker.hasError());
+}
+
+INSTANTIATE_TEST_SUITE_P(StreamWorkerInvalid, StreamWorkerInvalidTest, testing::Bool());
+
+class StreamWorkerTest : public StreamWorkerInvalidTest {
+  public:
+    StreamWorkerTest() : StreamWorkerInvalidTest(&stream) {}
+
+  protected:
+    TestStream stream;
+};
+
+static constexpr unsigned kWorkerIdleCheckTime = 50 * 1000;
+
+TEST_P(StreamWorkerTest, Uninitialized) {
+    EXPECT_FALSE(worker.hasWorkerCycleCalled());
+    EXPECT_FALSE(worker.hasError());
+}
+
+TEST_P(StreamWorkerTest, Start) {
+    ASSERT_TRUE(worker.start());
+    worker.ensureWorkerCycled();
+    EXPECT_FALSE(worker.hasError());
+}
+
+TEST_P(StreamWorkerTest, WorkerError) {
+    ASSERT_TRUE(worker.start());
+    stream.error = true;
+    worker.ensureWorkerCycled();
+    EXPECT_TRUE(worker.hasError());
+    EXPECT_TRUE(worker.hasNoWorkerCycleCalled(kWorkerIdleCheckTime));
+}
+
+TEST_P(StreamWorkerTest, PauseResume) {
+    ASSERT_TRUE(worker.start());
+    worker.ensureWorkerCycled();
+    EXPECT_FALSE(worker.hasError());
+    worker.pause();
+    EXPECT_TRUE(worker.hasNoWorkerCycleCalled(kWorkerIdleCheckTime));
+    EXPECT_FALSE(worker.hasError());
+    const size_t workerCyclesBefore = worker.getWorkerCycles();
+    worker.resume();
+    // 'resume' is synchronous and returns after the worker has looped at least once.
+    EXPECT_GT(worker.getWorkerCycles(), workerCyclesBefore);
+    EXPECT_FALSE(worker.hasError());
+}
+
+TEST_P(StreamWorkerTest, StopPaused) {
+    ASSERT_TRUE(worker.start());
+    worker.ensureWorkerCycled();
+    EXPECT_FALSE(worker.hasError());
+    worker.pause();
+    worker.stop();
+    EXPECT_FALSE(worker.hasError());
+}
+
+TEST_P(StreamWorkerTest, PauseAfterErrorIgnored) {
+    ASSERT_TRUE(worker.start());
+    stream.error = true;
+    worker.ensureWorkerCycled();
+    EXPECT_TRUE(worker.hasError());
+    worker.pause();
+    EXPECT_TRUE(worker.hasNoWorkerCycleCalled(kWorkerIdleCheckTime));
+    EXPECT_TRUE(worker.hasError());
+}
+
+TEST_P(StreamWorkerTest, ResumeAfterErrorIgnored) {
+    ASSERT_TRUE(worker.start());
+    stream.error = true;
+    worker.ensureWorkerCycled();
+    EXPECT_TRUE(worker.hasError());
+    worker.resume();
+    EXPECT_TRUE(worker.hasNoWorkerCycleCalled(kWorkerIdleCheckTime));
+    EXPECT_TRUE(worker.hasError());
+}
+
+TEST_P(StreamWorkerTest, WorkerErrorOnResume) {
+    ASSERT_TRUE(worker.start());
+    worker.ensureWorkerCycled();
+    EXPECT_FALSE(worker.hasError());
+    worker.pause();
+    EXPECT_FALSE(worker.hasError());
+    stream.error = true;
+    EXPECT_FALSE(worker.hasError());
+    worker.resume();
+    worker.ensureWorkerCycled();
+    EXPECT_TRUE(worker.hasError());
+    EXPECT_TRUE(worker.hasNoWorkerCycleCalled(kWorkerIdleCheckTime));
+}
+
+TEST_P(StreamWorkerTest, WaitForAtLeastOneCycle) {
+    ASSERT_TRUE(worker.start());
+    const size_t workerCyclesBefore = worker.getWorkerCycles();
+    EXPECT_TRUE(worker.waitForAtLeastOneCycle());
+    EXPECT_GT(worker.getWorkerCycles(), workerCyclesBefore);
+}
+
+TEST_P(StreamWorkerTest, WaitForAtLeastOneCycleError) {
+    ASSERT_TRUE(worker.start());
+    stream.error = true;
+    EXPECT_FALSE(worker.waitForAtLeastOneCycle());
+}
+
+INSTANTIATE_TEST_SUITE_P(StreamWorker, StreamWorkerTest, testing::Bool());
diff --git a/audio/effect/all-versions/default/OWNERS b/audio/effect/all-versions/OWNERS
similarity index 67%
copy from audio/effect/all-versions/default/OWNERS
copy to audio/effect/all-versions/OWNERS
index 6fdc97c..24071af 100644
--- a/audio/effect/all-versions/default/OWNERS
+++ b/audio/effect/all-versions/OWNERS
@@ -1,3 +1,2 @@
 elaurent@google.com
-krocard@google.com
 mnaganov@google.com
diff --git a/audio/effect/all-versions/vts/OWNERS b/audio/effect/all-versions/vts/OWNERS
deleted file mode 100644
index 0ea4666..0000000
--- a/audio/effect/all-versions/vts/OWNERS
+++ /dev/null
@@ -1,5 +0,0 @@
-elaurent@google.com
-krocard@google.com
-mnaganov@google.com
-yim@google.com
-zhuoyao@google.com
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
index 5915a53..9d0b9ec 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
@@ -490,6 +490,14 @@
 
         {.config =
                  {
+                         .prop = toInt(VehicleProperty::PARKING_BRAKE_AUTO_APPLY),
+                         .access = VehiclePropertyAccess::READ,
+                         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                 },
+         .initialValue = {.int32Values = {1}}},
+
+        {.config =
+                 {
                          .prop = toInt(VehicleProperty::FUEL_LEVEL_LOW),
                          .access = VehiclePropertyAccess::READ,
                          .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
@@ -1059,7 +1067,7 @@
         {.config =
                  {
                          .prop = toInt(VehicleProperty::SUPPORT_CUSTOMIZE_VENDOR_PERMISSION),
-                         .access = VehiclePropertyAccess::READ_WRITE,
+                         .access = VehiclePropertyAccess::READ,
                          .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
                          .configArray =
                                  {kMixedTypePropertyForTest,
diff --git a/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal
index 94645a4..9ecb2d5 100644
--- a/automotive/vehicle/2.0/types.hal
+++ b/automotive/vehicle/2.0/types.hal
@@ -688,7 +688,7 @@
      * Parking brake state.
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
-     * @access VehiclePropertyAccess:READ_WRITE
+     * @access VehiclePropertyAccess:READ
      */
     PARKING_BRAKE_ON = (
         0x0402
@@ -700,7 +700,7 @@
      * Auto-apply parking brake.
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
-     * @access VehiclePropertyAccess:READ_WRITE
+     * @access VehiclePropertyAccess:READ
      */
     PARKING_BRAKE_AUTO_APPLY = (
         0x0403
diff --git a/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/CommonProps.aidl b/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/CommonProps.aidl
index 4b4e7df..d4433c5 100644
--- a/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/CommonProps.aidl
+++ b/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/CommonProps.aidl
@@ -37,6 +37,5 @@
   int sensorId;
   android.hardware.biometrics.common.SensorStrength sensorStrength = android.hardware.biometrics.common.SensorStrength.CONVENIENCE;
   int maxEnrollmentsPerUser;
-  android.hardware.biometrics.common.HardwareInfo[] hardwareInfo;
-  String softwareInfo;
+  android.hardware.biometrics.common.ComponentInfo[] componentInfo;
 }
diff --git a/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/HardwareInfo.aidl b/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/ComponentInfo.aidl
similarity index 94%
rename from biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/HardwareInfo.aidl
rename to biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/ComponentInfo.aidl
index c5288fd..ad11dda 100644
--- a/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/HardwareInfo.aidl
+++ b/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/ComponentInfo.aidl
@@ -33,8 +33,10 @@
 
 package android.hardware.biometrics.common;
 @VintfStability
-parcelable HardwareInfo {
-  String deviceName;
+parcelable ComponentInfo {
+  String componentId;
   String hardwareVersion;
+  String firmwareVersion;
   String serialNumber;
+  String softwareVersion;
 }
diff --git a/biometrics/common/aidl/android/hardware/biometrics/common/CommonProps.aidl b/biometrics/common/aidl/android/hardware/biometrics/common/CommonProps.aidl
index 7c3d511..2f5af5d 100644
--- a/biometrics/common/aidl/android/hardware/biometrics/common/CommonProps.aidl
+++ b/biometrics/common/aidl/android/hardware/biometrics/common/CommonProps.aidl
@@ -16,7 +16,7 @@
 
 package android.hardware.biometrics.common;
 
-import android.hardware.biometrics.common.HardwareInfo;
+import android.hardware.biometrics.common.ComponentInfo;
 import android.hardware.biometrics.common.SensorStrength;
 
 @VintfStability
@@ -41,16 +41,7 @@
     int maxEnrollmentsPerUser;
 
     /**
-     * A list of hardware information for subsystems that pertain to this biometric sensor.
+     * A list of component information for subsystems that pertain to this biometric sensor.
      */
-    HardwareInfo[] hardwareInfo;
-
-    /**
-     * Software information for subsystems that pertain to this biometric sensor.
-     * This may include information for the matching algorithm, the PAD (Presentation Attack
-     * Detection) algorithm, and any other algorithm(s) used by this biometric sensor.
-     * For example, <algorithm_1_info>;<algorithm_2_info>;<algorithm_3_info>.
-     * The format of each algorithm's info can be <vendor>/<algorithm>/<version>.
-     */
-    String softwareInfo;
+    ComponentInfo[] componentInfo;
 }
diff --git a/biometrics/common/aidl/android/hardware/biometrics/common/HardwareInfo.aidl b/biometrics/common/aidl/android/hardware/biometrics/common/ComponentInfo.aidl
similarity index 62%
rename from biometrics/common/aidl/android/hardware/biometrics/common/HardwareInfo.aidl
rename to biometrics/common/aidl/android/hardware/biometrics/common/ComponentInfo.aidl
index ce9e354..b268eef 100644
--- a/biometrics/common/aidl/android/hardware/biometrics/common/HardwareInfo.aidl
+++ b/biometrics/common/aidl/android/hardware/biometrics/common/ComponentInfo.aidl
@@ -17,19 +17,34 @@
 package android.hardware.biometrics.common;
 
 @VintfStability
-parcelable HardwareInfo {
+parcelable ComponentInfo {
     /**
      * An identifier uniquely identifying a subsystem.
+     * It must not be an empty string.
      */
-    String deviceName;
+    String componentId;
 
     /**
      * The hardware version. For example, <vendor>/<model>/<revision>.
+     * If there's no hardware version for this component, it must be empty.
      */
     String hardwareVersion;
 
     /**
+     * The firmware version.
+     * If there's no firmware version for this component, it must be empty.
+     */
+    String firmwareVersion;
+
+    /**
      * The sensor's serial number.
+     * If there's no serial number for this component, it must be empty.
      */
     String serialNumber;
+
+    /**
+     * The software version. For example, <vendor>/<version>/<revision>.
+     * If there's no software version for this component, it must be empty.
+     */
+    String softwareVersion;
 }
diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/ISessionCallback.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/ISessionCallback.aidl
index d6ebbb6..b0bfa30 100644
--- a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/ISessionCallback.aidl
+++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/ISessionCallback.aidl
@@ -53,4 +53,5 @@
   void onEnrollmentsRemoved(in int[] enrollmentIds);
   void onAuthenticatorIdRetrieved(in long authenticatorId);
   void onAuthenticatorIdInvalidated(in long newAuthenticatorId);
+  void onSessionClosed();
 }
diff --git a/biometrics/face/aidl/android/hardware/biometrics/face/ISessionCallback.aidl b/biometrics/face/aidl/android/hardware/biometrics/face/ISessionCallback.aidl
index 2e3cd95..c1aa3fc 100644
--- a/biometrics/face/aidl/android/hardware/biometrics/face/ISessionCallback.aidl
+++ b/biometrics/face/aidl/android/hardware/biometrics/face/ISessionCallback.aidl
@@ -227,4 +227,10 @@
      *                           current set of enrollments.
      */
     void onAuthenticatorIdInvalidated(in long newAuthenticatorId);
+
+    /**
+     * This method notifes the client that this session has closed.
+     * The client must not make any more calls to this session.
+     */
+    void onSessionClosed();
 }
diff --git a/biometrics/face/aidl/default/Face.cpp b/biometrics/face/aidl/default/Face.cpp
index a4520de..aca3e13 100644
--- a/biometrics/face/aidl/default/Face.cpp
+++ b/biometrics/face/aidl/default/Face.cpp
@@ -24,23 +24,33 @@
 const int kMaxEnrollmentsPerUser = 5;
 const FaceSensorType kSensorType = FaceSensorType::RGB;
 const bool kHalControlsPreview = true;
-const std::string kHwDeviceName = "faceSensor";
+const std::string kHwComponentId = "faceSensor";
 const std::string kHardwareVersion = "vendor/model/revision";
+const std::string kFirmwareVersion = "1.01";
 const std::string kSerialNumber = "00000001";
-const std::string kSoftwareVersion = "vendor1/algorithm1/version;vendor2/algorithm2/version";
+const std::string kSwComponentId = "matchingAlgorithm";
+const std::string kSoftwareVersion = "vendor/version/revision";
 
 ndk::ScopedAStatus Face::getSensorProps(std::vector<SensorProps>* return_val) {
-    common::HardwareInfo hardware_info;
-    hardware_info.deviceName = kHwDeviceName;
-    hardware_info.hardwareVersion = kHardwareVersion;
-    hardware_info.serialNumber = kSerialNumber;
+    common::ComponentInfo hw_component_info;
+    hw_component_info.componentId = kHwComponentId;
+    hw_component_info.hardwareVersion = kHardwareVersion;
+    hw_component_info.firmwareVersion = kFirmwareVersion;
+    hw_component_info.serialNumber = kSerialNumber;
+    hw_component_info.softwareVersion = "";
+
+    common::ComponentInfo sw_component_info;
+    sw_component_info.componentId = kSwComponentId;
+    sw_component_info.hardwareVersion = "";
+    sw_component_info.firmwareVersion = "";
+    sw_component_info.serialNumber = "";
+    sw_component_info.softwareVersion = kSoftwareVersion;
 
     common::CommonProps commonProps;
     commonProps.sensorId = kSensorId;
     commonProps.sensorStrength = kSensorStrength;
     commonProps.maxEnrollmentsPerUser = kMaxEnrollmentsPerUser;
-    commonProps.hardwareInfo = {std::move(hardware_info)};
-    commonProps.softwareInfo = kSoftwareVersion;
+    commonProps.componentInfo = {std::move(hw_component_info), std::move(sw_component_info)};
 
     SensorProps props;
     props.commonProps = std::move(commonProps);
diff --git a/biometrics/face/aidl/vts/VtsHalBiometricsFaceTargetTest.cpp b/biometrics/face/aidl/vts/VtsHalBiometricsFaceTargetTest.cpp
index 4cc8b4a..936fcc6 100644
--- a/biometrics/face/aidl/vts/VtsHalBiometricsFaceTargetTest.cpp
+++ b/biometrics/face/aidl/vts/VtsHalBiometricsFaceTargetTest.cpp
@@ -120,6 +120,8 @@
         return ndk::ScopedAStatus::ok();
     }
 
+    ndk::ScopedAStatus onSessionClosed() override { return ndk::ScopedAStatus::ok(); }
+
   private:
     std::promise<SessionCallbackInvocation> invocation_promise_;
 };
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ISessionCallback.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ISessionCallback.aidl
index 13c2b05..3a97717 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ISessionCallback.aidl
+++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ISessionCallback.aidl
@@ -50,4 +50,5 @@
   void onEnrollmentsRemoved(in int[] enrollmentIds);
   void onAuthenticatorIdRetrieved(in long authenticatorId);
   void onAuthenticatorIdInvalidated(in long newAuthenticatorId);
+  void onSessionClosed();
 }
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISessionCallback.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISessionCallback.aidl
index fde1df7..cf3a271 100644
--- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISessionCallback.aidl
+++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISessionCallback.aidl
@@ -200,4 +200,10 @@
      *                           current set of enrollments.
      */
     void onAuthenticatorIdInvalidated(in long newAuthenticatorId);
+
+    /**
+     * This method notifes the client that this session has closed.
+     * The client must not make any more calls to this session.
+     */
+    void onSessionClosed();
 }
diff --git a/biometrics/fingerprint/aidl/default/Fingerprint.cpp b/biometrics/fingerprint/aidl/default/Fingerprint.cpp
index 79f48fe..fbfa52f 100644
--- a/biometrics/fingerprint/aidl/default/Fingerprint.cpp
+++ b/biometrics/fingerprint/aidl/default/Fingerprint.cpp
@@ -26,10 +26,12 @@
 constexpr int MAX_ENROLLMENTS_PER_USER = 5;
 constexpr FingerprintSensorType SENSOR_TYPE = FingerprintSensorType::REAR;
 constexpr bool SUPPORTS_NAVIGATION_GESTURES = true;
-constexpr char HW_DEVICE_NAME[] = "fingerprintSensor";
+constexpr char HW_COMPONENT_ID[] = "fingerprintSensor";
 constexpr char HW_VERSION[] = "vendor/model/revision";
+constexpr char FW_VERSION[] = "1.01";
 constexpr char SERIAL_NUMBER[] = "00000001";
-constexpr char SW_VERSION[] = "vendor1/algorithm1/version;vendor2/algorithm2/version";
+constexpr char SW_COMPONENT_ID[] = "matchingAlgorithm";
+constexpr char SW_VERSION[] = "vendor/version/revision";
 
 }  // namespace
 
@@ -37,10 +39,13 @@
     : mEngine(std::make_unique<FakeFingerprintEngine>()), mWorker(MAX_WORKER_QUEUE_SIZE) {}
 
 ndk::ScopedAStatus Fingerprint::getSensorProps(std::vector<SensorProps>* out) {
-    std::vector<common::HardwareInfo> hardwareInfos = {{HW_DEVICE_NAME, HW_VERSION, SERIAL_NUMBER}};
+    std::vector<common::ComponentInfo> componentInfo = {
+            {HW_COMPONENT_ID, HW_VERSION, FW_VERSION, SERIAL_NUMBER, "" /* softwareVersion */},
+            {SW_COMPONENT_ID, "" /* hardwareVersion */, "" /* firmwareVersion */,
+             "" /* serialNumber */, SW_VERSION}};
 
     common::CommonProps commonProps = {SENSOR_ID, SENSOR_STRENGTH, MAX_ENROLLMENTS_PER_USER,
-                                       hardwareInfos, SW_VERSION};
+                                       componentInfo};
 
     SensorLocation sensorLocation = {0 /* displayId */, 0 /* sensorLocationX */,
                                      0 /* sensorLocationY */, 0 /* sensorRadius */};
diff --git a/biometrics/fingerprint/aidl/default/Session.cpp b/biometrics/fingerprint/aidl/default/Session.cpp
index c035407..f030f13 100644
--- a/biometrics/fingerprint/aidl/default/Session.cpp
+++ b/biometrics/fingerprint/aidl/default/Session.cpp
@@ -219,11 +219,11 @@
     return ndk::ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus Session::close(int32_t cookie) {
+ndk::ScopedAStatus Session::close(int32_t /*cookie*/) {
     LOG(INFO) << "close";
     CHECK(mCurrentState == SessionState::IDLING) << "Can't close a non-idling session. Crashing.";
     mCurrentState = SessionState::CLOSED;
-    mCb->onStateChanged(cookie, mCurrentState);
+    mCb->onSessionClosed();
     return ndk::ScopedAStatus::ok();
 }
 
diff --git a/biometrics/fingerprint/aidl/default/tests/WorkerThreadTest.cpp b/biometrics/fingerprint/aidl/default/tests/WorkerThreadTest.cpp
index 0d5014bb..c548fe5 100644
--- a/biometrics/fingerprint/aidl/default/tests/WorkerThreadTest.cpp
+++ b/biometrics/fingerprint/aidl/default/tests/WorkerThreadTest.cpp
@@ -32,23 +32,41 @@
 TEST(WorkerThreadTest, ScheduleReturnsTrueWhenQueueHasSpace) {
     WorkerThread worker(1 /*maxQueueSize*/);
     for (int i = 0; i < 100; ++i) {
-        EXPECT_TRUE(worker.schedule(Callable::from([] {})));
-        // Allow enough time for the previous task to be processed.
-        std::this_thread::sleep_for(2ms);
+        std::promise<void> promise;
+        auto future = promise.get_future();
+
+        ASSERT_TRUE(worker.schedule(Callable::from([promise = std::move(promise)]() mutable {
+            // Notify that the task has started.
+            promise.set_value();
+        })));
+
+        auto status = future.wait_for(1s);
+        EXPECT_EQ(status, std::future_status::ready);
     }
 }
 
 TEST(WorkerThreadTest, ScheduleReturnsFalseWhenQueueIsFull) {
     WorkerThread worker(2 /*maxQueueSize*/);
-    // Add a long-running task.
-    worker.schedule(Callable::from([] { std::this_thread::sleep_for(1s); }));
 
-    // Allow enough time for the worker to start working on the previous task.
-    std::this_thread::sleep_for(2ms);
+    std::promise<void> promise;
+    auto future = promise.get_future();
 
+    // Schedule a long-running task.
+    ASSERT_TRUE(worker.schedule(Callable::from([promise = std::move(promise)]() mutable {
+        // Notify that the task has started.
+        promise.set_value();
+        // Block for a "very long" time.
+        std::this_thread::sleep_for(2s);
+    })));
+
+    // Make sure the long-running task began executing.
+    auto status = future.wait_for(1s);
+    ASSERT_EQ(status, std::future_status::ready);
+
+    // The first task is already being worked on, which means the queue must be empty.
     // Fill the worker's queue to the maximum.
-    worker.schedule(Callable::from([] {}));
-    worker.schedule(Callable::from([] {}));
+    ASSERT_TRUE(worker.schedule(Callable::from([] {})));
+    ASSERT_TRUE(worker.schedule(Callable::from([] {})));
 
     EXPECT_FALSE(worker.schedule(Callable::from([] {})));
 }
@@ -71,7 +89,8 @@
     auto future = promise.get_future();
 
     // Schedule a special task to signal when all of the tasks are finished.
-    worker.schedule(Callable::from([&promise] { promise.set_value(); }));
+    worker.schedule(
+            Callable::from([promise = std::move(promise)]() mutable { promise.set_value(); }));
     auto status = future.wait_for(1s);
     ASSERT_EQ(status, std::future_status::ready);
 
@@ -84,23 +103,37 @@
     std::promise<void> promise2;
     auto future1 = promise1.get_future();
     auto future2 = promise2.get_future();
+    std::atomic<bool> value;
 
+    // Local scope for the worker to test its destructor when it goes out of scope.
     {
         WorkerThread worker(2 /*maxQueueSize*/);
-        worker.schedule(Callable::from([&promise1] {
-            promise1.set_value();
-            std::this_thread::sleep_for(200ms);
-        }));
-        worker.schedule(Callable::from([&promise2] { promise2.set_value(); }));
 
-        // Make sure the first task is executing.
-        auto status1 = future1.wait_for(1s);
-        ASSERT_EQ(status1, std::future_status::ready);
+        ASSERT_TRUE(worker.schedule(Callable::from([promise = std::move(promise1)]() mutable {
+            promise.set_value();
+            std::this_thread::sleep_for(200ms);
+        })));
+
+        // The first task should start executing.
+        auto status = future1.wait_for(1s);
+        ASSERT_EQ(status, std::future_status::ready);
+
+        // The second task should schedule successfully.
+        ASSERT_TRUE(
+                worker.schedule(Callable::from([promise = std::move(promise2), &value]() mutable {
+                    // The worker should destruct before it gets a chance to execute this.
+                    value = true;
+                    promise.set_value();
+                })));
     }
 
     // The second task should never execute.
-    auto status2 = future2.wait_for(1s);
-    EXPECT_EQ(status2, std::future_status::timeout);
+    auto status = future2.wait_for(1s);
+    ASSERT_EQ(status, std::future_status::ready);
+    // The future is expected to be ready but contain an exception.
+    // Cannot use ASSERT_THROW because exceptions are disabled in this codebase.
+    // ASSERT_THROW(future2.get(), std::future_error);
+    EXPECT_FALSE(value);
 }
 
 }  // namespace
diff --git a/biometrics/fingerprint/aidl/vts/VtsHalBiometricsFingerprintTargetTest.cpp b/biometrics/fingerprint/aidl/vts/VtsHalBiometricsFingerprintTargetTest.cpp
index 894fdfe..885f703 100644
--- a/biometrics/fingerprint/aidl/vts/VtsHalBiometricsFingerprintTargetTest.cpp
+++ b/biometrics/fingerprint/aidl/vts/VtsHalBiometricsFingerprintTargetTest.cpp
@@ -119,6 +119,8 @@
         return ndk::ScopedAStatus::ok();
     }
 
+    ndk::ScopedAStatus onSessionClosed() override { return ndk::ScopedAStatus::ok(); }
+
   private:
     bool mIsPromiseValid;
     std::vector<Invocation> mInvocations;
diff --git a/bluetooth/audio/2.1/types.hal b/bluetooth/audio/2.1/types.hal
index 5604c38..e0dcc02 100644
--- a/bluetooth/audio/2.1/types.hal
+++ b/bluetooth/audio/2.1/types.hal
@@ -16,13 +16,14 @@
 
 package android.hardware.bluetooth.audio@2.1;
 
-import @2.0::PcmParameters;
-import @2.0::SessionType;
-import @2.0::SampleRate;
-import @2.0::ChannelMode;
 import @2.0::BitsPerSample;
-import @2.0::CodecConfiguration;
+import @2.0::ChannelMode;
 import @2.0::CodecCapabilities;
+import @2.0::CodecConfiguration;
+import @2.0::CodecType;
+import @2.0::PcmParameters;
+import @2.0::SampleRate;
+import @2.0::SessionType;
 
 enum SessionType : @2.0::SessionType {
     /** Used when encoded by Bluetooth Stack and streaming to LE Audio device */
@@ -35,6 +36,10 @@
     LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH,
 };
 
+enum CodecType : @2.0::CodecType {
+    LC3 = 0x20,
+};
+
 enum SampleRate : @2.0::SampleRate {
     RATE_8000 = 0x100,
     RATE_32000 = 0x200,
@@ -49,14 +54,57 @@
     uint32_t dataIntervalUs;
 };
 
-/** Used to configure either a Hardware or Software Encoding session based on session type */
-safe_union AudioConfiguration {
-    PcmParameters pcmConfig;
-    CodecConfiguration codecConfig;
+enum Lc3FrameDuration : uint8_t {
+    DURATION_10000US = 0x00,
+    DURATION_7500US = 0x01,
+};
+
+/**
+ * Used for Hardware Encoding/Decoding LC3 codec parameters.
+ */
+struct Lc3Parameters {
+    /* PCM is Input for encoder, Output for decoder */
+    BitsPerSample pcmBitDepth;
+
+    /* codec-specific parameters */
+    SampleRate samplingFrequency;
+    Lc3FrameDuration frameDuration;
+    /* length in octets of a codec frame */
+    uint32_t octetsPerFrame;
+    /* Number of blocks of codec frames per single SDU (Service Data Unit) */
+    uint8_t blocksPerSdu;
+};
+
+/**
+ * Used to specify the capabilities of the LC3 codecs supported by Hardware Encoding.
+ */
+struct Lc3CodecCapabilities {
+    /* This is bitfield, if bit N is set, HW Offloader supports N+1 channels at the same time.
+     * Example: 0x27 = 0b00100111: One, two, three or six channels supported.*/
+    uint8_t supportedChannelCounts;
+    Lc3Parameters lc3Capabilities;
 };
 
 /** Used to specify the capabilities of the different session types */
 safe_union AudioCapabilities {
     PcmParameters pcmCapabilities;
     CodecCapabilities codecCapabilities;
+    Lc3CodecCapabilities leAudioCapabilities;
 };
+
+/**
+ * Used to configure a LC3 Hardware Encoding session.
+ */
+struct Lc3CodecConfiguration {
+    /* This is also bitfield, specifying how the channels are ordered in the outgoing media packet.
+     * Bit meaning is defined in Bluetooth Assigned Numbers. */
+    uint32_t audioChannelAllocation;
+    Lc3Parameters lc3Config;
+};
+
+/** Used to configure either a Hardware or Software Encoding session based on session type */
+safe_union AudioConfiguration {
+    PcmParameters pcmConfig;
+    CodecConfiguration codecConfig;
+    Lc3CodecConfiguration leAudioCodecConfig;
+};
\ No newline at end of file
diff --git a/broadcastradio/1.0/default/OWNERS b/broadcastradio/1.0/default/OWNERS
index b159083..57e6592 100644
--- a/broadcastradio/1.0/default/OWNERS
+++ b/broadcastradio/1.0/default/OWNERS
@@ -1,4 +1,3 @@
 elaurent@google.com
-krocard@google.com
 mnaganov@google.com
 twasilczyk@google.com
diff --git a/camera/device/3.7/Android.bp b/camera/device/3.7/Android.bp
index 42782f2..163f781 100644
--- a/camera/device/3.7/Android.bp
+++ b/camera/device/3.7/Android.bp
@@ -1,5 +1,14 @@
 // This file is autogenerated by hidl-gen -Landroidbp.
 
+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"],
+}
+
 hidl_interface {
     name: "android.hardware.camera.device@3.7",
     root: "android.hardware",
diff --git a/camera/provider/2.7/Android.bp b/camera/provider/2.7/Android.bp
index 094dd9d..ba59b38 100644
--- a/camera/provider/2.7/Android.bp
+++ b/camera/provider/2.7/Android.bp
@@ -1,5 +1,14 @@
 // This file is autogenerated by hidl-gen -Landroidbp.
 
+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"],
+}
+
 hidl_interface {
     name: "android.hardware.camera.provider@2.7",
     root: "android.hardware",
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index 9e99c48..c656af2 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -359,7 +359,7 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.media.c2</name>
-        <version>1.0-1</version>
+        <version>1.0-2</version>
         <interface>
             <name>IComponentStore</name>
             <regex-instance>default[0-9]*</regex-instance>
diff --git a/contexthub/1.2/IContexthub.hal b/contexthub/1.2/IContexthub.hal
index 4bb9361..04a8cb2 100644
--- a/contexthub/1.2/IContexthub.hal
+++ b/contexthub/1.2/IContexthub.hal
@@ -51,18 +51,6 @@
     registerCallback_1_2(uint32_t hubId, IContexthubCallback cb) generates (Result result);
 
     /**
-     * Send a message to a hub
-     *
-     * @param hubId identifier for hub to send message to
-     * @param msg   message to be sent
-     *
-     * @return result OK if successful, error code otherwise
-     *                BAD_VALUE if parameters are not valid
-     *                TRANSACTION_FAILED if message send failed
-     */
-    sendMessageToHub_1_2(uint32_t hubId, ContextHubMsg msg) generates (Result result);
-
-    /**
      * Notification sent by the framework to indicate that the user
      * has changed a setting.
      *
diff --git a/contexthub/1.2/default/Contexthub.cpp b/contexthub/1.2/default/Contexthub.cpp
index 601eccd..57145fc 100644
--- a/contexthub/1.2/default/Contexthub.cpp
+++ b/contexthub/1.2/default/Contexthub.cpp
@@ -80,12 +80,6 @@
     return Result::BAD_PARAMS;
 }
 
-// We don't expose any nanoapps, therefore all nanoapp-related API calls return with BAD_PARAMS
-Return<Result> Contexthub::sendMessageToHub_1_2(uint32_t /* hubId */,
-                                                const ContextHubMsg& /* msg */) {
-    return Result::BAD_PARAMS;
-}
-
 Return<void> Contexthub::onSettingChanged(SettingV1_1 /*setting*/, SettingValue /*newValue*/) {
     return Void();
 }
diff --git a/contexthub/1.2/default/Contexthub.h b/contexthub/1.2/default/Contexthub.h
index 32b862d..305544d 100644
--- a/contexthub/1.2/default/Contexthub.h
+++ b/contexthub/1.2/default/Contexthub.h
@@ -55,8 +55,6 @@
     Return<Result> registerCallback_1_2(uint32_t hubId,
                                         const sp<V1_2::IContexthubCallback>& cb) override;
 
-    Return<Result> sendMessageToHub_1_2(uint32_t hubId, const ContextHubMsg& msg) override;
-
   private:
     sp<IContextHubCallbackWrapperBase> mCallback;
 };
diff --git a/contexthub/1.2/types.hal b/contexthub/1.2/types.hal
index 5a11efe..5033ce8 100644
--- a/contexthub/1.2/types.hal
+++ b/contexthub/1.2/types.hal
@@ -45,11 +45,8 @@
     @1.0::ContextHubMsg msg_1_0;
 
     /**
-     * The list of Android permissions that the sender of this message has at
-     * the time the message was sent.
-     *
-     * The HAL MUST drop messages to nanoapps if this list of permissions is not
-     * a superset of those of the receiving nanoapp(s).
+     * The list of Android permissions held by the sending nanoapp at the time
+     * the message was sent.
      *
      * The framework MUST drop messages to host apps that don't have a superset
      * of the permissions that the sending nanoapp is using.
diff --git a/contexthub/1.2/vts/functional/VtsHalContexthubV1_2TargetTest.cpp b/contexthub/1.2/vts/functional/VtsHalContexthubV1_2TargetTest.cpp
index c50d43c..3510c23 100644
--- a/contexthub/1.2/vts/functional/VtsHalContexthubV1_2TargetTest.cpp
+++ b/contexthub/1.2/vts/functional/VtsHalContexthubV1_2TargetTest.cpp
@@ -195,39 +195,8 @@
     std::promise<TransactionResult> promise;
 };
 
-// Parameterized fixture that sets the callback to TxnResultCallback
-class ContexthubTxnTest : public ContexthubHidlTest {
-  public:
-    virtual void SetUp() override {
-        ContexthubHidlTest::SetUp();
-        ASSERT_OK(registerCallback_1_2(cb));
-    }
-
-    sp<TxnResultCallback> cb = new TxnResultCallback();
-};
-
-TEST_P(ContexthubTxnTest, TestSendMessageToNonExistentNanoApp) {
-    ContextHubMsg msg;
-    msg.msg_1_0.appName = kNonExistentAppId;
-    msg.msg_1_0.msgType = 1;
-    msg.msg_1_0.msg.resize(4);
-    std::fill(msg.msg_1_0.msg.begin(), msg.msg_1_0.msg.end(), 0);
-
-    ALOGD("Sending message to non-existent nanoapp");
-    Result result = hubApi->sendMessageToHub_1_2(getHubId(), msg);
-    if (result != Result::OK && result != Result::BAD_PARAMS &&
-        result != Result::TRANSACTION_FAILED) {
-        FAIL() << "Got result " << asBaseType(result) << ", expected OK, BAD_PARAMS"
-               << ", or TRANSACTION_FAILED";
-    }
-}
-
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ContexthubHidlTest);
 INSTANTIATE_TEST_SUITE_P(HubIdSpecificTests, ContexthubHidlTest, testing::ValuesIn(kTestParameters),
                          android::hardware::PrintInstanceTupleNameToString<>);
 
-GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ContexthubTxnTest);
-INSTANTIATE_TEST_SUITE_P(HubIdSpecificTests, ContexthubTxnTest, testing::ValuesIn(kTestParameters),
-                         android::hardware::PrintInstanceTupleNameToString<>);
-
 }  // anonymous namespace
diff --git a/gnss/2.1/default/Android.bp b/gnss/2.1/default/Android.bp
index 9a44eb5..609f59e 100644
--- a/gnss/2.1/default/Android.bp
+++ b/gnss/2.1/default/Android.bp
@@ -33,6 +33,7 @@
         "service.cpp",
     ],
     shared_libs: [
+        "libcutils",
         "libhidlbase",
         "libutils",
         "liblog",
diff --git a/gnss/aidl/default/Android.bp b/gnss/aidl/default/Android.bp
index d363a9f..4cc2b6e 100644
--- a/gnss/aidl/default/Android.bp
+++ b/gnss/aidl/default/Android.bp
@@ -40,6 +40,7 @@
     ],
     shared_libs: [
         "libbase",
+        "libcutils",
         "libbinder_ndk",
         "libhidlbase",
         "libutils",
diff --git a/gnss/common/utils/default/Android.bp b/gnss/common/utils/default/Android.bp
index a330c5a..43db873 100644
--- a/gnss/common/utils/default/Android.bp
+++ b/gnss/common/utils/default/Android.bp
@@ -44,6 +44,7 @@
     ],
     export_include_dirs: ["include"],
     shared_libs: [
+        "libcutils",
         "libhidlbase",
         "libutils",
         "android.hardware.gnss@1.0",
diff --git a/gnss/common/utils/default/include/v2_1/GnssTemplate.h b/gnss/common/utils/default/include/v2_1/GnssTemplate.h
index 4d4ec93..79c78c3 100644
--- a/gnss/common/utils/default/include/v2_1/GnssTemplate.h
+++ b/gnss/common/utils/default/include/v2_1/GnssTemplate.h
@@ -28,6 +28,8 @@
 #include <string>
 #include <thread>
 
+#include <cutils/properties.h>
+
 #include "GnssAntennaInfo.h"
 #include "GnssConfiguration.h"
 #include "GnssDebug.h"
@@ -157,9 +159,17 @@
 std::unique_ptr<V2_0::GnssLocation> GnssTemplate<T_IGnss>::getLocationFromHW() {
     char inputBuffer[INPUT_BUFFER_SIZE];
     if (!mHardwareModeChecked) {
-        mGnssFd = open(GNSS_PATH, O_RDWR | O_NONBLOCK);
+        // default using gnss0
+        const char * gnss_dev_path = GNSS_PATH;
+        char devname_value[PROPERTY_VALUE_MAX] = "";
+        if (property_get("debug.location.gnss.devname", devname_value, NULL) > 0) {
+            gnss_dev_path = devname_value;
+            ALOGD("using %s instead of the default %s", gnss_dev_path, GNSS_PATH);
+        }
+
+        mGnssFd = open(gnss_dev_path, O_RDWR | O_NONBLOCK);
         if (mGnssFd == -1) {
-            ALOGW("Failed to open /dev/gnss0 errno: %d", errno);
+            ALOGW("Failed to open %s errno: %d", gnss_dev_path, errno);
         }
         mHardwareModeChecked = true;
     }
diff --git a/graphics/composer/2.2/utils/vts/ReadbackVts.cpp b/graphics/composer/2.2/utils/vts/ReadbackVts.cpp
index 7bb9121..b179f35 100644
--- a/graphics/composer/2.2/utils/vts/ReadbackVts.cpp
+++ b/graphics/composer/2.2/utils/vts/ReadbackVts.cpp
@@ -268,7 +268,7 @@
     mLayerCount = 1;
     mFormat = format;
     mUsage = static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
-                                   BufferUsage::COMPOSER_OVERLAY);
+                                   BufferUsage::COMPOSER_OVERLAY | BufferUsage::GPU_TEXTURE);
 
     mAccessRegion.top = 0;
     mAccessRegion.left = 0;
diff --git a/media/c2/1.2/Android.bp b/media/c2/1.2/Android.bp
new file mode 100644
index 0000000..1094721
--- /dev/null
+++ b/media/c2/1.2/Android.bp
@@ -0,0 +1,31 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.media.c2@1.2",
+    root: "android.hardware",
+    srcs: [
+        "types.hal",
+        "IComponent.hal",
+        "IComponentStore.hal",
+    ],
+    interfaces: [
+        "android.hardware.graphics.bufferqueue@1.0",
+        "android.hardware.graphics.bufferqueue@2.0",
+        "android.hardware.graphics.common@1.0",
+        "android.hardware.graphics.common@1.1",
+        "android.hardware.graphics.common@1.2",
+        "android.hardware.media.bufferpool@2.0",
+        "android.hardware.media.c2@1.0",
+        "android.hardware.media.c2@1.1",
+        "android.hardware.media.omx@1.0",
+        "android.hardware.media@1.0",
+        "android.hidl.base@1.0",
+        "android.hidl.safe_union@1.0",
+    ],
+    gen_java: false,
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.media.swcodec",
+        "test_com.android.media.swcodec",
+    ],
+}
diff --git a/media/c2/1.2/IComponent.hal b/media/c2/1.2/IComponent.hal
new file mode 100644
index 0000000..088d810
--- /dev/null
+++ b/media/c2/1.2/IComponent.hal
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.media.c2@1.2;
+
+import android.hardware.graphics.bufferqueue@2.0::IGraphicBufferProducer;
+import android.hardware.media.c2@1.1::IComponent;
+import android.hardware.media.c2@1.0::Status;
+
+
+/**
+ * Interface for a Codec2 component corresponding to API level 1.2 or below.
+ * Components have two states: stopped and running. The running state has three
+ * sub-states: executing, tripped and error.
+ *
+ * All methods in `IComponent` must not block. If a method call cannot be
+ * completed in a timely manner, it must return `TIMED_OUT` in the return
+ * status.
+ *
+ * @note This is an extension of version 1.1 of `IComponent`. The purpose of the
+ * extension is to add blocking allocation of output buffer from surface.
+ */
+interface IComponent extends @1.1::IComponent {
+    /**
+     * Starts using a surface for output with a synchronization object
+     *
+     * This method must not block.
+     *
+     * @param blockPoolId Id of the `C2BlockPool` to be associated with the
+     *     output surface.
+     * @param surface Output surface.
+     * @param syncObject synchronization object for buffer allocation between
+     *     Framework and Component.
+     * @return status Status of the call, which may be
+     *   - `OK`        - The operation completed successfully.
+     *   - `CANNOT_DO` - The component does not support an output surface.
+     *   - `REFUSED`   - The output surface cannot be accessed.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     */
+    setOutputSurfaceWithSyncObj(
+            uint64_t blockPoolId,
+            @2.0::IGraphicBufferProducer surface,
+            SurfaceSyncObj syncObject
+        ) generates (
+            Status status
+        );
+};
diff --git a/media/c2/1.2/IComponentStore.hal b/media/c2/1.2/IComponentStore.hal
new file mode 100644
index 0000000..c38fc7a
--- /dev/null
+++ b/media/c2/1.2/IComponentStore.hal
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.media.c2@1.2;
+
+import android.hardware.media.bufferpool@2.0::IClientManager;
+import android.hardware.media.c2@1.0::IComponentListener;
+import android.hardware.media.c2@1.1::IComponentStore;
+import android.hardware.media.c2@1.0::Status;
+
+import IComponent;
+
+/**
+ * Entry point for Codec2 HAL.
+ *
+ * All methods in `IComponentStore` must not block. If a method call cannot be
+ * completed in a timely manner, it must return `TIMED_OUT` in the return
+ * status. The only exceptions are getPoolClientManager() and getConfigurable(),
+ * which must always return immediately.
+ *
+ * @note This is an extension of version 1.1 of `IComponentStore`. The purpose
+ * of the extension is to add support for blocking output buffer allocator.
+ */
+interface IComponentStore extends @1.1::IComponentStore {
+    /**
+     * Creates a component by name.
+     *
+     * @param name Name of the component to create. This must match one of the
+     *     names returned by listComponents().
+     * @param listener Callback receiver.
+     * @param pool `IClientManager` object of the BufferPool in the client
+     *     process. This may be null if the client does not own a BufferPool.
+     * @return status Status of the call, which may be
+     *   - `OK`        - The component was created successfully.
+     *   - `NOT_FOUND` - There is no component with the given name.
+     *   - `NO_MEMORY` - Not enough memory to create the component.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     * @return comp The created component if @p status is `OK`.
+     *
+     * @sa IComponentListener.
+     */
+    createComponent_1_2(
+            string name,
+            IComponentListener listener,
+            IClientManager pool
+        ) generates (
+            Status status,
+            IComponent comp
+        );
+};
diff --git a/media/c2/1.2/types.hal b/media/c2/1.2/types.hal
new file mode 100644
index 0000000..096edbd
--- /dev/null
+++ b/media/c2/1.2/types.hal
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.media.c2@1.2;
+
+/**
+ * Surface(BufferQueue/IGBP) synchronization object regarding # of dequeued
+ * output buffers. This keeps # of dequeued buffers from Surface less than
+ * configured max # of dequeued buffers all the time.
+ */
+struct SurfaceSyncObj {
+    /**
+     * ASharedMemory for synchronization data. Layout is below
+     *
+     * |lock(futex)                               4bytes|
+     * |conditional_variable(futex)               4bytes|
+     * |# of max dequeable buffer                 4bytes|
+     * |# of dequeued buffer                      4bytes|
+     * |Status of the surface                     4bytes|
+     *      INIT        = 0, Configuring surface is not finished.
+     *      ACTIVE      = 1, Surface is ready to allocate(dequeue).
+     *      SWITCHING   = 2, Switching to the new surface. It is blocked
+     *                       to allocate(dequeue) a buffer until switching
+     *                       completes.
+     */
+    handle syncMemory;
+
+    // Read-only.
+    // The values which are tied and not changed with respect to Surface
+    // which is currently set up.
+    /** BufferQueue id. */
+    uint64_t bqId;
+    /** Generation id. */
+    uint32_t generationId;
+    /** Consumer usage flags. See +ndk
+      * libnativewindow#AHardwareBuffer_UsageFlags for possible values.
+      */
+    uint64_t consumerUsage;
+};
diff --git a/neuralnetworks/1.0/types.t b/neuralnetworks/1.0/types.t
index d7b26aa..be1ee07 100644
--- a/neuralnetworks/1.0/types.t
+++ b/neuralnetworks/1.0/types.t
@@ -63,361 +63,25 @@
     RELU6 = 3,
 };
 
-/**
- * How an operand is used.
- */
-enum OperandLifeTime : int32_t {
-    /**
-     * The operand is internal to the model. It's created by an operation and
-     * consumed by other operations. It must be an output operand of
-     * exactly one operation.
-     */
-    TEMPORARY_VARIABLE,
+%insert OperandLifeTime
 
-    /**
-     * The operand is an input of the model. It must not be an output
-     * operand of any operation.
-     *
-     * An operand can't be both input and output of a model.
-     */
-    MODEL_INPUT,
+%insert DeviceStatus
 
-    /**
-     * The operand is an output of the model. It must be an output
-     * operand of exactly one operation.
-     *
-     * An operand can't be both input and output of a model.
-     */
-    MODEL_OUTPUT,
+%insert PerformanceInfo
 
-    /**
-     * The operand is a constant found in Model.operandValues. It must
-     * not be an output operand of any operation.
-     */
-    CONSTANT_COPY,
+%insert Capabilities
 
-    /**
-     * The operand is a constant that was specified via a Memory
-     * object. It must not be an output operand of any operation.
-     */
-    CONSTANT_REFERENCE,
+%insert DataLocation
 
-    /**
-     * The operand does not have a value. This is valid only for optional
-     * arguments of operations.
-     */
-    NO_VALUE,
-};
+%insert Operand
 
-/**
- * Status of a device.
- */
-enum DeviceStatus : int32_t {
-    AVAILABLE,
-    BUSY,
-    OFFLINE,
-    UNKNOWN,
-};
+%insert Operation
 
-/**
- * Performance information for the reference workload.
- *
- * Used by a driver to report its performance characteristics.
- */
-struct PerformanceInfo {
-    /**
-     * Ratio of the time taken by the driver to execute the
-     * workload compared to the time the CPU would take for the
-     * same workload. A lower number is better.
-     */
-    float execTime;
+%insert Model
 
-    /**
-     * Ratio of the energy used by the driver compared to what
-     * the CPU would use for doing the same workload. A lower number
-     * is better.
-     */
-    float powerUsage;
-};
+%insert RequestArgument
 
-/**
- * The capabilities of a driver.
- */
-struct Capabilities {
-    /**
-     * Driver performance when operating on float32 data.
-     */
-    PerformanceInfo float32Performance;
-
-    /**
-     * Driver performance when operating on asymmetric 8-bit quantized data.
-     */
-    PerformanceInfo quantized8Performance;
-};
-
-/**
- * Describes the location of a data object.
- */
-struct DataLocation {
-    /**
-     * The index of the memory pool where this location is found.
-     */
-    uint32_t poolIndex;
-
-    /**
-     * Offset in bytes from the start of the pool.
-     */
-    uint32_t offset;
-
-    /**
-     * The length of the data in bytes.
-     */
-    uint32_t length;
-};
-
-/**
- * Describes one operand of the model's graph.
- */
-struct Operand {
-    /**
-     * Data type of the operand.
-     */
-    OperandType type;
-
-    /**
-     * Dimensions of the operand.
-     *
-     * For a scalar operand, dimensions.size() must be 0.
-     *
-     * For a tensor operand, dimensions.size() must be at least 1;
-     * however, any of the dimensions may be unspecified.
-     *
-     * A tensor operand with all dimensions specified has "fully
-     * specified" dimensions. Whenever possible (i.e., whenever the
-     * dimensions are known at model construction time), a tensor
-     * operand should have (but is not required to have) fully
-     * specified dimensions, in order to enable the best possible
-     * performance.
-     *
-     * If a tensor operand's dimensions are not fully specified, the
-     * dimensions of the operand are deduced from the operand
-     * dimensions and values of the operation for which that operand
-     * is an output.
-     *
-     * In the following situations, a tensor operand's dimensions must
-     * be fully specified:
-     *
-     *     . The operand has lifetime CONSTANT_COPY or
-     *       CONSTANT_REFERENCE.
-     *
-     *     . The operand has lifetime MODEL_INPUT or MODEL_OUTPUT. Fully
-     *       specified dimensions must either be present in the
-     *       Operand or they must be provided in the corresponding
-     *       RequestArgument.
-     *       EXCEPTION: If the input or output is optional and omitted
-     *       (by setting the hasNoValue field of the corresponding
-     *       RequestArgument to true) then it need not have fully
-     *       specified dimensions.
-     *
-     * A tensor operand with some number of unspecified dimensions is
-     * represented by setting each unspecified dimension to 0.
-     */
-    vec<uint32_t> dimensions;
-
-    /**
-     * The number of times this operand appears as an operation input.
-     *
-     * (For example, if this operand appears once in one operation's
-     * input list, and three times in another operation's input list,
-     * then numberOfConsumers = 4.)
-     */
-    uint32_t numberOfConsumers;
-
-    /**
-     * Quantized scale of the operand.
-     *
-     * Only applicable if the operand is of type TENSOR_QUANT8_ASYMM or
-     * TENSOR_INT32.
-     */
-    float scale;
-
-    /**
-     * Quantized zero-point offset of the operand.
-     *
-     * Only applicable if the operand is of type TENSOR_QUANT8_ASYMM.
-     */
-    int32_t zeroPoint;
-
-    /**
-     * How the operand is used.
-     */
-    OperandLifeTime lifetime;
-
-    /**
-     * Where to find the data for this operand.
-     * If the lifetime is TEMPORARY_VARIABLE, MODEL_INPUT, MODEL_OUTPUT, or
-     * NO_VALUE:
-     * - All the fields must be 0.
-     * If the lifetime is CONSTANT_COPY:
-     * - location.poolIndex is 0.
-     * - location.offset is the offset in bytes into Model.operandValues.
-     * - location.length is set.
-     * If the lifetime is CONSTANT_REFERENCE:
-     * - location.poolIndex is set.
-     * - location.offset is the offset in bytes into the specified pool.
-     * - location.length is set.
-     */
-    DataLocation location;
-};
-
-/**
- * Describes one operation of the model's graph.
- */
-struct Operation {
-    /**
-     * The operation type.
-     */
-    OperationType type;
-
-    /**
-     * Describes the table that contains the indexes of the inputs of the
-     * operation. The offset is the index in the operandIndexes table.
-     */
-    vec<uint32_t> inputs;
-
-    /**
-     * Describes the table that contains the indexes of the outputs of the
-     * operation. The offset is the index in the operandIndexes table.
-     */
-    vec<uint32_t> outputs;
-};
-
-/**
- * A Neural Network Model.
- *
- * This includes not only the execution graph, but also constant data such as
- * weights or scalars added at construction time. The only information that
- * might not be known is the shape of the input tensors.
- */
-struct Model {
-    /**
-     * All operands included in the model.
-     */
-    vec<Operand> operands;
-
-    /**
-     * All operations included in the model.
-     *
-     * The operations are sorted into execution order. Every operand
-     * with lifetime MODEL_OUTPUT or TEMPORARY_VARIABLE must be
-     * written before it is read.
-     */
-    vec<Operation> operations;
-
-    /**
-     * Input indexes of the model. There must be at least one.
-     *
-     * Each value corresponds to the index of the operand in "operands".
-     */
-    vec<uint32_t> inputIndexes;
-
-    /**
-     * Output indexes of the model. There must be at least one.
-     *
-     * Each value corresponds to the index of the operand in "operands".
-     */
-    vec<uint32_t> outputIndexes;
-
-    /**
-     * A byte buffer containing operand data that were copied into the model.
-     *
-     * An operand's value must be located here if and only if Operand::lifetime
-     * equals OperandLifeTime::CONSTANT_COPY.
-     */
-    vec<uint8_t> operandValues;
-
-    /**
-     * A collection of shared memory pools containing operand values.
-     *
-     * An operand's value must be located here if and only if Operand::lifetime
-     * equals OperandLifeTime::CONSTANT_REFERENCE.
-     */
-    vec<memory> pools;
-};
-
-/**
- * Metadata information specifying the location of the input or output data and
- * any updates to the input or output operand.
- */
-struct RequestArgument {
-    /**
-     * If true, the argument does not have a value. This can be used for
-     * operations that take optional arguments. If true, the fields of location
-     * are set to 0 and the dimensions vector is left empty.
-     */
-    bool hasNoValue;
-
-    /**
-     * The location within one of the memory pools passed in the Request.
-     */
-    DataLocation location;
-
-    /**
-     * Updated dimension information.
-     *
-     * If dimensions.size() > 0, dimension information was provided
-     * along with the argument. This can be the case for models that
-     * accept inputs of varying size. This can't change the rank, just
-     * the value of the dimensions that were unspecified in the
-     * model. If dimensions.size() > 0, then all dimensions must be
-     * specified here; and any dimension that was specified in the
-     * model must have the same value here.
-     *
-     * If the dimensions in the model are not fully specified, then
-     * they must be fully specified here, unless hasNoValue is set to
-     * true. If the dimensions in the model are fully specified, then
-     * either dimensions.size() may be 0, or the dimensions in the
-     * model must be identical to the dimensions here.
-     */
-    vec<uint32_t> dimensions;
-};
-
-/**
- * Inputs to be sent to and outputs to be retrieved from a prepared model.
- *
- * A Request serves two primary tasks:
- * 1) Provides the input and output data to be used when executing the model.
- * 2) Specifies any updates to the input operand metadata that were left
- *    unspecified at model preparation time.
- *
- * An output must not overlap with any other output, with an input, or
- * with an operand of lifetime CONSTANT_REFERENCE.
- */
-struct Request {
-    /**
-     * Input data and information to be used in the execution of a prepared
-     * model.
-     *
-     * The index of the input corresponds to the index in Model.inputIndexes.
-     *   E.g., input[i] corresponds to Model.inputIndexes[i].
-     */
-    vec<RequestArgument> inputs;
-
-    /**
-     * Output data and information to be used in the execution of a prepared
-     * model.
-     *
-     * The index of the output corresponds to the index in Model.outputIndexes.
-     *   E.g., output[i] corresponds to Model.outputIndexes[i].
-     */
-    vec<RequestArgument> outputs;
-
-    /**
-     * A collection of shared memory pools containing operand data for both the
-     * inputs and the outputs to a model.
-     */
-    vec<memory> pools;
-};
+%insert Request
 
 /**
  * Return status of a function.
diff --git a/neuralnetworks/1.1/types.t b/neuralnetworks/1.1/types.t
index 75ac2e7..8c22b30 100644
--- a/neuralnetworks/1.1/types.t
+++ b/neuralnetworks/1.1/types.t
@@ -31,128 +31,10 @@
 %insert Operation_1.1
 };
 
-/**
- * The capabilities of a driver.
- */
-struct Capabilities {
-    /**
-     * Driver performance when operating on float32 data.
-     */
-    PerformanceInfo float32Performance;
+%insert Capabilities
 
-    /**
-     * Driver performance when operating on asymmetric 8-bit quantized data.
-     */
-    PerformanceInfo quantized8Performance;
+%insert Operation
 
-    /**
-     * Driver performance when operating on float32 data but performing
-     * calculations with range and/or precision as low as that of the IEEE
-     * 754 16-bit floating-point format.
-     */
-    PerformanceInfo relaxedFloat32toFloat16Performance;
-};
+%insert Model
 
-/**
- * Describes one operation of the model's graph.
- */
-struct Operation {
-    /**
-     * The operation type.
-     */
-    OperationType type;
-
-    /**
-     * Describes the table that contains the indexes of the inputs of the
-     * operation. The offset is the index in the operandIndexes table.
-     */
-    vec<uint32_t> inputs;
-
-    /**
-     * Describes the table that contains the indexes of the outputs of the
-     * operation. The offset is the index in the operandIndexes table.
-     */
-    vec<uint32_t> outputs;
-};
-
-/**
- * A Neural Network Model.
- *
- * This includes not only the execution graph, but also constant data such as
- * weights or scalars added at construction time. The only information that
- * may not be known is the shape of the input tensors.
- */
-struct Model {
-    /**
-     * All operands included in the model.
-     */
-    vec<Operand> operands;
-
-    /**
-     * All operations included in the model.
-     *
-     * The operations are sorted into execution order. Every operand
-     * with lifetime MODEL_OUTPUT or TEMPORARY_VARIABLE must be
-     * written before it is read.
-     */
-    vec<Operation> operations;
-
-    /**
-     * Input indexes of the model. There must be at least one.
-     *
-     * Each value corresponds to the index of the operand in "operands".
-     */
-    vec<uint32_t> inputIndexes;
-
-    /**
-     * Output indexes of the model. There must be at least one.
-     *
-     * Each value corresponds to the index of the operand in "operands".
-     */
-    vec<uint32_t> outputIndexes;
-
-    /**
-     * A byte buffer containing operand data that were copied into the model.
-     *
-     * An operand's value must be located here if and only if Operand::lifetime
-     * equals OperandLifeTime::CONSTANT_COPY.
-     */
-    vec<uint8_t> operandValues;
-
-    /**
-     * A collection of shared memory pools containing operand values.
-     *
-     * An operand's value must be located here if and only if Operand::lifetime
-     * equals OperandLifeTime::CONSTANT_REFERENCE.
-     */
-    vec<memory> pools;
-
-    /**
-     * 'true' indicates TENSOR_FLOAT32 may be calculated with range and/or
-     * precision as low as that of the IEEE 754 16-bit floating-point format.
-     * 'false' indicates TENSOR_FLOAT32 must be calculated using at least the
-     * range and precision of the IEEE 754 32-bit floating-point format.
-     */
-    bool relaxComputationFloat32toFloat16;
-};
-
-/**
- * Execution preferences.
- */
-enum ExecutionPreference : int32_t {
-    /**
-     * Prefer executing in a way that minimizes battery drain.
-     * This is desirable for compilations that will be executed often.
-     */
-    LOW_POWER = 0,
-    /**
-     * Prefer returning a single answer as fast as possible, even if this causes
-     * more power consumption.
-     */
-    FAST_SINGLE_ANSWER = 1,
-    /**
-     * Prefer maximizing the throughput of successive frames, for example when
-     * processing successive frames coming from the camera.
-     */
-    SUSTAINED_SPEED = 2,
-};
+%insert ExecutionPreference
diff --git a/neuralnetworks/1.2/types.t b/neuralnetworks/1.2/types.t
index 4c9fd02..b490f7f 100644
--- a/neuralnetworks/1.2/types.t
+++ b/neuralnetworks/1.2/types.t
@@ -97,379 +97,23 @@
     BASE_MAX        = 0xFFFF,
 };
 
-/**
- * Device types.
- *
- * The type of NNAPI device.
- */
-enum DeviceType : int32_t {
-    // Leaving 0 unused as it means unknown type in NDK NNAPI. There is no
-    // HAL equivalent of unknown type and a 1.2 HAL implementation must belong
-    // to one of the categories below.
-    /** The device does not fall into any category below. */
-    OTHER = 1,
-    /** The device runs NNAPI models on single or multi-core CPU. */
-    CPU = 2,
-    /** The device can run NNAPI models and also accelerate graphics APIs such
-     * as OpenGL ES and Vulkan. */
-    GPU = 3,
-    /** Dedicated accelerator for Machine Learning workloads. */
-    ACCELERATOR = 4,
-};
+%insert DeviceType
 
-/**
- * The capabilities of a driver.
- *
- * Performance of an operation comes from the type of its first operand.
- * This represents performance for non extension operand types.
- */
-struct Capabilities {
-    /**
-     * Driver performance when operating on float32 data but performing
-     * calculations with range and/or precision as low as that of the IEEE
-     * 754 16-bit floating-point format.
-     */
-    PerformanceInfo relaxedFloat32toFloat16PerformanceScalar;
-    PerformanceInfo relaxedFloat32toFloat16PerformanceTensor;
+%insert Capabilities
 
-    /**
-     * Driver performance when operating on a particular data type.
-     * In the case of float32 data, this is used when the calculations
-     * are not relaxed.
-     */
-    struct OperandPerformance {
-        OperandType type;
-        PerformanceInfo info;
-    };
+%insert Operation
 
-    /**
-     * Performance by operand type. Must be sorted by OperandType.
-     * If a particular OperandType is not present in operandPerformance,
-     * its performance is treated as { .execTime = FLT_MAX, .powerUsage = FLT_MAX }.
-     */
-    vec<OperandPerformance> operandPerformance;
-};
+%insert SymmPerChannelQuantParams
 
-/**
- * Describes one operation of the model's graph.
- */
-struct Operation {
-    /**
-     * The operation type.
-     *
-     * Besides the values listed in {@link OperationType}, any value above
-     * {@link OperationTypeRange::BASE_MAX} is possible and should be interpreted
-     * as an extension type according to {@link Model::extensionNameToPrefix}.
-     */
-    OperationType type;
+%insert Operand
 
-    /**
-     * Describes the table that contains the indexes of the inputs of the
-     * operation. The offset is the index in the operandIndexes table.
-     */
-    vec<uint32_t> inputs;
+%insert Model
 
-    /**
-     * Describes the table that contains the indexes of the outputs of the
-     * operation. The offset is the index in the operandIndexes table.
-     */
-    vec<uint32_t> outputs;
-};
+%insert OutputShape
 
-/**
- * Parameters for TENSOR_QUANT8_SYMM_PER_CHANNEL operand.
- */
-struct SymmPerChannelQuantParams {
-    /** Array of scaling values for each channel. Each value must be greater than zero. */
-    vec<float> scales;
-    /** Index of the channel dimension */
-    uint32_t channelDim;
-};
+%insert MeasureTiming
 
-/**
- * Describes one operand of the model's graph.
- */
-struct Operand {
-    /**
-     * The data type.
-     *
-     * Besides the values listed in {@link OperandType}, any value above
-     * {@link OperandTypeRange::BASE_MAX} is possible and should be interpreted
-     * as an extension type according to {@link Model::extensionNameToPrefix}.
-     */
-    OperandType type;
-
-    /**
-     * Dimensions of the operand.
-     *
-     * For a scalar operand, dimensions.size() must be 0.
-     *
-     * A tensor operand with all dimensions specified has "fully
-     * specified" dimensions. Whenever possible (i.e., whenever the
-     * dimensions are known at model construction time), a tensor
-     * operand should have (but is not required to have) fully
-     * specified dimensions, in order to enable the best possible
-     * performance.
-     *
-     * If a tensor operand's dimensions are not fully specified, the
-     * dimensions of the operand are deduced from the operand
-     * dimensions and values of the operation for which that operand
-     * is an output.
-     *
-     * In the following situations, a tensor operand's dimensions must
-     * be fully specified:
-     *
-     *     . The operand has lifetime CONSTANT_COPY or
-     *       CONSTANT_REFERENCE.
-     *
-     *     . The operand has lifetime MODEL_INPUT. Fully
-     *       specified dimensions must either be present in the
-     *       Operand or they must be provided in the corresponding
-     *       RequestArgument.
-     *       EXCEPTION: If the input is optional and omitted
-     *       (by setting the hasNoValue field of the corresponding
-     *       RequestArgument to true) then it need not have fully
-     *       specified dimensions.
-     *
-     * A tensor operand with some number of unspecified dimensions is
-     * represented by setting each unspecified dimension to 0.
-     *
-     * A tensor operand with unspecified rank is represented by providing
-     * an empty dimensions vector.
-     */
-    vec<uint32_t> dimensions;
-
-    /**
-     * The number of times this operand appears as an operation input.
-     *
-     * (For example, if this operand appears once in one operation's
-     * input list, and three times in another operation's input list,
-     * then numberOfConsumers = 4.)
-     */
-    uint32_t numberOfConsumers;
-
-    /**
-     * Quantized scale of the operand.
-     *
-     * Must be 0 when not applicable to an operand type.
-     *
-     * See {@link OperandType}.
-     */
-    float scale;
-
-    /**
-     * Quantized zero-point offset of the operand.
-     *
-     * Must be 0 when not applicable to an operand type.
-     *
-     * See {@link OperandType}.
-     */
-    int32_t zeroPoint;
-
-    /**
-     * How the operand is used.
-     */
-    OperandLifeTime lifetime;
-
-    /**
-     * Where to find the data for this operand.
-     * If the lifetime is TEMPORARY_VARIABLE, MODEL_INPUT, MODEL_OUTPUT, or
-     * NO_VALUE:
-     * - All the fields must be 0.
-     * If the lifetime is CONSTANT_COPY:
-     * - location.poolIndex is 0.
-     * - location.offset is the offset in bytes into Model.operandValues.
-     * - location.length is set.
-     * If the lifetime is CONSTANT_REFERENCE:
-     * - location.poolIndex is set.
-     * - location.offset is the offset in bytes into the specified pool.
-     * - location.length is set.
-     */
-    DataLocation location;
-
-    /**
-     * Additional parameters specific to a particular operand type.
-     */
-    safe_union ExtraParams {
-        /**
-         * No additional parameters.
-         */
-        Monostate none;
-
-        /**
-         * Symmetric per-channel quantization parameters.
-         *
-         * Only applicable to operands of type TENSOR_QUANT8_SYMM_PER_CHANNEL.
-         */
-        SymmPerChannelQuantParams channelQuant;
-
-        /**
-         * Extension operand parameters.
-         *
-         * The framework treats this as an opaque data blob.
-         * The format is up to individual extensions.
-         */
-        vec<uint8_t> extension;
-    } extraParams;
-};
-
-/**
- * A Neural Network Model.
- *
- * This includes not only the execution graph, but also constant data such as
- * weights or scalars added at construction time. The only information that
- * may not be known is the shape of the input tensors.
- */
-struct Model {
-    /**
-     * All operands included in the model.
-     */
-    vec<Operand> operands;
-
-    /**
-     * All operations included in the model.
-     *
-     * The operations are sorted into execution order. Every operand
-     * with lifetime MODEL_OUTPUT or TEMPORARY_VARIABLE must be
-     * written before it is read.
-     */
-    vec<Operation> operations;
-
-    /**
-     * Input indexes of the model. There must be at least one.
-     *
-     * Each value corresponds to the index of the operand in "operands".
-     */
-    vec<uint32_t> inputIndexes;
-
-    /**
-     * Output indexes of the model. There must be at least one.
-     *
-     * Each value corresponds to the index of the operand in "operands".
-     */
-    vec<uint32_t> outputIndexes;
-
-    /**
-     * A byte buffer containing operand data that were copied into the model.
-     *
-     * An operand's value must be located here if and only if Operand::lifetime
-     * equals OperandLifeTime::CONSTANT_COPY.
-     */
-    vec<uint8_t> operandValues;
-
-    /**
-     * A collection of shared memory pools containing operand values.
-     *
-     * An operand's value must be located here if and only if Operand::lifetime
-     * equals OperandLifeTime::CONSTANT_REFERENCE.
-     */
-    vec<memory> pools;
-
-    /**
-     * 'true' indicates TENSOR_FLOAT32 may be calculated with range and/or
-     * precision as low as that of the IEEE 754 16-bit floating-point format.
-     * 'false' indicates TENSOR_FLOAT32 must be calculated using at least the
-     * range and precision of the IEEE 754 32-bit floating-point format.
-     */
-    bool relaxComputationFloat32toFloat16;
-
-    /**
-     * The mapping between extension names and prefixes of operand and
-     * operation type values.
-     *
-     * An operand or operation whose numeric type value is above
-     * {@link OperandTypeRange::BASE_MAX} or
-     * {@link OperationTypeRange::BASE_MAX} respectively should be interpreted
-     * as an extension operand. The low
-     * {@link Model::ExtensionTypeEncoding::LOW_BITS_TYPE} bits of the value
-     * correspond to the type ID within the extension and the high
-     * {@link Model::ExtensionTypeEncoding::HIGH_BITS_PREFIX} bits encode
-     * the "prefix", which maps uniquely to the extension name.
-     *
-     * For example, if a model contains an operation whose value is
-     * 0xAAAABBBB and extensionNameToPrefix contains an entry with
-     * prefix=0xAAAA and name="vendor.test.test_extension", then
-     * the operation should be interpreted as the operation 0xBBBB
-     * of the extension named vendor.test.test_extension.
-     *
-     * This is a one-to-one correspondence. That is, there must be at most one
-     * prefix corresponding to each extension name and at most one extension
-     * name corresponding to each prefix.
-     */
-    vec<ExtensionNameAndPrefix> extensionNameToPrefix;
-
-    /**
-     * A correspondence between an extension name and a prefix of operand and
-     * operation type values.
-     */
-    struct ExtensionNameAndPrefix {
-        /**
-         * The extension name.
-         *
-         * See {@link Extension::name} for the format specification.
-         */
-        string name;
-
-        /**
-         * The unique extension identifier within the model.
-         *
-         * See {@link Model::extensionNameToPrefix}.
-         */
-        uint16_t prefix;
-    };
-
-    /**
-     * Numeric values of extension operand and operation types have the
-     * following structure:
-     * - 16 high bits represent the "prefix", which corresponds uniquely to the
-     *   extension name.
-     * - 16 low bits represent the type ID within the extension.
-     */
-    enum ExtensionTypeEncoding : uint8_t {
-        HIGH_BITS_PREFIX = 16,
-        LOW_BITS_TYPE = 16,
-    };
-};
-
-/**
- * Describes the shape information of an output operand after execution.
- */
-struct OutputShape {
-    /**
-     * Dimensions of the operand.
-     */
-    vec<uint32_t> dimensions;
-
-    /**
-     * Whether the provided buffer size is sufficient for the output.
-     */
-    bool isSufficient;
-};
-
-/**
- * Specifies whether or not to measure timing information during execution.
- */
-enum MeasureTiming : int32_t {
-    NO = 0,
-    YES = 1,
-};
-
-/**
-
- * Timing information measured during execution. Each time is a duration from
- * the beginning of some task to the end of that task, including time when that
- * task is not active (for example, preempted by some other task, or
- * waiting for some resource to become available).
- *
- * Times are measured in microseconds.
- * When a time is not available, it must be reported as UINT64_MAX.
- */
-struct Timing {
-    /** Execution time on device (not driver, which runs on host processor). */
-    uint64_t timeOnDevice;
-    /** Execution time in driver (including time on device). */
-    uint64_t timeInDriver;
-};
+%insert Timing
 
 /**
  * FmqRequestDatum is a single element of a serialized representation of an
@@ -683,46 +327,4 @@
     Timing executionTiming;
 };
 
-/**
- * Information about an extension.
- */
-struct Extension {
-    /**
-     * The extension name.
-     *
-     * The name must consist of lowercase latin letters, numbers, periods, and
-     * underscore signs. The name must contain at least one period.
-     *
-     * The name must start with the reverse domain name of the vendor.
-     *
-     * Example: com.google.test_extension
-     */
-    string name;
-
-    /**
-     * Information about an extension operand type.
-     */
-    struct OperandTypeInformation {
-        /**
-         * The extension operand type.
-         */
-        uint16_t type;
-
-        /**
-         * Indicates whether the extension operand type represents a tensor or
-         * a scalar.
-         */
-        bool isTensor;
-
-        /**
-         * The byte size of the operand (if scalar) or of a single element (if
-         * tensor).
-         */
-        uint32_t byteSize;
-    };
-
-    /**
-     * Information about operand types defined by the extension.
-     */
-    vec<OperandTypeInformation> operandTypes;
-};
+%insert Extension
diff --git a/neuralnetworks/1.3/types.t b/neuralnetworks/1.3/types.t
index 9f69c9e..96d1a1b 100644
--- a/neuralnetworks/1.3/types.t
+++ b/neuralnetworks/1.3/types.t
@@ -90,459 +90,25 @@
     BASE_MAX        = 0xFFFF,
 };
 
-/**
- * Priority given to a prepared model for execution.
- */
-enum Priority : int32_t {
-    LOW,
-    MEDIUM,
-    HIGH,
-};
+%insert Priority
 
-/**
- * The capabilities of a driver.
- *
- * This represents performance of non-extension operations.
- *
- * Performance of an operation other than {@link OperationType::IF} and
- * {@link OperationType::WHILE} comes from the type of its first operand.
- */
-struct Capabilities {
-    /**
-     * Driver performance when operating on float32 data but performing
-     * calculations with range and/or precision as low as that of the IEEE
-     * 754 16-bit floating-point format.
-     */
-    PerformanceInfo relaxedFloat32toFloat16PerformanceScalar;
-    PerformanceInfo relaxedFloat32toFloat16PerformanceTensor;
+%insert Capabilities
 
-    /**
-     * Driver performance when operating on a particular data type.
-     * In the case of float32 data, this is used when the calculations
-     * are not relaxed.
-     */
-    struct OperandPerformance {
-        OperandType type;
-        PerformanceInfo info;
-    };
+%insert Operation
 
-    /**
-     * Performance by operand type. Must be sorted by OperandType.
-     *
-     * If a particular {@link OperandType} is not present in operandPerformance,
-     * its performance is treated as
-     * { .execTime = FLT_MAX, .powerUsage = FLT_MAX }.
-     *
-     * Performance does not apply to {@link OperandType::SUBGRAPH}, and a driver
-     * must not report operand performance for {@link OperandType::SUBGRAPH}.
-     */
-    vec<OperandPerformance> operandPerformance;
+%insert OperandLifeTime
 
-    /**
-     * Performance of an {@link OperationType::IF} operation is the sum of
-     * {@link Capabilities::ifPerformance} and the mean of performance for the
-     * two branch subgraphs, where performance for a subgraph is the sum of the
-     * performance of all operations within the subgraph.
-     */
-    PerformanceInfo ifPerformance;
+%insert Operand
 
-    /**
-     * Performance of a {@link OperationType::WHILE} operation is the sum of
-     * {@link Capabilities::whilePerformance}, performance for the condition
-     * subgraph and performance for the body subgraph, where performance for a
-     * subgraph is the sum of the performance of all operations within the
-     * subgraph.
-     */
-    PerformanceInfo whilePerformance;
-};
+%insert Model
 
-/**
- * Describes one operation of the model's graph.
- */
-struct Operation {
-    /**
-     * The operation type.
-     *
-     * Besides the values listed in {@link OperationType}, any value above
-     * {@link OperationTypeRange::BASE_MAX} is possible and should be interpreted
-     * as an extension type according to {@link Model::extensionNameToPrefix}.
-     */
-    OperationType type;
+%insert Subgraph
 
-    /**
-     * Describes the table that contains the indexes of the inputs of the
-     * operation. The offset is the index in the operandIndexes table.
-     */
-    vec<uint32_t> inputs;
+%insert BufferDesc
 
-    /**
-     * Describes the table that contains the indexes of the outputs of the
-     * operation. The offset is the index in the operandIndexes table.
-     */
-    vec<uint32_t> outputs;
-};
+%insert BufferRole
 
-/**
- * How an operand is used.
- */
-enum OperandLifeTime : int32_t {
-    /**
-     * The operand is internal to the model. It's created by an operation and
-     * consumed by other operations. It must be an output operand of
-     * exactly one operation.
-     */
-    TEMPORARY_VARIABLE,
-
-    /**
-     * The operand is an input of a subgraph. It must not be an output
-     * operand of any operation.
-     *
-     * An operand can't be both input and output of a subgraph.
-     */
-    SUBGRAPH_INPUT,
-
-    /**
-     * The operand is an output of a subgraph. It must be an output
-     * operand of exactly one operation.
-     *
-     * An operand can't be both input and output of a subgraph.
-     */
-    SUBGRAPH_OUTPUT,
-
-    /**
-     * The operand is a constant found in Model.operandValues. It must
-     * not be an output operand of any operation.
-     */
-    CONSTANT_COPY,
-
-    /**
-     * The operand is a constant that was specified via a Memory
-     * object. It must not be an output operand of any operation.
-     */
-    CONSTANT_REFERENCE,
-
-    /**
-     * The operand does not have a value. This is valid only for optional
-     * arguments of operations.
-     */
-    NO_VALUE,
-
-    /**
-     * The operand is a reference to a subgraph. It must be an input to one
-     * or more {@link OperationType::IF} or {@link OperationType::WHILE}
-     * operations.
-     */
-    SUBGRAPH,
-};
-
-/**
- * Describes one operand of the model's graph.
- */
-struct Operand {
-    /**
-     * The data type.
-     *
-     * Besides the values listed in {@link OperandType}, any value above
-     * {@link OperandTypeRange::BASE_MAX} is possible and should be interpreted
-     * as an extension type according to {@link Model::extensionNameToPrefix}.
-     */
-    OperandType type;
-
-    /**
-     * Dimensions of the operand.
-     *
-     * For a scalar operand, dimensions.size() must be 0.
-     *
-     * A tensor operand with all dimensions specified has "fully
-     * specified" dimensions. Whenever possible (i.e., whenever the
-     * dimensions are known at model construction time), a tensor
-     * operand should have (but is not required to have) fully
-     * specified dimensions, in order to enable the best possible
-     * performance.
-     *
-     * If a tensor operand's dimensions are not fully specified, the
-     * dimensions of the operand are deduced from the operand
-     * dimensions and values of the operation for which that operand
-     * is an output or from the corresponding {@link OperationType::IF} or
-     * {@link OperationType::WHILE} operation input operand dimensions in the
-     * case of referenced subgraph input operands.
-     *
-     * In the following situations, a tensor operand's dimensions must
-     * be fully specified:
-     *
-     *     . The operand has lifetime CONSTANT_COPY or
-     *       CONSTANT_REFERENCE.
-     *
-     *     . The operand has lifetime SUBGRAPH_INPUT and belongs to the main
-     *       subgraph. Fully specified dimensions must either be present in the
-     *       Operand or they must be provided in the corresponding
-     *       RequestArgument.
-     *       EXCEPTION: If the input is optional and omitted
-     *       (by setting the hasNoValue field of the corresponding
-     *       RequestArgument to true) then it need not have fully
-     *       specified dimensions.
-     *
-     * A tensor operand with some number of unspecified dimensions is
-     * represented by setting each unspecified dimension to 0.
-     *
-     * A tensor operand with unspecified rank is represented by providing
-     * an empty dimensions vector.
-     */
-    vec<uint32_t> dimensions;
-
-    /**
-     * The number of times this operand appears as an operation input.
-     *
-     * (For example, if this operand appears once in one operation's
-     * input list, and three times in another operation's input list,
-     * then numberOfConsumers = 4.)
-     */
-    uint32_t numberOfConsumers;
-
-    /**
-     * Quantized scale of the operand.
-     *
-     * Must be 0 when not applicable to an operand type.
-     *
-     * See {@link OperandType}.
-     */
-    float scale;
-
-    /**
-     * Quantized zero-point offset of the operand.
-     *
-     * Must be 0 when not applicable to an operand type.
-     *
-     * See {@link OperandType}.
-     */
-    int32_t zeroPoint;
-
-    /**
-     * How the operand is used.
-     */
-    OperandLifeTime lifetime;
-
-    /**
-     * Where to find the data for this operand.
-     * If the lifetime is TEMPORARY_VARIABLE, SUBGRAPH_INPUT, SUBGRAPH_OUTPUT,
-     * or NO_VALUE:
-     * - All the fields must be 0.
-     * If the lifetime is CONSTANT_COPY:
-     * - location.poolIndex is 0.
-     * - location.offset is the offset in bytes into Model.operandValues.
-     * - location.length is set.
-     * If the lifetime is CONSTANT_REFERENCE:
-     * - location.poolIndex is set.
-     * - location.offset is the offset in bytes into the specified pool.
-     * - location.length is set.
-     * If the lifetime is SUBGRAPH:
-     * - location.poolIndex is 0.
-     * - location.offset is the index of the referenced subgraph in
-     *   {@link Model::referenced}.
-     * - location.length is 0.
-     */
-    DataLocation location;
-
-    /**
-     * Additional parameters specific to a particular operand type.
-     */
-    @1.2::Operand.ExtraParams extraParams;
-};
-
-/**
- * A Neural Network Model.
- *
- * This includes not only the execution graph, but also constant data such as
- * weights or scalars added at construction time. The only information that
- * may not be known is the shape of the input tensors.
- */
-struct Model {
-    /**
-     * The top-level subgraph.
-     */
-    Subgraph main;
-
-    /**
-     * Referenced subgraphs.
-     *
-     * Each subgraph is referenced by the main subgraph or at least one other
-     * referenced subgraph.
-     *
-     * There must be no reference cycles.
-     */
-    vec<Subgraph> referenced;
-
-    /**
-     * A byte buffer containing operand data that were copied into the model.
-     *
-     * An operand's value must be located here if and only if Operand::lifetime
-     * equals OperandLifeTime::CONSTANT_COPY.
-     */
-    vec<uint8_t> operandValues;
-
-    /**
-     * A collection of shared memory pools containing operand values.
-     *
-     * An operand's value must be located here if and only if Operand::lifetime
-     * equals OperandLifeTime::CONSTANT_REFERENCE.
-     */
-    vec<memory> pools;
-
-    /**
-     * 'true' indicates TENSOR_FLOAT32 may be calculated with range and/or
-     * precision as low as that of the IEEE 754 16-bit floating-point format.
-     * 'false' indicates TENSOR_FLOAT32 must be calculated using at least the
-     * range and precision of the IEEE 754 32-bit floating-point format.
-     */
-    bool relaxComputationFloat32toFloat16;
-
-    /**
-     * The mapping between extension names and prefixes of operand and
-     * operation type values.
-     *
-     * An operand or operation whose numeric type value is above
-     * {@link OperandTypeRange::BASE_MAX} or
-     * {@link OperationTypeRange::BASE_MAX} respectively should be interpreted
-     * as an extension operand. The low
-     * {@link @1.2::Model::ExtensionTypeEncoding::LOW_BITS_TYPE} bits of the
-     * value correspond to the type ID within the extension and the high
-     * {@link @1.2::Model::ExtensionTypeEncoding::HIGH_BITS_PREFIX} bits encode
-     * the "prefix", which maps uniquely to the extension name.
-     *
-     * For example, if a model contains an operation whose value is
-     * 0xAAAABBBB and extensionNameToPrefix contains an entry with
-     * prefix=0xAAAA and name="vendor.test.test_extension", then
-     * the operation should be interpreted as the operation 0xBBBB
-     * of the extension named vendor.test.test_extension.
-     *
-     * This is a one-to-one correspondence. That is, there must be at most one
-     * prefix corresponding to each extension name and at most one extension
-     * name corresponding to each prefix.
-     */
-    vec<@1.2::Model.ExtensionNameAndPrefix> extensionNameToPrefix;
-};
-
-/**
- * An excerpt of the execution graph.
- */
-struct Subgraph {
-    /**
-     * All operands included in the subgraph.
-     */
-    vec<Operand> operands;
-
-    /**
-     * All operations included in the subgraph.
-     *
-     * The operations are sorted into execution order. Every operand
-     * with lifetime SUBGRAPH_OUTPUT or TEMPORARY_VARIABLE must be
-     * written before it is read.
-     */
-    vec<Operation> operations;
-
-    /**
-     * Input indexes of the subgraph. There must be at least one.
-     *
-     * Each value corresponds to the index of the operand in "operands".
-     */
-    vec<uint32_t> inputIndexes;
-
-    /**
-     * Output indexes of the subgraph. There must be at least one.
-     *
-     * Each value corresponds to the index of the operand in "operands".
-     */
-    vec<uint32_t> outputIndexes;
-};
-
-/**
- * A buffer descriptor. Describes the properties of a buffer.
- */
-struct BufferDesc {
-    /**
-     * Dimensions of the buffer. May have unknown dimensions or rank. A buffer with some number
-     * of unspecified dimensions is represented by setting each unspecified dimension to 0. A
-     * buffer with unspecified rank is represented by providing an empty dimensions vector.
-     */
-    vec<uint32_t> dimensions;
-};
-
-/**
- * Describes a role of an input or output to a prepared model.
- */
-struct BufferRole {
-    /**
-     * The index of the IPreparedModel within the "preparedModel" argument passed in
-     * IDevice::allocate.
-     */
-    uint32_t modelIndex;
-
-    /**
-     * The index of the input or output operand.
-     */
-    uint32_t ioIndex;
-
-    /**
-     * A floating-point value within the range (0.0, 1.0]. Describes how likely the
-     * buffer is to be used in the specified role. This is provided as a hint to
-     * optimize the case when multiple roles prefer different buffer locations or data
-     * layouts.
-     */
-    float frequency;
-};
-
-/**
- * Inputs to be sent to and outputs to be retrieved from a prepared model.
- *
- * A Request serves two primary tasks:
- * 1) Provides the input and output data to be used when executing the model.
- * 2) Specifies any updates to the input operand metadata that were left
- *    unspecified at model preparation time.
- *
- * An output must not overlap with any other output, with an input, or
- * with an operand of lifetime CONSTANT_REFERENCE.
- */
-struct Request {
-    /**
-     * Input data and information to be used in the execution of a prepared
-     * model.
-     *
-     * The index of the input corresponds to the index in Model.main.inputIndexes.
-     *   E.g., input[i] corresponds to Model.main.inputIndexes[i].
-     */
-    vec<RequestArgument> inputs;
-
-    /**
-     * Output data and information to be used in the execution of a prepared
-     * model.
-     *
-     * The index of the output corresponds to the index in Model.main.outputIndexes.
-     *   E.g., output[i] corresponds to Model.main.outputIndexes[i].
-     */
-    vec<RequestArgument> outputs;
-
-    /**
-     * A memory pool.
-     */
-    safe_union MemoryPool {
-        /**
-         * Specifies a client-managed shared memory pool.
-         */
-        memory hidlMemory;
-
-        /**
-         * Specifies a driver-managed buffer. It is the token returned from IDevice::allocate,
-         * and is specific to the IDevice object.
-         */
-        uint32_t token;
-    };
-
-    /**
-     * A collection of memory pools containing operand data for both the
-     * inputs and the outputs to a model.
-     */
-    vec<MemoryPool> pools;
-};
+%insert Request
 
 /**
  * Optional time point of the steady clock (as from std::chrono::steady_clock)
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/BufferDesc.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/BufferDesc.aidl
index 71b7758..05cec76 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/BufferDesc.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/BufferDesc.aidl
@@ -12,7 +12,8 @@
  * WITHOUT 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/BufferRole.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/BufferRole.aidl
index c2d636c..f18e92a 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/BufferRole.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/BufferRole.aidl
@@ -12,7 +12,8 @@
  * WITHOUT 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Capabilities.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Capabilities.aidl
index 01cc753..30877c0 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Capabilities.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Capabilities.aidl
@@ -12,7 +12,8 @@
  * WITHOUT 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/DataLocation.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/DataLocation.aidl
index e836dae..db49a38 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/DataLocation.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/DataLocation.aidl
@@ -12,7 +12,8 @@
  * WITHOUT 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/DeviceBuffer.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/DeviceBuffer.aidl
index 7bc8aa7..7cdd6db 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/DeviceBuffer.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/DeviceBuffer.aidl
@@ -12,7 +12,8 @@
  * WITHOUT 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/DeviceType.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/DeviceType.aidl
index 1abacc8..82fe8ae 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/DeviceType.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/DeviceType.aidl
@@ -12,7 +12,8 @@
  * WITHOUT 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/ErrorStatus.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/ErrorStatus.aidl
index 873c584..57d5d6e 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/ErrorStatus.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/ErrorStatus.aidl
@@ -12,7 +12,8 @@
  * WITHOUT 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/ExecutionPreference.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/ExecutionPreference.aidl
index c4badc0..4352d8f 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/ExecutionPreference.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/ExecutionPreference.aidl
@@ -12,7 +12,8 @@
  * WITHOUT 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/ExecutionResult.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/ExecutionResult.aidl
index b99bb31..44e9922 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/ExecutionResult.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/ExecutionResult.aidl
@@ -12,7 +12,8 @@
  * WITHOUT 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Extension.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Extension.aidl
index a7ae942..c47028d 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Extension.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Extension.aidl
@@ -12,7 +12,8 @@
  * WITHOUT 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/ExtensionNameAndPrefix.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/ExtensionNameAndPrefix.aidl
index 4c25538..6c287fd 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/ExtensionNameAndPrefix.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/ExtensionNameAndPrefix.aidl
@@ -12,7 +12,8 @@
  * WITHOUT 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/ExtensionOperandTypeInformation.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/ExtensionOperandTypeInformation.aidl
index b32b217..a3680aa 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/ExtensionOperandTypeInformation.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/ExtensionOperandTypeInformation.aidl
@@ -12,7 +12,8 @@
  * WITHOUT 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/FusedActivationFunc.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/FusedActivationFunc.aidl
index 2fee136..7e61bbb 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/FusedActivationFunc.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/FusedActivationFunc.aidl
@@ -12,7 +12,8 @@
  * WITHOUT 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IBuffer.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IBuffer.aidl
index 2860692..f10e7e2 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IBuffer.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IBuffer.aidl
@@ -12,7 +12,8 @@
  * WITHOUT 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/HardwareInfo.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IBurst.aidl
similarity index 79%
copy from biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/HardwareInfo.aidl
copy to neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IBurst.aidl
index c5288fd..634f39e 100644
--- a/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/HardwareInfo.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IBurst.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2021 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -31,10 +31,9 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.common;
+package android.hardware.neuralnetworks;
 @VintfStability
-parcelable HardwareInfo {
-  String deviceName;
-  String hardwareVersion;
-  String serialNumber;
+interface IBurst {
+  android.hardware.neuralnetworks.ExecutionResult executeSynchronously(in android.hardware.neuralnetworks.Request request, in long[] memoryIdentifierTokens, in boolean measureTiming, in long deadline, in long loopTimeoutDuration);
+  void releaseMemoryResource(in long memoryIdentifierToken);
 }
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IDevice.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IDevice.aidl
index 4c5fd2f..b328b29 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IDevice.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IDevice.aidl
@@ -12,7 +12,8 @@
  * WITHOUT 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IFencedExecutionCallback.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IFencedExecutionCallback.aidl
index abe67b8..0bfb80a 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IFencedExecutionCallback.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IFencedExecutionCallback.aidl
@@ -12,7 +12,8 @@
  * WITHOUT 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IPreparedModel.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IPreparedModel.aidl
index 1f7cbe0..52882cd 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IPreparedModel.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IPreparedModel.aidl
@@ -12,7 +12,8 @@
  * WITHOUT 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -35,6 +36,7 @@
 interface IPreparedModel {
   android.hardware.neuralnetworks.ExecutionResult executeSynchronously(in android.hardware.neuralnetworks.Request request, in boolean measureTiming, in long deadline, in long loopTimeoutDuration);
   android.hardware.neuralnetworks.FencedExecutionResult executeFenced(in android.hardware.neuralnetworks.Request request, in ParcelFileDescriptor[] waitFor, in boolean measureTiming, in long deadline, in long loopTimeoutDuration, in long duration);
+  android.hardware.neuralnetworks.IBurst configureExecutionBurst();
   const long DEFAULT_LOOP_TIMEOUT_DURATION_NS = 2000000000;
   const long MAXIMUM_LOOP_TIMEOUT_DURATION_NS = 15000000000;
 }
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IPreparedModelCallback.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IPreparedModelCallback.aidl
index 8eaaab6..e0c763b 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IPreparedModelCallback.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IPreparedModelCallback.aidl
@@ -12,7 +12,8 @@
  * WITHOUT 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IPreparedModelParcel.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IPreparedModelParcel.aidl
index 8388fda..dbedf12 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IPreparedModelParcel.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IPreparedModelParcel.aidl
@@ -12,7 +12,8 @@
  * WITHOUT 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Memory.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Memory.aidl
index 3b2f240..8207b25 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Memory.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Memory.aidl
@@ -12,7 +12,8 @@
  * WITHOUT 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Model.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Model.aidl
index 9d12e58..30d8dda 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Model.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Model.aidl
@@ -12,7 +12,8 @@
  * WITHOUT 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/NumberOfCacheFiles.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/NumberOfCacheFiles.aidl
index c1e87da..9314760 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/NumberOfCacheFiles.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/NumberOfCacheFiles.aidl
@@ -12,7 +12,8 @@
  * WITHOUT 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Operand.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Operand.aidl
index bb78caa..5a9f4ff 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Operand.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Operand.aidl
@@ -12,7 +12,8 @@
  * WITHOUT 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/OperandExtraParams.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/OperandExtraParams.aidl
index 3f6d93b..14792cf 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/OperandExtraParams.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/OperandExtraParams.aidl
@@ -12,7 +12,8 @@
  * WITHOUT 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/OperandLifeTime.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/OperandLifeTime.aidl
index d581ced..40adfb1 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/OperandLifeTime.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/OperandLifeTime.aidl
@@ -12,7 +12,8 @@
  * WITHOUT 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/OperandPerformance.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/OperandPerformance.aidl
index 87fd3a6..de93d8b 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/OperandPerformance.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/OperandPerformance.aidl
@@ -12,7 +12,8 @@
  * WITHOUT 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/OperandType.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/OperandType.aidl
index 186c13d..9f2c759 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/OperandType.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/OperandType.aidl
@@ -12,7 +12,8 @@
  * WITHOUT 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Operation.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Operation.aidl
index fec83a8..33fcd60 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Operation.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Operation.aidl
@@ -12,7 +12,8 @@
  * WITHOUT 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/OperationType.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/OperationType.aidl
index ad42b02..de3b438 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/OperationType.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/OperationType.aidl
@@ -12,7 +12,8 @@
  * WITHOUT 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/OutputShape.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/OutputShape.aidl
index 09a43f7..f733505 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/OutputShape.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/OutputShape.aidl
@@ -12,7 +12,8 @@
  * WITHOUT 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/PerformanceInfo.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/PerformanceInfo.aidl
index 178946c..04910f5 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/PerformanceInfo.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/PerformanceInfo.aidl
@@ -12,7 +12,8 @@
  * WITHOUT 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Priority.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Priority.aidl
index d9b77fa..8f35709 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Priority.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Priority.aidl
@@ -12,7 +12,8 @@
  * WITHOUT 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Request.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Request.aidl
index 599b3f4..39ec7a9 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Request.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Request.aidl
@@ -12,7 +12,8 @@
  * WITHOUT 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/RequestArgument.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/RequestArgument.aidl
index 91b9aa7..e3541c0 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/RequestArgument.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/RequestArgument.aidl
@@ -12,7 +12,8 @@
  * WITHOUT 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/RequestMemoryPool.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/RequestMemoryPool.aidl
index 3813b51..312f581 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/RequestMemoryPool.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/RequestMemoryPool.aidl
@@ -12,7 +12,8 @@
  * WITHOUT 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Subgraph.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Subgraph.aidl
index dec976f..b7d4451 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Subgraph.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Subgraph.aidl
@@ -12,7 +12,8 @@
  * WITHOUT 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/SymmPerChannelQuantParams.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/SymmPerChannelQuantParams.aidl
index 66fdfe7..02d68f9 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/SymmPerChannelQuantParams.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/SymmPerChannelQuantParams.aidl
@@ -12,7 +12,8 @@
  * WITHOUT 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Timing.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Timing.aidl
index d0de34a..9690e01 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Timing.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Timing.aidl
@@ -12,7 +12,8 @@
  * WITHOUT 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/neuralnetworks/aidl/android/hardware/neuralnetworks/IBurst.aidl b/neuralnetworks/aidl/android/hardware/neuralnetworks/IBurst.aidl
new file mode 100644
index 0000000..85d2a03
--- /dev/null
+++ b/neuralnetworks/aidl/android/hardware/neuralnetworks/IBurst.aidl
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.neuralnetworks;
+
+import android.hardware.neuralnetworks.ErrorStatus;
+import android.hardware.neuralnetworks.ExecutionResult;
+import android.hardware.neuralnetworks.Request;
+
+/**
+ * IBurst represents a burst execution object.
+ *
+ * Burst executions are a sequence of executions of the same prepared model that occur in rapid
+ * succession, such as frames of a camera capture or successive audio samples. A burst object is
+ * used to control a set of burst executions, and to preserve resources between executions, enabling
+ * executions to have lower overhead. Burst objects enable some optimizations:
+ * (1) A burst object is created before a sequence of executions, and freed when the sequence has
+ *     ended. Because of this, the lifetime of the burst object hints to a driver how long it should
+ *     remain in a high performance state.
+ * (2) A burst object can preserve resources between executions. For example, a driver can map a
+ *     memory object on the first execution and cache the mapping in the burst object for reuse in
+ *     subsequent executions. Any cached resource can be released when the burst object is destroyed
+ *     or when the NNAPI runtime notifies the burst object that the resource is no longer required.
+ * (3) A burst object may be used for at most one execution at a time. This enables any transient
+ *     execution resources such as intermediate tensors to be allocated once when the burst object
+ *     is created and freed when the burst object is destroyed.
+ */
+@VintfStability
+interface IBurst {
+    /**
+     * Performs a synchronous execution on a burst object.
+     *
+     * The execution is performed synchronously with respect to the caller. executeSynchronously
+     * must verify the inputs to the function are correct, and the usages of memory pools allocated
+     * by IDevice::allocate are valid. If there is an error, executeSynchronously must immediately
+     * return a service specific exception with the appropriate ErrorStatus value. If the inputs to
+     * the function are valid and there is no error, executeSynchronously must perform the
+     * execution, and must not return until the execution is complete.
+     *
+     * The caller must not change the content of any data object referenced by 'request' (described
+     * by the {@link DataLocation} of a {@link RequestArgument}) until executeSynchronously returns.
+     * executeSynchronously must not change the content of any of the data objects corresponding to
+     * 'request' inputs.
+     *
+     * If the burst object was configured from a prepared model wherein all tensor operands have
+     * fully specified dimensions, and the inputs to the function are valid, and at execution time
+     * every operation's input operands have legal values, then the execution should complete
+     * successfully: there must be no failure unless the device itself is in a bad state.
+     *
+     * executeSynchronously may be called with an optional deadline. If the execution is not able to
+     * be completed before the provided deadline, the execution may be aborted, and either
+     * {@link ErrorStatus::MISSED_DEADLINE_TRANSIENT} or {@link
+     * ErrorStatus::MISSED_DEADLINE_PERSISTENT} may be returned. The error due to an abort must be
+     * sent the same way as other errors, described above.
+     *
+     * Only a single execution on a given burst object may be active at any time.
+     *
+     * @param request The input and output information on which the prepared model is to be
+     *                executed.
+     * @param memoryIdentifierTokens A list of tokens where each token is a non-negative number
+     *                               that uniquely identifies a memory object. Each memory
+     *                               identifier token corresponds to an element of request.pools. A
+     *                               value of -1 indicates no identity.
+     * @param measure Specifies whether or not to measure duration of the execution. The duration
+     *                runs from the time the driver sees the call to the executeSynchronously
+     *                function to the time the driver returns from the function.
+     * @param deadline The time by which the execution is expected to complete. The time is measured
+     *                 in nanoseconds since epoch of the steady clock (as from
+     *                 std::chrono::steady_clock). If the execution cannot be finished by the
+     *                 deadline, the execution may be aborted. Passing -1 means the deadline is
+     *                 omitted. Other negative values are invalid.
+     * @param loopTimeoutDuration The maximum amount of time in nanoseconds that should be spent
+     *                            executing a {@link OperationType::WHILE} operation. If a loop
+     *                            condition model does not output false within this duration, the
+     *                            execution must be aborted. If -1 is provided, the maximum amount
+     *                            of time is {@link DEFAULT_LOOP_TIMEOUT_DURATION_NS}. Other
+     *                            negative values are invalid. When provided, the duration must not
+     *                            exceed {@link MAXIMUM_LOOP_TIMEOUT_DURATION_NS}.
+     * @return ExecutionResult parcelable, containing the status of the execution, output shapes and
+     *     timing information.
+     * @throws ServiceSpecificException with one of the following ErrorStatus values:
+     *     - DEVICE_UNAVAILABLE if driver is offline or busy
+     *     - GENERAL_FAILURE if there is an unspecified error
+     *     - INVALID_ARGUMENT if one of the input arguments is invalid
+     *     - MISSED_DEADLINE_* if the execution is aborted because it cannot be completed by the
+     *       deadline
+     *     - RESOURCE_EXHAUSTED_* if the task was aborted by the driver
+     */
+    ExecutionResult executeSynchronously(in Request request, in long[] memoryIdentifierTokens,
+            in boolean measureTiming, in long deadline, in long loopTimeoutDuration);
+
+    /**
+     * releaseMemoryResource is used by the client to signal to the service that a memory buffer
+     * corresponding to a slot number is no longer needed by the client, and any cached resources
+     * associated with that memory object may be released.
+     *
+     * The identifier tokens are unique to the burst object.
+     *
+     * @param memoryIdentifierToken Value uniquely identifying a memory object that is no longer
+     *                              used.
+     * @throws ServiceSpecificException with one of the following ErrorStatus values:
+     *     - DEVICE_UNAVAILABLE if driver is offline or busy
+     *     - GENERAL_FAILURE if there is an unspecified error
+     *     - INVALID_ARGUMENT if one of the input arguments is invalid
+     */
+    void releaseMemoryResource(in long memoryIdentifierToken);
+}
diff --git a/neuralnetworks/aidl/android/hardware/neuralnetworks/IPreparedModel.aidl b/neuralnetworks/aidl/android/hardware/neuralnetworks/IPreparedModel.aidl
index 0240e3c..2a9757b 100644
--- a/neuralnetworks/aidl/android/hardware/neuralnetworks/IPreparedModel.aidl
+++ b/neuralnetworks/aidl/android/hardware/neuralnetworks/IPreparedModel.aidl
@@ -20,6 +20,7 @@
 import android.hardware.neuralnetworks.ErrorStatus;
 import android.hardware.neuralnetworks.ExecutionResult;
 import android.hardware.neuralnetworks.FencedExecutionResult;
+import android.hardware.neuralnetworks.IBurst;
 import android.hardware.neuralnetworks.Request;
 
 /**
@@ -166,4 +167,22 @@
     FencedExecutionResult executeFenced(in Request request, in ParcelFileDescriptor[] waitFor,
             in boolean measureTiming, in long deadline, in long loopTimeoutDuration,
             in long duration);
+
+    /**
+     * Configure a Burst object used to execute multiple inferences on a prepared model in rapid
+     * succession.
+     *
+     * If the prepared model was prepared from a model wherein all tensor operands have fully
+     * specified dimensions, and a valid serialized Request is sent to the Burst for execution, and
+     * at execution time every operation's input operands have legal values, then the execution
+     * should complete successfully (ErrorStatus::NONE): There must be no failure unless the device
+     * itself is in a bad state.
+     *
+     * @return burst Execution burst controller object.
+     * @throws ServiceSpecificException with one of the following ErrorStatus values:
+     *     - DEVICE_UNAVAILABLE if driver is offline or busy
+     *     - GENERAL_FAILURE if there is an unspecified error
+     *     - RESOURCE_EXHAUSTED_* if the task was aborted by the driver
+     */
+    IBurst configureExecutionBurst();
 }
diff --git a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Service.h b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Service.h
index b4587ac..cb6ff4b 100644
--- a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Service.h
+++ b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Service.h
@@ -20,13 +20,12 @@
 #include <nnapi/IDevice.h>
 #include <nnapi/Result.h>
 #include <nnapi/Types.h>
-#include <nnapi/hal/CommonUtils.h>
 
 #include <string>
 
 namespace aidl::android::hardware::neuralnetworks::utils {
 
-nn::GeneralResult<nn::SharedDevice> getDevice(const std::string& name);
+::android::nn::GeneralResult<::android::nn::SharedDevice> getDevice(const std::string& name);
 
 }  // namespace aidl::android::hardware::neuralnetworks::utils
 
diff --git a/neuralnetworks/aidl/utils/src/Service.cpp b/neuralnetworks/aidl/utils/src/Service.cpp
index 5ec6ded..511de55 100644
--- a/neuralnetworks/aidl/utils/src/Service.cpp
+++ b/neuralnetworks/aidl/utils/src/Service.cpp
@@ -18,6 +18,7 @@
 
 #include <android/binder_auto_utils.h>
 #include <android/binder_manager.h>
+#include <android/binder_process.h>
 
 #include <nnapi/IDevice.h>
 #include <nnapi/Result.h>
@@ -29,19 +30,21 @@
 
 namespace aidl::android::hardware::neuralnetworks::utils {
 
-nn::GeneralResult<nn::SharedDevice> getDevice(const std::string& name) {
+nn::GeneralResult<nn::SharedDevice> getDevice(const std::string& instanceName) {
+    auto fullName = std::string(IDevice::descriptor) + "/" + instanceName;
     hal::utils::ResilientDevice::Factory makeDevice =
-            [name](bool blocking) -> nn::GeneralResult<nn::SharedDevice> {
-        auto service = blocking ? IDevice::fromBinder(
-                                          ndk::SpAIBinder(AServiceManager_getService(name.c_str())))
-                                : IDevice::fromBinder(ndk::SpAIBinder(
-                                          AServiceManager_checkService(name.c_str())));
+            [instanceName,
+             name = std::move(fullName)](bool blocking) -> nn::GeneralResult<nn::SharedDevice> {
+        const auto& getService =
+                blocking ? AServiceManager_getService : AServiceManager_checkService;
+        auto service = IDevice::fromBinder(ndk::SpAIBinder(getService(name.c_str())));
         if (service == nullptr) {
             return NN_ERROR() << (blocking ? "AServiceManager_getService"
                                            : "AServiceManager_checkService")
                               << " returned nullptr";
         }
-        return Device::create(name, std::move(service));
+        ABinderProcess_startThreadPool();
+        return Device::create(instanceName, std::move(service));
     };
 
     return hal::utils::ResilientDevice::create(std::move(makeDevice));
diff --git a/neuralnetworks/aidl/utils/test/MockPreparedModel.h b/neuralnetworks/aidl/utils/test/MockPreparedModel.h
index 545b491..36e0ec3 100644
--- a/neuralnetworks/aidl/utils/test/MockPreparedModel.h
+++ b/neuralnetworks/aidl/utils/test/MockPreparedModel.h
@@ -39,6 +39,8 @@
                  bool measureTiming, int64_t deadline, int64_t loopTimeoutDuration,
                  int64_t duration, FencedExecutionResult* fencedExecutionResult),
                 (override));
+    MOCK_METHOD(ndk::ScopedAStatus, configureExecutionBurst, (std::shared_ptr<IBurst> * burst),
+                (override));
 };
 
 inline std::shared_ptr<MockPreparedModel> MockPreparedModel::create() {
diff --git a/neuralnetworks/aidl/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/aidl/vts/functional/GeneratedTestHarness.cpp
index 4eb704b..2dd02dd 100644
--- a/neuralnetworks/aidl/vts/functional/GeneratedTestHarness.cpp
+++ b/neuralnetworks/aidl/vts/functional/GeneratedTestHarness.cpp
@@ -17,6 +17,7 @@
 #include "GeneratedTestHarness.h"
 
 #include <aidl/android/hardware/neuralnetworks/ErrorStatus.h>
+#include <aidl/android/hardware/neuralnetworks/RequestMemoryPool.h>
 #include <android-base/logging.h>
 #include <android/binder_auto_utils.h>
 #include <android/sync.h>
@@ -299,9 +300,11 @@
 }
 
 static void makeOutputInsufficientSize(uint32_t outputIndex, Request* request) {
-    auto& length = request->outputs[outputIndex].location.length;
-    ASSERT_GT(length, 1u);
-    length -= 1u;
+    auto& loc = request->outputs[outputIndex].location;
+    ASSERT_GT(loc.length, 1u);
+    loc.length -= 1u;
+    // Test that the padding is not used for output data.
+    loc.padding += 1u;
 }
 
 static void makeOutputDimensionsUnspecified(Model* model) {
@@ -336,6 +339,12 @@
     std::vector<std::shared_ptr<IBuffer>> mBuffers;
 };
 
+// Returns the number of bytes needed to round up "size" to the nearest multiple of "multiple".
+static uint32_t roundUpBytesNeeded(uint32_t size, uint32_t multiple) {
+    CHECK(multiple != 0);
+    return ((size + multiple - 1) / multiple) * multiple - size;
+}
+
 std::optional<Request> ExecutionContext::createRequest(const TestModel& testModel,
                                                        MemoryType memoryType) {
     // Memory pools are organized as:
@@ -370,10 +379,13 @@
         }
 
         // Reserve shared memory for input.
+        inputSize += roundUpBytesNeeded(inputSize, nn::kDefaultRequestMemoryAlignment);
+        const auto padding = roundUpBytesNeeded(op.data.size(), nn::kDefaultRequestMemoryPadding);
         DataLocation loc = {.poolIndex = kInputPoolIndex,
                             .offset = static_cast<int64_t>(inputSize),
-                            .length = static_cast<int64_t>(op.data.size())};
-        inputSize += op.data.alignedSize();
+                            .length = static_cast<int64_t>(op.data.size()),
+                            .padding = static_cast<int64_t>(padding)};
+        inputSize += (op.data.size() + padding);
         inputs[i] = {.hasNoValue = false, .location = loc, .dimensions = {}};
     }
 
@@ -404,10 +416,13 @@
         size_t bufferSize = std::max<size_t>(op.data.size(), 1);
 
         // Reserve shared memory for output.
+        outputSize += roundUpBytesNeeded(outputSize, nn::kDefaultRequestMemoryAlignment);
+        const auto padding = roundUpBytesNeeded(bufferSize, nn::kDefaultRequestMemoryPadding);
         DataLocation loc = {.poolIndex = kOutputPoolIndex,
                             .offset = static_cast<int64_t>(outputSize),
-                            .length = static_cast<int64_t>(bufferSize)};
-        outputSize += op.data.size() == 0 ? TestBuffer::kAlignment : op.data.alignedSize();
+                            .length = static_cast<int64_t>(bufferSize),
+                            .padding = static_cast<int64_t>(padding)};
+        outputSize += (bufferSize + padding);
         outputs[i] = {.hasNoValue = false, .location = loc, .dimensions = {}};
     }
 
@@ -568,6 +583,53 @@
             }
             break;
         }
+        case Executor::BURST: {
+            SCOPED_TRACE("burst");
+
+            // create burst
+            std::shared_ptr<IBurst> burst;
+            auto ret = preparedModel->configureExecutionBurst(&burst);
+            ASSERT_TRUE(ret.isOk()) << ret.getDescription();
+            ASSERT_NE(nullptr, burst.get());
+
+            // associate a unique slot with each memory pool
+            int64_t currentSlot = 0;
+            std::vector<int64_t> slots;
+            slots.reserve(request.pools.size());
+            for (const auto& pool : request.pools) {
+                if (pool.getTag() == RequestMemoryPool::Tag::pool) {
+                    slots.push_back(currentSlot++);
+                } else {
+                    EXPECT_EQ(pool.getTag(), RequestMemoryPool::Tag::token);
+                    slots.push_back(-1);
+                }
+            }
+
+            ExecutionResult executionResult;
+            // execute
+            ret = burst->executeSynchronously(request, slots, testConfig.measureTiming, kNoDeadline,
+                                              loopTimeoutDuration, &executionResult);
+            ASSERT_TRUE(ret.isOk() || ret.getExceptionCode() == EX_SERVICE_SPECIFIC)
+                    << ret.getDescription();
+            if (ret.isOk()) {
+                executionStatus = executionResult.outputSufficientSize
+                                          ? ErrorStatus::NONE
+                                          : ErrorStatus::OUTPUT_INSUFFICIENT_SIZE;
+                outputShapes = std::move(executionResult.outputShapes);
+                timing = executionResult.timing;
+            } else {
+                executionStatus = static_cast<ErrorStatus>(ret.getServiceSpecificError());
+            }
+
+            // Mark each slot as unused after the execution. This is unnecessary because the burst
+            // is freed after this scope ends, but this is here to test the functionality.
+            for (int64_t slot : slots) {
+                ret = burst->releaseMemoryResource(slot);
+                ASSERT_TRUE(ret.isOk()) << ret.getDescription();
+            }
+
+            break;
+        }
         case Executor::FENCED: {
             SCOPED_TRACE("fenced");
             ErrorStatus result = ErrorStatus::NONE;
@@ -713,19 +775,19 @@
         case TestKind::GENERAL: {
             outputTypesList = {OutputType::FULLY_SPECIFIED};
             measureTimingList = {false, true};
-            executorList = {Executor::SYNC};
+            executorList = {Executor::SYNC, Executor::BURST};
             memoryTypeList = {MemoryType::ASHMEM};
         } break;
         case TestKind::DYNAMIC_SHAPE: {
             outputTypesList = {OutputType::UNSPECIFIED, OutputType::INSUFFICIENT};
             measureTimingList = {false, true};
-            executorList = {Executor::SYNC, Executor::FENCED};
+            executorList = {Executor::SYNC, Executor::BURST, Executor::FENCED};
             memoryTypeList = {MemoryType::ASHMEM};
         } break;
         case TestKind::MEMORY_DOMAIN: {
             outputTypesList = {OutputType::FULLY_SPECIFIED};
             measureTimingList = {false};
-            executorList = {Executor::SYNC, Executor::FENCED};
+            executorList = {Executor::SYNC, Executor::BURST, Executor::FENCED};
             memoryTypeList = {MemoryType::BLOB_AHWB, MemoryType::DEVICE};
         } break;
         case TestKind::FENCED_COMPUTE: {
@@ -741,7 +803,7 @@
         case TestKind::INTINITE_LOOP_TIMEOUT: {
             outputTypesList = {OutputType::MISSED_DEADLINE};
             measureTimingList = {false, true};
-            executorList = {Executor::SYNC, Executor::FENCED};
+            executorList = {Executor::SYNC, Executor::BURST, Executor::FENCED};
             memoryTypeList = {MemoryType::ASHMEM};
         } break;
     }
@@ -765,7 +827,7 @@
                                    const TestModel& coupledModel) {
     const std::vector<OutputType> outputTypesList = {OutputType::FULLY_SPECIFIED};
     const std::vector<bool> measureTimingList = {false, true};
-    const std::vector<Executor> executorList = {Executor::SYNC, Executor::FENCED};
+    const std::vector<Executor> executorList = {Executor::SYNC, Executor::BURST, Executor::FENCED};
 
     for (const OutputType outputType : outputTypesList) {
         for (const bool measureTiming : measureTimingList) {
diff --git a/neuralnetworks/aidl/vts/functional/MemoryDomainTests.cpp b/neuralnetworks/aidl/vts/functional/MemoryDomainTests.cpp
index 57bc1ae..627c26a 100644
--- a/neuralnetworks/aidl/vts/functional/MemoryDomainTests.cpp
+++ b/neuralnetworks/aidl/vts/functional/MemoryDomainTests.cpp
@@ -203,6 +203,10 @@
         return ndk::ScopedAStatus::fromServiceSpecificError(
                 static_cast<int32_t>(ErrorStatus::GENERAL_FAILURE));
     }
+    ndk::ScopedAStatus configureExecutionBurst(std::shared_ptr<IBurst>*) override {
+        return ndk::ScopedAStatus::fromServiceSpecificError(
+                static_cast<int32_t>(ErrorStatus::GENERAL_FAILURE));
+    }
 };
 
 template <typename... Args>
@@ -866,6 +870,9 @@
             case Executor::SYNC:
                 EXPECT_EQ(executeSync(preparedModel, request), expectedStatus);
                 break;
+            case Executor::BURST:
+                EXPECT_EQ(executeBurst(preparedModel, request), expectedStatus);
+                break;
             case Executor::FENCED:
                 EXPECT_EQ(executeFenced(preparedModel, request), expectedStatus);
                 break;
@@ -916,6 +923,35 @@
         return executionStatus;
     }
 
+    ErrorStatus executeBurst(const std::shared_ptr<IPreparedModel>& preparedModel,
+                             const Request& request) {
+        // create burst
+        std::shared_ptr<IBurst> burst;
+        auto ret = preparedModel->configureExecutionBurst(&burst);
+        EXPECT_TRUE(ret.isOk()) << ret.getDescription();
+        EXPECT_NE(nullptr, burst.get());
+        if (!ret.isOk() || burst.get() == nullptr) {
+            return ErrorStatus::GENERAL_FAILURE;
+        }
+
+        // use -1 for all memory identifier tokens
+        const std::vector<int64_t> slots(request.pools.size(), -1);
+
+        ExecutionResult executionResult;
+        ret = burst->executeSynchronously(request, slots, false, kNoDeadline,
+                                          kOmittedTimeoutDuration, &executionResult);
+
+        if (!ret.isOk()) {
+            EXPECT_EQ(ret.getExceptionCode(), EX_SERVICE_SPECIFIC);
+            return static_cast<ErrorStatus>(ret.getServiceSpecificError());
+        }
+        const ErrorStatus executionStatus = executionResult.outputSufficientSize
+                                                    ? ErrorStatus::NONE
+                                                    : ErrorStatus::OUTPUT_INSUFFICIENT_SIZE;
+        EXPECT_EQ(executionResult.timing, kNoTiming);
+        return executionStatus;
+    }
+
     const Executor kExecutor = std::get<Executor>(GetParam());
 };
 
@@ -1159,7 +1195,7 @@
                   ErrorStatus::GENERAL_FAILURE);
 }
 
-const auto kExecutorChoices = testing::Values(Executor::SYNC, Executor::FENCED);
+const auto kExecutorChoices = testing::Values(Executor::SYNC, Executor::BURST, Executor::FENCED);
 
 std::string printMemoryDomainExecutionTest(
         const testing::TestParamInfo<MemoryDomainExecutionTestParam>& info) {
diff --git a/neuralnetworks/aidl/vts/functional/QualityOfServiceTests.cpp b/neuralnetworks/aidl/vts/functional/QualityOfServiceTests.cpp
index 58db98f..9ace1a9 100644
--- a/neuralnetworks/aidl/vts/functional/QualityOfServiceTests.cpp
+++ b/neuralnetworks/aidl/vts/functional/QualityOfServiceTests.cpp
@@ -51,6 +51,10 @@
 using Results = std::tuple<ErrorStatus, std::vector<OutputShape>, Timing>;
 using MaybeResults = std::optional<Results>;
 
+using ExecutionFunction =
+        std::function<MaybeResults(const std::shared_ptr<IPreparedModel>& preparedModel,
+                                   const Request& request, int64_t deadline)>;
+
 static int64_t makeDeadline(DeadlineBoundType deadlineBoundType) {
     const auto getNanosecondsSinceEpoch = [](const auto& time) -> int64_t {
         const auto timeSinceEpoch = time.time_since_epoch();
@@ -177,13 +181,53 @@
                          std::move(executionResult.outputShapes), executionResult.timing});
 }
 
+static MaybeResults executeBurst(const std::shared_ptr<IPreparedModel>& preparedModel,
+                                 const Request& request, int64_t deadline) {
+    SCOPED_TRACE("burst");
+    const bool measure = false;
+
+    // create burst
+    std::shared_ptr<IBurst> burst;
+    auto ret = preparedModel->configureExecutionBurst(&burst);
+    EXPECT_TRUE(ret.isOk()) << ret.getDescription();
+    EXPECT_NE(nullptr, burst.get());
+    if (!ret.isOk() || burst.get() == nullptr) {
+        return std::nullopt;
+    }
+
+    // use -1 for all memory identifier tokens
+    const std::vector<int64_t> slots(request.pools.size(), -1);
+
+    // run execution
+    ExecutionResult executionResult;
+    ret = burst->executeSynchronously(request, slots, measure, deadline, kOmittedTimeoutDuration,
+                                      &executionResult);
+    EXPECT_TRUE(ret.isOk() || ret.getExceptionCode() == EX_SERVICE_SPECIFIC)
+            << ret.getDescription();
+    if (!ret.isOk()) {
+        if (ret.getExceptionCode() != EX_SERVICE_SPECIFIC) {
+            return std::nullopt;
+        }
+        return MaybeResults(
+                {static_cast<ErrorStatus>(ret.getServiceSpecificError()), {}, kNoTiming});
+    }
+
+    // return results
+    return MaybeResults({executionResult.outputSufficientSize
+                                 ? ErrorStatus::NONE
+                                 : ErrorStatus::OUTPUT_INSUFFICIENT_SIZE,
+                         std::move(executionResult.outputShapes), executionResult.timing});
+}
+
 void runExecutionTest(const std::shared_ptr<IPreparedModel>& preparedModel,
                       const TestModel& testModel, const Request& request,
-                      const ExecutionContext& context, DeadlineBoundType deadlineBound) {
+                      const ExecutionContext& context, bool synchronous,
+                      DeadlineBoundType deadlineBound) {
+    const ExecutionFunction execute = synchronous ? executeSynchronously : executeBurst;
     const auto deadline = makeDeadline(deadlineBound);
 
     // Perform execution and unpack results.
-    const auto results = executeSynchronously(preparedModel, request, deadline);
+    const auto results = execute(preparedModel, request, deadline);
     if (!results.has_value()) return;
     const auto& [status, outputShapes, timing] = results.value();
 
@@ -235,8 +279,11 @@
 void runExecutionTests(const std::shared_ptr<IPreparedModel>& preparedModel,
                        const TestModel& testModel, const Request& request,
                        const ExecutionContext& context) {
-    for (auto deadlineBound : deadlineBounds) {
-        runExecutionTest(preparedModel, testModel, request, context, deadlineBound);
+    for (bool synchronous : {false, true}) {
+        for (auto deadlineBound : deadlineBounds) {
+            runExecutionTest(preparedModel, testModel, request, context, synchronous,
+                             deadlineBound);
+        }
     }
 }
 
diff --git a/neuralnetworks/aidl/vts/functional/ValidateRequest.cpp b/neuralnetworks/aidl/vts/functional/ValidateRequest.cpp
index 3be4c1b..29e2471 100644
--- a/neuralnetworks/aidl/vts/functional/ValidateRequest.cpp
+++ b/neuralnetworks/aidl/vts/functional/ValidateRequest.cpp
@@ -16,7 +16,9 @@
 
 #define LOG_TAG "neuralnetworks_aidl_hal_test"
 
+#include <aidl/android/hardware/neuralnetworks/RequestMemoryPool.h>
 #include <android/binder_auto_utils.h>
+#include <variant>
 
 #include <chrono>
 
@@ -77,6 +79,35 @@
         ASSERT_EQ(static_cast<ErrorStatus>(executeStatus.getServiceSpecificError()),
                   ErrorStatus::INVALID_ARGUMENT);
     }
+
+    // burst
+    {
+        SCOPED_TRACE(message + " [burst]");
+
+        // create burst
+        std::shared_ptr<IBurst> burst;
+        auto ret = preparedModel->configureExecutionBurst(&burst);
+        ASSERT_TRUE(ret.isOk()) << ret.getDescription();
+        ASSERT_NE(nullptr, burst.get());
+
+        // use -1 for all memory identifier tokens
+        const std::vector<int64_t> slots(request.pools.size(), -1);
+
+        ExecutionResult executionResult;
+        const auto executeStatus = burst->executeSynchronously(
+                request, slots, measure, kNoDeadline, kOmittedTimeoutDuration, &executionResult);
+        ASSERT_FALSE(executeStatus.isOk());
+        ASSERT_EQ(executeStatus.getExceptionCode(), EX_SERVICE_SPECIFIC);
+        ASSERT_EQ(static_cast<ErrorStatus>(executeStatus.getServiceSpecificError()),
+                  ErrorStatus::INVALID_ARGUMENT);
+    }
+}
+
+std::shared_ptr<IBurst> createBurst(const std::shared_ptr<IPreparedModel>& preparedModel) {
+    std::shared_ptr<IBurst> burst;
+    const auto ret = preparedModel->configureExecutionBurst(&burst);
+    if (!ret.isOk()) return nullptr;
+    return burst;
 }
 
 ///////////////////////// REMOVE INPUT ////////////////////////////////////
@@ -110,6 +141,65 @@
     removeOutputTest(preparedModel, request);
 }
 
+void validateBurst(const std::shared_ptr<IPreparedModel>& preparedModel, const Request& request) {
+    // create burst
+    std::shared_ptr<IBurst> burst;
+    auto ret = preparedModel->configureExecutionBurst(&burst);
+    ASSERT_TRUE(ret.isOk()) << ret.getDescription();
+    ASSERT_NE(nullptr, burst.get());
+
+    const auto test = [&burst, &request](const std::vector<int64_t>& slots) {
+        ExecutionResult executionResult;
+        const auto executeStatus =
+                burst->executeSynchronously(request, slots, /*measure=*/false, kNoDeadline,
+                                            kOmittedTimeoutDuration, &executionResult);
+        ASSERT_FALSE(executeStatus.isOk());
+        ASSERT_EQ(executeStatus.getExceptionCode(), EX_SERVICE_SPECIFIC);
+        ASSERT_EQ(static_cast<ErrorStatus>(executeStatus.getServiceSpecificError()),
+                  ErrorStatus::INVALID_ARGUMENT);
+    };
+
+    int64_t currentSlot = 0;
+    std::vector<int64_t> slots;
+    slots.reserve(request.pools.size());
+    for (const auto& pool : request.pools) {
+        if (pool.getTag() == RequestMemoryPool::Tag::pool) {
+            slots.push_back(currentSlot++);
+        } else {
+            slots.push_back(-1);
+        }
+    }
+
+    constexpr int64_t invalidSlot = -2;
+
+    // validate failure when invalid memory identifier token value
+    for (size_t i = 0; i < request.pools.size(); ++i) {
+        const int64_t oldSlotValue = slots[i];
+
+        slots[i] = invalidSlot;
+        test(slots);
+
+        slots[i] = oldSlotValue;
+    }
+
+    // validate failure when request.pools.size() != memoryIdentifierTokens.size()
+    if (request.pools.size() > 0) {
+        slots = std::vector<int64_t>(request.pools.size() - 1, -1);
+        test(slots);
+    }
+
+    // validate failure when request.pools.size() != memoryIdentifierTokens.size()
+    slots = std::vector<int64_t>(request.pools.size() + 1, -1);
+    test(slots);
+
+    // validate failure when invalid memory identifier token value
+    const auto freeStatus = burst->releaseMemoryResource(invalidSlot);
+    ASSERT_FALSE(freeStatus.isOk());
+    ASSERT_EQ(freeStatus.getExceptionCode(), EX_SERVICE_SPECIFIC);
+    ASSERT_EQ(static_cast<ErrorStatus>(freeStatus.getServiceSpecificError()),
+              ErrorStatus::INVALID_ARGUMENT);
+}
+
 void validateRequestFailure(const std::shared_ptr<IPreparedModel>& preparedModel,
                             const Request& request) {
     SCOPED_TRACE("Expecting request to fail [executeSynchronously]");
diff --git a/neuralnetworks/aidl/vts/functional/VtsHalNeuralnetworks.cpp b/neuralnetworks/aidl/vts/functional/VtsHalNeuralnetworks.cpp
index 2d91b8e..0c3a196 100644
--- a/neuralnetworks/aidl/vts/functional/VtsHalNeuralnetworks.cpp
+++ b/neuralnetworks/aidl/vts/functional/VtsHalNeuralnetworks.cpp
@@ -127,6 +127,8 @@
 // Forward declaration from ValidateRequest.cpp
 void validateRequest(const std::shared_ptr<IPreparedModel>& preparedModel, const Request& request);
 // Forward declaration from ValidateRequest.cpp
+void validateBurst(const std::shared_ptr<IPreparedModel>& preparedModel, const Request& request);
+// Forward declaration from ValidateRequest.cpp
 void validateRequestFailure(const std::shared_ptr<IPreparedModel>& preparedModel,
                             const Request& request);
 
@@ -140,6 +142,7 @@
     if (preparedModel == nullptr) return;
 
     validateRequest(preparedModel, request);
+    validateBurst(preparedModel, request);
     // HIDL also had test that expected executeFenced to fail on received null fd (-1). This is not
     // allowed in AIDL and will result in EX_TRANSACTION_FAILED.
 }
@@ -178,8 +181,6 @@
 
 std::string toString(Executor executor) {
     switch (executor) {
-        case Executor::ASYNC:
-            return "ASYNC";
         case Executor::SYNC:
             return "SYNC";
         case Executor::BURST:
diff --git a/neuralnetworks/aidl/vts/functional/VtsHalNeuralnetworks.h b/neuralnetworks/aidl/vts/functional/VtsHalNeuralnetworks.h
index 9b81ee1..4312d3a 100644
--- a/neuralnetworks/aidl/vts/functional/VtsHalNeuralnetworks.h
+++ b/neuralnetworks/aidl/vts/functional/VtsHalNeuralnetworks.h
@@ -52,7 +52,7 @@
                          std::shared_ptr<IPreparedModel>* preparedModel,
                          bool reportSkipping = true);
 
-enum class Executor { ASYNC, SYNC, BURST, FENCED };
+enum class Executor { SYNC, BURST, FENCED };
 
 std::string toString(Executor executor);
 
diff --git a/neuralnetworks/utils/service/Android.bp b/neuralnetworks/utils/service/Android.bp
index 9f8b9bb..5f36dff 100644
--- a/neuralnetworks/utils/service/Android.bp
+++ b/neuralnetworks/utils/service/Android.bp
@@ -35,12 +35,15 @@
         "neuralnetworks_utils_hal_1_1",
         "neuralnetworks_utils_hal_1_2",
         "neuralnetworks_utils_hal_1_3",
+        "neuralnetworks_utils_hal_aidl",
         "neuralnetworks_utils_hal_common",
     ],
     shared_libs: [
+        "android.hardware.neuralnetworks-V1-ndk_platform",
         "android.hardware.neuralnetworks@1.0",
         "android.hardware.neuralnetworks@1.1",
         "android.hardware.neuralnetworks@1.2",
         "android.hardware.neuralnetworks@1.3",
+        "libbinder_ndk",
     ],
 }
diff --git a/neuralnetworks/utils/service/src/Service.cpp b/neuralnetworks/utils/service/src/Service.cpp
index a59549d..c83bcc9 100644
--- a/neuralnetworks/utils/service/src/Service.cpp
+++ b/neuralnetworks/utils/service/src/Service.cpp
@@ -16,7 +16,9 @@
 
 #include "Service.h"
 
+#include <aidl/android/hardware/neuralnetworks/IDevice.h>
 #include <android-base/logging.h>
+#include <android/binder_manager.h>
 #include <android/hardware/neuralnetworks/1.0/IDevice.h>
 #include <android/hardware/neuralnetworks/1.1/IDevice.h>
 #include <android/hardware/neuralnetworks/1.2/IDevice.h>
@@ -31,6 +33,7 @@
 #include <nnapi/hal/1.1/Service.h>
 #include <nnapi/hal/1.2/Service.h>
 #include <nnapi/hal/1.3/Service.h>
+#include <nnapi/hal/aidl/Service.h>
 
 #include <functional>
 #include <memory>
@@ -42,11 +45,12 @@
 namespace android::hardware::neuralnetworks::service {
 namespace {
 
+namespace aidl_hal = ::aidl::android::hardware::neuralnetworks;
 using getDeviceFn = std::add_pointer_t<nn::GeneralResult<nn::SharedDevice>(const std::string&)>;
 
-void getDevicesForVersion(const std::string& descriptor, getDeviceFn getDevice,
-                          std::vector<nn::SharedDevice>* devices,
-                          std::unordered_set<std::string>* registeredDevices) {
+void getHidlDevicesForVersion(const std::string& descriptor, getDeviceFn getDevice,
+                              std::vector<nn::SharedDevice>* devices,
+                              std::unordered_set<std::string>* registeredDevices) {
     CHECK(devices != nullptr);
     CHECK(registeredDevices != nullptr);
 
@@ -66,18 +70,52 @@
     }
 }
 
+void getAidlDevices(std::vector<nn::SharedDevice>* devices,
+                    std::unordered_set<std::string>* registeredDevices) {
+    CHECK(devices != nullptr);
+    CHECK(registeredDevices != nullptr);
+
+    std::vector<std::string> names;
+    constexpr auto callback = [](const char* serviceName, void* names) {
+        static_cast<std::vector<std::string>*>(names)->emplace_back(serviceName);
+    };
+
+    // Devices with SDK level lower than 31 (Android S) don't have any AIDL drivers available, so
+    // there is no need for a workaround supported on lower levels.
+    if (__builtin_available(android __ANDROID_API_S__, *)) {
+        AServiceManager_forEachDeclaredInstance(aidl_hal::IDevice::descriptor,
+                                                static_cast<void*>(&names), callback);
+    }
+
+    for (const auto& name : names) {
+        if (const auto [it, unregistered] = registeredDevices->insert(name); unregistered) {
+            auto maybeDevice = aidl_hal::utils::getDevice(name);
+            if (maybeDevice.has_value()) {
+                auto device = std::move(maybeDevice).value();
+                CHECK(device != nullptr);
+                devices->push_back(std::move(device));
+            } else {
+                LOG(ERROR) << "getDevice(" << name << ") failed with " << maybeDevice.error().code
+                           << ": " << maybeDevice.error().message;
+            }
+        }
+    }
+}
+
 std::vector<nn::SharedDevice> getDevices() {
     std::vector<nn::SharedDevice> devices;
     std::unordered_set<std::string> registeredDevices;
 
-    getDevicesForVersion(V1_3::IDevice::descriptor, &V1_3::utils::getDevice, &devices,
-                         &registeredDevices);
-    getDevicesForVersion(V1_2::IDevice::descriptor, &V1_2::utils::getDevice, &devices,
-                         &registeredDevices);
-    getDevicesForVersion(V1_1::IDevice::descriptor, &V1_1::utils::getDevice, &devices,
-                         &registeredDevices);
-    getDevicesForVersion(V1_0::IDevice::descriptor, &V1_0::utils::getDevice, &devices,
-                         &registeredDevices);
+    getAidlDevices(&devices, &registeredDevices);
+
+    getHidlDevicesForVersion(V1_3::IDevice::descriptor, &V1_3::utils::getDevice, &devices,
+                             &registeredDevices);
+    getHidlDevicesForVersion(V1_2::IDevice::descriptor, &V1_2::utils::getDevice, &devices,
+                             &registeredDevices);
+    getHidlDevicesForVersion(V1_1::IDevice::descriptor, &V1_1::utils::getDevice, &devices,
+                             &registeredDevices);
+    getHidlDevicesForVersion(V1_0::IDevice::descriptor, &V1_0::utils::getDevice, &devices,
+                             &registeredDevices);
 
     return devices;
 }
diff --git a/radio/1.6/IRadioResponse.hal b/radio/1.6/IRadioResponse.hal
index d65c6d0..805586b 100644
--- a/radio/1.6/IRadioResponse.hal
+++ b/radio/1.6/IRadioResponse.hal
@@ -342,6 +342,7 @@
      *  RadioError:RADIO_NOT_AVAILABLE
      *  RadioError:MODEM_ERR
      *  RadioError:INVALID_ARGUMENTS
+     *  RadioError:REQUEST_NOT_SUPPORTED
      */
     oneway setDataThrottlingResponse(RadioResponseInfo info);
 
@@ -432,6 +433,7 @@
      *   RadioError:RADIO_NOT_AVAILABLE
      *   RadioError:INTERNAL_ERR
      *   RadioError:MODEM_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
      */
     oneway getSlicingConfigResponse(RadioResponseInfo info,
             SlicingConfig slicingConfig);
diff --git a/radio/1.6/types.hal b/radio/1.6/types.hal
index 95eba69..f2c0e76 100644
--- a/radio/1.6/types.hal
+++ b/radio/1.6/types.hal
@@ -1027,18 +1027,6 @@
      */
     uint8_t precedence;
     /**
-     * Parameters defining this RouteSelectionDescriptor. The length of the vector
-     * must be >= 1.
-     */
-    vec<RouteSelectionDescriptorParams> routeSelectionDescriptorParams;
-};
-
-/**
- * This struct represents a route selection descriptor. A valid struct must have
- * at least one of the vectors non-empty.
- */
-struct RouteSelectionDescriptorParams {
-    /**
      * Valid values are IP, IPV6 and IPV4V6.
      */
     OptionalPdpProtocolType sessionType;
diff --git a/radio/1.6/vts/functional/radio_hidl_hal_api.cpp b/radio/1.6/vts/functional/radio_hidl_hal_api.cpp
index 91d98cb..70abc4b 100644
--- a/radio/1.6/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.6/vts/functional/radio_hidl_hal_api.cpp
@@ -172,7 +172,13 @@
     EXPECT_EQ(std::cv_status::no_timeout, wait());
     EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
     EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
-    EXPECT_EQ(::android::hardware::radio::V1_6::RadioError::NONE, radioRsp_v1_6->rspInfo.error);
+    if (getRadioHalCapabilities().modemReducedFeatureSet1) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_v1_6->rspInfo.error,
+                {::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED}));
+    } else {
+        EXPECT_EQ(::android::hardware::radio::V1_6::RadioError::NONE, radioRsp_v1_6->rspInfo.error);
+    }
 }
 
 /*
@@ -420,13 +426,18 @@
     EXPECT_EQ(std::cv_status::no_timeout, wait());
     EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
     EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
-    ASSERT_TRUE(
-            CheckAnyOfErrors(radioRsp_v1_6->rspInfo.error,
-                             {::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE,
-                              ::android::hardware::radio::V1_6::RadioError::MODEM_ERR,
-                              ::android::hardware::radio::V1_6::RadioError::NONE,
-                              ::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS}));
-
+    if (getRadioHalCapabilities().modemReducedFeatureSet1) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_v1_6->rspInfo.error,
+                {::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED}));
+    } else {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_v1_6->rspInfo.error,
+                {::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE,
+                 ::android::hardware::radio::V1_6::RadioError::MODEM_ERR,
+                 ::android::hardware::radio::V1_6::RadioError::NONE,
+                 ::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS}));
+    }
     serial = GetRandomSerialNumber();
 
     res = radio_v1_6->setDataThrottling(serial, DataThrottlingAction::THROTTLE_ANCHOR_CARRIER,
@@ -435,13 +446,18 @@
     EXPECT_EQ(std::cv_status::no_timeout, wait());
     EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
     EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
-    ASSERT_TRUE(
-            CheckAnyOfErrors(radioRsp_v1_6->rspInfo.error,
-                             {::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE,
-                              ::android::hardware::radio::V1_6::RadioError::MODEM_ERR,
-                              ::android::hardware::radio::V1_6::RadioError::NONE,
-                              ::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS}));
-
+    if (getRadioHalCapabilities().modemReducedFeatureSet1) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_v1_6->rspInfo.error,
+                {::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED}));
+    } else {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_v1_6->rspInfo.error,
+                {::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE,
+                 ::android::hardware::radio::V1_6::RadioError::MODEM_ERR,
+                 ::android::hardware::radio::V1_6::RadioError::NONE,
+                 ::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS}));
+    }
     serial = GetRandomSerialNumber();
 
     res = radio_v1_6->setDataThrottling(serial, DataThrottlingAction::HOLD, 60000);
@@ -450,13 +466,18 @@
     EXPECT_EQ(std::cv_status::no_timeout, wait());
     EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
     EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
-    ASSERT_TRUE(
-            CheckAnyOfErrors(radioRsp_v1_6->rspInfo.error,
-                             {::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE,
-                              ::android::hardware::radio::V1_6::RadioError::MODEM_ERR,
-                              ::android::hardware::radio::V1_6::RadioError::NONE,
-                              ::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS}));
-
+    if (getRadioHalCapabilities().modemReducedFeatureSet1) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_v1_6->rspInfo.error,
+                {::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED}));
+    } else {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_v1_6->rspInfo.error,
+                {::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE,
+                 ::android::hardware::radio::V1_6::RadioError::MODEM_ERR,
+                 ::android::hardware::radio::V1_6::RadioError::NONE,
+                 ::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS}));
+    }
     serial = GetRandomSerialNumber();
 
     res = radio_v1_6->setDataThrottling(serial, DataThrottlingAction::NO_DATA_THROTTLING, 60000);
@@ -464,12 +485,18 @@
     EXPECT_EQ(std::cv_status::no_timeout, wait());
     EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
     EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
-    ASSERT_TRUE(
-            CheckAnyOfErrors(radioRsp_v1_6->rspInfo.error,
-                             {::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE,
-                              ::android::hardware::radio::V1_6::RadioError::MODEM_ERR,
-                              ::android::hardware::radio::V1_6::RadioError::NONE,
-                              ::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS}));
+    if (getRadioHalCapabilities().modemReducedFeatureSet1) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_v1_6->rspInfo.error,
+                {::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED}));
+    } else {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_v1_6->rspInfo.error,
+                {::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE,
+                 ::android::hardware::radio::V1_6::RadioError::MODEM_ERR,
+                 ::android::hardware::radio::V1_6::RadioError::NONE,
+                 ::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS}));
+    }
 }
 
 /*
diff --git a/radio/config/1.3/types.hal b/radio/config/1.3/types.hal
index 117abf3..8667f0a 100644
--- a/radio/config/1.3/types.hal
+++ b/radio/config/1.3/types.hal
@@ -31,6 +31,11 @@
    * <li> calling android.hardware.radio@1.6::IRadio.setNrDualConnectivityState
    * or querying android.hardware.radio@1.6::IRadio.isNrDualConnectivityEnabled
    * </li>
+   * <li>Requesting android.hardware.radio@1.6::IRadio.setDataThrottling()
+   * </li>
+   * <li>Providing android.hardware.radio@1.6::SlicingConfig through
+   * android.hardware.radio@1.6::getSlicingConfig()
+   * </li>
    * </ul>
    */
   bool modemReducedFeatureSet1;
diff --git a/radio/config/1.3/vts/functional/radio_config_hidl_hal_utils.h b/radio/config/1.3/vts/functional/radio_config_hidl_hal_utils.h
index 895ae08..50038eb 100644
--- a/radio/config/1.3/vts/functional/radio_config_hidl_hal_utils.h
+++ b/radio/config/1.3/vts/functional/radio_config_hidl_hal_utils.h
@@ -37,7 +37,7 @@
 
 #include "vts_test_util.h"
 
-using namespace ::android::hardware::radio::config::V1_2;
+using namespace ::android::hardware::radio::config::V1_3;
 
 using ::android::sp;
 using ::android::hardware::hidl_string;
@@ -46,9 +46,11 @@
 using ::android::hardware::Void;
 using ::android::hardware::radio::config::V1_1::ModemsConfig;
 using ::android::hardware::radio::config::V1_1::PhoneCapability;
+using ::android::hardware::radio::config::V1_2::IRadioConfigIndication;
 using ::android::hardware::radio::config::V1_2::SimSlotStatus;
 using ::android::hardware::radio::config::V1_3::HalDeviceCapabilities;
 using ::android::hardware::radio::config::V1_3::IRadioConfig;
+using ::android::hardware::radio::config::V1_3::IRadioConfigResponse;
 using ::android::hardware::radio::V1_0::RadioResponseInfo;
 
 #define RADIO_SERVICE_NAME "slot1"
diff --git a/radio/config/1.3/vts/functional/radio_config_response.cpp b/radio/config/1.3/vts/functional/radio_config_response.cpp
index 11e3cce..5501ae2 100644
--- a/radio/config/1.3/vts/functional/radio_config_response.cpp
+++ b/radio/config/1.3/vts/functional/radio_config_response.cpp
@@ -64,8 +64,9 @@
 }
 
 Return<void> RadioConfigResponse::getHalDeviceCapabilitiesResponse(
-        const ::android::hardware::radio::V1_6::RadioResponseInfo& /* info */,
+        const ::android::hardware::radio::V1_6::RadioResponseInfo& info,
         const ::android::hardware::radio::config::V1_3::HalDeviceCapabilities& capabilities) {
     halDeviceCapabilities = capabilities;
+    parent.notify(info.serial);
     return Void();
 }
diff --git a/scripts/list_hal_vts.py b/scripts/list_hal_vts.py
new file mode 100755
index 0000000..1fb51a5
--- /dev/null
+++ b/scripts/list_hal_vts.py
@@ -0,0 +1,143 @@
+#!/usr/bin/python3
+
+"""
+List VTS tests for each HAL by parsing module-info.json.
+
+Example usage:
+
+  # First, build modules-info.json
+  m -j "${ANDROID_PRODUCT_OUT#$ANDROID_BUILD_TOP/}/module-info.json"
+
+  # List with pretty-printed JSON. *IDL packages without a VTS module will show up
+  # as keys with empty lists.
+  ./list_hals_vts.py | python3 -m json.tool
+
+  # List with CSV. *IDL packages without a VTS module will show up as a line with
+  # empty value in the VTS module column.
+  ./list_hals_vts.py --csv
+"""
+
+import argparse
+import collections
+import csv
+import io
+import json
+import os
+import logging
+import pathlib
+import re
+import sys
+
+PATH_PACKAGE_PATTERN = re.compile(
+  r'^hardware/interfaces/(?P<path>(?:\w+/)*?)(?:aidl|(?P<version>\d+\.\d+))/.*')
+
+
+class CriticalHandler(logging.StreamHandler):
+  def emit(self, record):
+    super(CriticalHandler, self).emit(record)
+    if record.levelno >= logging.CRITICAL:
+      sys.exit(1)
+
+
+logger = logging.getLogger(__name__)
+logger.addHandler(CriticalHandler())
+
+
+def default_json():
+  out = os.environ.get('ANDROID_PRODUCT_OUT')
+  if not out: return None
+  return os.path.join(out, 'module-info.json')
+
+
+def infer_package(path):
+  """
+  Infer package from a relative path from build top where a VTS module lives.
+
+  :param path: a path like 'hardware/interfaces/vibrator/aidl/vts'
+  :return: The inferred *IDL package, e.g. 'android.hardware.vibrator'
+
+  >>> infer_package('hardware/interfaces/automotive/sv/1.0/vts/functional')
+  'android.hardware.automotive.sv@1.0'
+  >>> infer_package('hardware/interfaces/vibrator/aidl/vts')
+  'android.hardware.vibrator'
+  """
+  mo = re.match(PATH_PACKAGE_PATTERN, path)
+  if not mo: return None
+  package = 'android.hardware.' + ('.'.join(pathlib.Path(mo.group('path')).parts))
+  if mo.group('version'):
+    package += '@' + mo.group('version')
+  return package
+
+
+def load_modules_info(json_file):
+  """
+  :param json_file: The path to modules-info.json
+  :return: a dictionary, where the keys are inferred *IDL package names, and
+           values are a list of VTS modules with that inferred package name.
+  """
+  with open(json_file) as fp:
+    root = json.load(fp)
+    ret = collections.defaultdict(list)
+    for module_name, module_info in root.items():
+      if 'vts' not in module_info.get('compatibility_suites', []):
+        continue
+      for path in module_info.get('path', []):
+        inferred_package = infer_package(path)
+        if not inferred_package:
+          continue
+        ret[inferred_package].append(module_name)
+    return ret
+
+
+def add_missing_idl(vts_modules):
+  top = os.environ.get("ANDROID_BUILD_TOP")
+  interfaces = None
+  if top:
+    interfaces = os.path.join(top, "hardware", "interfaces")
+  else:
+    logger.warning("Missing ANDROID_BUILD_TOP")
+    interfaces = "hardware/interfaces"
+  if not os.path.isdir(interfaces):
+    logger.error("Not adding missing *IDL modules because missing hardware/interfaces dir")
+    return
+  assert not interfaces.endswith(os.path.sep)
+  for root, dirs, files in os.walk(interfaces):
+    for dir in dirs:
+      full_dir = os.path.join(root, dir)
+      assert full_dir.startswith(interfaces)
+      top_rel_dir = os.path.join('hardware', 'interfaces', full_dir[len(interfaces) + 1:])
+      inferred_package = infer_package(top_rel_dir)
+      if inferred_package is None:
+        continue
+      if inferred_package not in vts_modules:
+        vts_modules[inferred_package] = []
+
+
+def main():
+  parser = argparse.ArgumentParser(__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
+  parser.add_argument('json', metavar='module-info.json', default=default_json(), nargs='?')
+  parser.add_argument('--csv', action='store_true', help='Print CSV. If not specified print JSON.')
+  args = parser.parse_args()
+  if not args.json:
+    logger.critical('No module-info.json is specified or found.')
+  vts_modules = load_modules_info(args.json)
+  add_missing_idl(vts_modules)
+
+  if args.csv:
+    out = io.StringIO()
+    writer = csv.writer(out, )
+    writer.writerow(["package", "vts_module"])
+    for package, modules in vts_modules.items():
+      if not modules:
+        writer.writerow([package, ""])
+      for module in modules:
+        writer.writerow([package, module])
+    result = out.getvalue()
+  else:
+    result = json.dumps(vts_modules)
+
+  print(result)
+
+
+if __name__ == '__main__':
+  main()
diff --git a/security/keymint/aidl/Android.bp b/security/keymint/aidl/Android.bp
index 54cb4b8..6766d99 100644
--- a/security/keymint/aidl/Android.bp
+++ b/security/keymint/aidl/Android.bp
@@ -19,7 +19,8 @@
     stability: "vintf",
     backend: {
         java: {
-            sdk_version: "module_current",
+            platform_apis: true,
+            srcs_available: true,
         },
         ndk: {
             vndk: {
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Algorithm.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Algorithm.aidl
index 5adbdc1..6da124f 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Algorithm.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Algorithm.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.keymint;
+/* @hide */
 @Backing(type="int") @VintfStability
 enum Algorithm {
   RSA = 1,
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/AttestationKey.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/AttestationKey.aidl
index 21721bf..90f2e6e 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/AttestationKey.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/AttestationKey.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.keymint;
+/* @hide */
 @RustDerive(Clone=true, Eq=true, Hash=true, Ord=true, PartialEq=true, PartialOrd=true) @VintfStability
 parcelable AttestationKey {
   byte[] keyBlob;
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/BeginResult.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/BeginResult.aidl
index d9d9c13..c952a31 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/BeginResult.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/BeginResult.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.keymint;
+/* @hide */
 @VintfStability
 parcelable BeginResult {
   long challenge;
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/BlockMode.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/BlockMode.aidl
index feba9d0..0049883 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/BlockMode.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/BlockMode.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.keymint;
+/* @hide */
 @Backing(type="int") @VintfStability
 enum BlockMode {
   ECB = 1,
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Certificate.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Certificate.aidl
index 470d534..645f0a7 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Certificate.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Certificate.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.keymint;
+/* @hide */
 @VintfStability
 parcelable Certificate {
   byte[] encodedCertificate;
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Digest.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Digest.aidl
index 5a15aad..0df7096 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Digest.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Digest.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.keymint;
+/* @hide */
 @Backing(type="int") @VintfStability
 enum Digest {
   NONE = 0,
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/EcCurve.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/EcCurve.aidl
index d7ec006..6b4a9ae 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/EcCurve.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/EcCurve.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.keymint;
+/* @hide */
 @Backing(type="int") @VintfStability
 enum EcCurve {
   P_224 = 0,
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/ErrorCode.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/ErrorCode.aidl
index 91e2899..69ec4ce 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/ErrorCode.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/ErrorCode.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.keymint;
+/* @hide */
 @Backing(type="int") @VintfStability
 enum ErrorCode {
   OK = 0,
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/HardwareAuthToken.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/HardwareAuthToken.aidl
index 3205a46..2e07924 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/HardwareAuthToken.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/HardwareAuthToken.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.keymint;
+/* @hide */
 @RustDerive(Clone=true, Eq=true, Hash=true, Ord=true, PartialEq=true, PartialOrd=true) @VintfStability
 parcelable HardwareAuthToken {
   long challenge;
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/HardwareAuthenticatorType.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/HardwareAuthenticatorType.aidl
index 926f2ec..dfc98f0 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/HardwareAuthenticatorType.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/HardwareAuthenticatorType.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.keymint;
+/* @hide */
 @Backing(type="int") @VintfStability
 enum HardwareAuthenticatorType {
   NONE = 0,
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintDevice.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintDevice.aidl
index bb18669..195590c 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintDevice.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintDevice.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.keymint;
+/* @hide */
 @VintfStability
 interface IKeyMintDevice {
   android.hardware.security.keymint.KeyMintHardwareInfo getHardwareInfo();
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintOperation.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintOperation.aidl
index 28a83da..5ac2b4a 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintOperation.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintOperation.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.keymint;
+/* @hide */
 @VintfStability
 interface IKeyMintOperation {
   void updateAad(in byte[] input, in @nullable android.hardware.security.keymint.HardwareAuthToken authToken, in @nullable android.hardware.security.secureclock.TimeStampToken timeStampToken);
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
index 8387ecc..63bad2c 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.keymint;
+/* @hide */
 @VintfStability
 interface IRemotelyProvisionedComponent {
   byte[] generateEcdsaP256KeyPair(in boolean testMode, out android.hardware.security.keymint.MacedPublicKey macedPublicKey);
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyCharacteristics.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyCharacteristics.aidl
index 91ac7be..008381f 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyCharacteristics.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyCharacteristics.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.keymint;
+/* @hide */
 @VintfStability
 parcelable KeyCharacteristics {
   android.hardware.security.keymint.SecurityLevel securityLevel = android.hardware.security.keymint.SecurityLevel.SOFTWARE;
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyCreationResult.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyCreationResult.aidl
index b85203f..9f77d3e 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyCreationResult.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyCreationResult.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.keymint;
+/* @hide */
 @VintfStability
 parcelable KeyCreationResult {
   byte[] keyBlob;
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyFormat.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyFormat.aidl
index 4500288..9560d8d 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyFormat.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyFormat.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.keymint;
+/* @hide */
 @Backing(type="int") @VintfStability
 enum KeyFormat {
   X509 = 0,
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyMintHardwareInfo.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyMintHardwareInfo.aidl
index d959ac4..2113e42a 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyMintHardwareInfo.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyMintHardwareInfo.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.keymint;
+/* @hide */
 @RustDerive(Clone=true, Eq=true, Hash=true, Ord=true, PartialEq=true, PartialOrd=true) @VintfStability
 parcelable KeyMintHardwareInfo {
   int versionNumber;
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyOrigin.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyOrigin.aidl
index 2b65567..4b3c659 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyOrigin.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyOrigin.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.keymint;
+/* @hide */
 @Backing(type="int") @VintfStability
 enum KeyOrigin {
   GENERATED = 0,
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyParameter.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyParameter.aidl
index ee8abda..c5a1e01 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyParameter.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyParameter.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.keymint;
+/* @hide */
 @RustDerive(Clone=true, Eq=true, Hash=true, Ord=true, PartialEq=true, PartialOrd=true) @VintfStability
 parcelable KeyParameter {
   android.hardware.security.keymint.Tag tag = android.hardware.security.keymint.Tag.INVALID;
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyParameterValue.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyParameterValue.aidl
index fc57cd2..7a0b074 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyParameterValue.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyParameterValue.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.keymint;
+/* @hide */
 @RustDerive(Clone=true, Eq=true, Hash=true, Ord=true, PartialEq=true, PartialOrd=true) @VintfStability
 union KeyParameterValue {
   int invalid;
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyPurpose.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyPurpose.aidl
index f891de6..b84bec1 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyPurpose.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyPurpose.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.keymint;
+/* @hide */
 @Backing(type="int") @VintfStability
 enum KeyPurpose {
   ENCRYPT = 0,
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/MacedPublicKey.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/MacedPublicKey.aidl
index 30b38e1..8095e8c 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/MacedPublicKey.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/MacedPublicKey.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.keymint;
+/* @hide */
 @VintfStability
 parcelable MacedPublicKey {
   byte[] macedKey;
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/PaddingMode.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/PaddingMode.aidl
index bfb6ea1..dba4a8a 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/PaddingMode.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/PaddingMode.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.keymint;
+/* @hide */
 @Backing(type="int") @VintfStability
 enum PaddingMode {
   NONE = 1,
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/ProtectedData.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/ProtectedData.aidl
index 64cce78..d1610b4 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/ProtectedData.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/ProtectedData.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.keymint;
+/* @hide */
 @VintfStability
 parcelable ProtectedData {
   byte[] protectedData;
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/SecurityLevel.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/SecurityLevel.aidl
index 628476d..0d278e0 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/SecurityLevel.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/SecurityLevel.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.keymint;
+/* @hide */
 @Backing(type="int") @VintfStability
 enum SecurityLevel {
   SOFTWARE = 0,
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Tag.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Tag.aidl
index ccb0404..7591318 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Tag.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Tag.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.keymint;
+/* @hide */
 @Backing(type="int") @VintfStability
 enum Tag {
   INVALID = 0,
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/TagType.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/TagType.aidl
index 58f8bd3..a7d1de5 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/TagType.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/TagType.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.keymint;
+/* @hide */
 @Backing(type="int") @VintfStability
 enum TagType {
   INVALID = 0,
diff --git a/security/keymint/aidl/android/hardware/security/keymint/Algorithm.aidl b/security/keymint/aidl/android/hardware/security/keymint/Algorithm.aidl
index 8300b0d..1820893 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/Algorithm.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/Algorithm.aidl
@@ -18,6 +18,7 @@
 
 /**
  * Algorithms provided by IKeyMintDevice implementations.
+ * @hide
  */
 @VintfStability
 @Backing(type="int")
diff --git a/security/keymint/aidl/android/hardware/security/keymint/AttestationKey.aidl b/security/keymint/aidl/android/hardware/security/keymint/AttestationKey.aidl
index 8167ceb..b4bc60c 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/AttestationKey.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/AttestationKey.aidl
@@ -22,6 +22,7 @@
  * Contains a key blob with Tag::ATTEST_KEY that can be used to sign an attestation certificate,
  * and the DER-encoded X.501 Subject Name that will be placed in the Issuer field of the attestation
  * certificate.
+ * @hide
  */
 @VintfStability
 @RustDerive(Clone=true, Eq=true, PartialEq=true, Ord=true, PartialOrd=true, Hash=true)
diff --git a/security/keymint/aidl/android/hardware/security/keymint/BeginResult.aidl b/security/keymint/aidl/android/hardware/security/keymint/BeginResult.aidl
index aaf9f3c..2304a58 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/BeginResult.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/BeginResult.aidl
@@ -21,6 +21,7 @@
 
 /**
  * This is all the results returned by the IKeyMintDevice begin() function.
+ * @hide
  */
 @VintfStability
 parcelable BeginResult {
diff --git a/security/keymint/aidl/android/hardware/security/keymint/BlockMode.aidl b/security/keymint/aidl/android/hardware/security/keymint/BlockMode.aidl
index 629c89f..749da81 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/BlockMode.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/BlockMode.aidl
@@ -18,6 +18,7 @@
 
 /**
  * Symmetric block cipher modes provided by IKeyMintDevice implementations.
+ * @hide
  */
 @VintfStability
 @Backing(type="int")
diff --git a/security/keymint/aidl/android/hardware/security/keymint/Certificate.aidl b/security/keymint/aidl/android/hardware/security/keymint/Certificate.aidl
index 0e5d898..21dfdd5 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/Certificate.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/Certificate.aidl
@@ -18,6 +18,7 @@
 
 /**
  * This encodes an IKeyMintDevice certificate, generated for a KeyMint asymmetric public key.
+ * @hide
  */
 @VintfStability
 parcelable Certificate {
diff --git a/security/keymint/aidl/android/hardware/security/keymint/Digest.aidl b/security/keymint/aidl/android/hardware/security/keymint/Digest.aidl
index b44da5a..a8768c3 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/Digest.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/Digest.aidl
@@ -18,6 +18,7 @@
 
 /**
  * Digests provided by keyMint implementations.
+ * @hide
  */
 @VintfStability
 @Backing(type="int")
diff --git a/security/keymint/aidl/android/hardware/security/keymint/EcCurve.aidl b/security/keymint/aidl/android/hardware/security/keymint/EcCurve.aidl
index b9d1646..5b1c10c 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/EcCurve.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/EcCurve.aidl
@@ -18,6 +18,7 @@
 
 /**
  * Supported EC curves, used in ECDSA
+ * @hide
  */
 @VintfStability
 @Backing(type="int")
diff --git a/security/keymint/aidl/android/hardware/security/keymint/ErrorCode.aidl b/security/keymint/aidl/android/hardware/security/keymint/ErrorCode.aidl
index 95b38f2..0e2c5f2 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/ErrorCode.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/ErrorCode.aidl
@@ -19,6 +19,7 @@
 /**
  * KeyMint error codes.  Aidl will return these error codes as service specific
  * errors in EX_SERVICE_SPECIFIC.
+ * @hide
  */
 @VintfStability
 @Backing(type="int")
diff --git a/security/keymint/aidl/android/hardware/security/keymint/HardwareAuthToken.aidl b/security/keymint/aidl/android/hardware/security/keymint/HardwareAuthToken.aidl
index 57150d5..0933bd5 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/HardwareAuthToken.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/HardwareAuthToken.aidl
@@ -27,6 +27,7 @@
  * passed to begin(), update(), and finish() to prove that authentication occurred.  See those
  * methods for more details.  It is up to the caller to determine which of the generated auth tokens
  * is appropriate for a given key operation.
+ * @hide
  */
 @VintfStability
 @RustDerive(Clone=true, Eq=true, PartialEq=true, Ord=true, PartialOrd=true, Hash=true)
diff --git a/security/keymint/aidl/android/hardware/security/keymint/HardwareAuthenticatorType.aidl b/security/keymint/aidl/android/hardware/security/keymint/HardwareAuthenticatorType.aidl
index 33f71b8..2d9d0ff 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/HardwareAuthenticatorType.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/HardwareAuthenticatorType.aidl
@@ -20,6 +20,7 @@
  * Hardware authentication type, used by HardwareAuthTokens to specify the mechanism used to
  * authentiate the user, and in KeyCharacteristics to specify the allowable mechanisms for
  * authenticating to activate a key.
+ * @hide
  */
 @VintfStability
 @Backing(type="int")
diff --git a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
index 384416e..3100b23 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
@@ -211,6 +211,7 @@
  * hardwareEnforced authorization list.  Tag::OS_VERSION, Tag::OS_PATCHLEVEL,
  * Tag::VENDOR_PATCHLEVEL, and Tag::BOOT_PATCHLEVEL must be cryptographically bound to every
  * IKeyMintDevice key, as described in the Key Access Control section above.
+ * @hide
  */
 @VintfStability
 interface IKeyMintDevice {
diff --git a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintOperation.aidl b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintOperation.aidl
index 1c2511b..5ad54cd 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintOperation.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintOperation.aidl
@@ -20,6 +20,7 @@
 import android.hardware.security.keymint.KeyParameter;
 import android.hardware.security.secureclock.TimeStampToken;
 
+/** @hide */
 @VintfStability
 interface IKeyMintOperation {
     /**
diff --git a/security/keymint/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl b/security/keymint/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
index 1b09e9d..5c8ca6d 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
@@ -109,6 +109,7 @@
  * The IRemotelyProvisionedComponent supports a test mode, allowing the generation of test key pairs
  * and test CertificateRequests. Test keys/requests are annotated as such, and the BCC used for test
  * CertificateRequests must contain freshly-generated keys, not the real BCC key pairs.
+ * @hide
  */
 @VintfStability
 interface IRemotelyProvisionedComponent {
@@ -165,7 +166,7 @@
      *                protected: bstr .cbor {
      *                    1 : -8,                     // Algorithm : EdDSA
      *                },
-     *                unprotected: bstr .size 0
+     *                unprotected: { },
      *                payload: bstr .cbor SignatureKey,
      *                signature: bstr PureEd25519(.cbor SignatureKeySignatureInput)
      *            ]
@@ -190,7 +191,7 @@
      *                protected: bstr .cbor {
      *                    1 : -8,                     // Algorithm : EdDSA
      *                },
-     *                unprotected: bstr .size 0
+     *                unprotected: { },
      *                payload: bstr .cbor Eek,
      *                signature: bstr PureEd25519(.cbor EekSignatureInput)
      *            ]
@@ -239,7 +240,7 @@
      *                protected : bstr .cbor {
      *                    1 : 5,                           // Algorithm : HMAC-256
      *                },
-     *                unprotected : bstr .size 0,
+     *                unprotected : { },
      *                // Payload is PublicKeys from keysToSign argument, in provided order.
      *                payload: bstr .cbor [ * PublicKey ],
      *                tag: bstr
diff --git a/security/keymint/aidl/android/hardware/security/keymint/KeyCharacteristics.aidl b/security/keymint/aidl/android/hardware/security/keymint/KeyCharacteristics.aidl
index 3a32e4d..25fdee3 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/KeyCharacteristics.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/KeyCharacteristics.aidl
@@ -28,6 +28,7 @@
  * enforced.  Note that enforcement at a given security level means that the semantics of the tag
  * and value are fully enforced.  See the definition of individual tags for specifications of what
  * must be enforced.
+ * @hide
  */
 @VintfStability
 parcelable KeyCharacteristics {
diff --git a/security/keymint/aidl/android/hardware/security/keymint/KeyCreationResult.aidl b/security/keymint/aidl/android/hardware/security/keymint/KeyCreationResult.aidl
index 69bec2d7..c589ca1 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/KeyCreationResult.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/KeyCreationResult.aidl
@@ -22,6 +22,7 @@
 /**
  * This structure is returned when a new key is created with generateKey(), importKey() or
  * importWrappedKey().
+ * @hide
  */
 @VintfStability
 parcelable KeyCreationResult {
diff --git a/security/keymint/aidl/android/hardware/security/keymint/KeyFormat.aidl b/security/keymint/aidl/android/hardware/security/keymint/KeyFormat.aidl
index 6ad8e3d..da3d521 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/KeyFormat.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/KeyFormat.aidl
@@ -18,6 +18,7 @@
 
 /**
  * Formats for key import and export.
+ * @hide
  */
 @VintfStability
 @Backing(type="int")
diff --git a/security/keymint/aidl/android/hardware/security/keymint/KeyMintHardwareInfo.aidl b/security/keymint/aidl/android/hardware/security/keymint/KeyMintHardwareInfo.aidl
index ae0d152..8da7578 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/KeyMintHardwareInfo.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/KeyMintHardwareInfo.aidl
@@ -20,6 +20,7 @@
 
 /**
  * KeyMintHardwareInfo is the hardware information returned by calling KeyMint getHardwareInfo()
+ * @hide
  */
 @VintfStability
 @RustDerive(Clone=true, Eq=true, PartialEq=true, Ord=true, PartialOrd=true, Hash=true)
diff --git a/security/keymint/aidl/android/hardware/security/keymint/KeyOrigin.aidl b/security/keymint/aidl/android/hardware/security/keymint/KeyOrigin.aidl
index 0cd53c2..f896125 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/KeyOrigin.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/KeyOrigin.aidl
@@ -21,6 +21,7 @@
  * either the hardware-enforced or software-enforced list for a key, indicating whether the key is
  * hardware or software-based.  Specifically, a key with GENERATED in the hardware-enforced list
  * must be guaranteed never to have existed outide the secure hardware.
+ * @hide
  */
 @VintfStability
 @Backing(type="int")
diff --git a/security/keymint/aidl/android/hardware/security/keymint/KeyParameter.aidl b/security/keymint/aidl/android/hardware/security/keymint/KeyParameter.aidl
index bf6c9b2..b69e678 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/KeyParameter.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/KeyParameter.aidl
@@ -22,6 +22,7 @@
 /**
  * Identifies the key authorization parameters to be used with keyMint.  This is usually
  * provided as an array of KeyParameters to IKeyMintDevice or Operation.
+ * @hide
  */
 @VintfStability
 @RustDerive(Clone=true, Eq=true, PartialEq=true, Ord=true, PartialOrd=true, Hash=true)
diff --git a/security/keymint/aidl/android/hardware/security/keymint/KeyParameterValue.aidl b/security/keymint/aidl/android/hardware/security/keymint/KeyParameterValue.aidl
index a4f5154..59016f2 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/KeyParameterValue.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/KeyParameterValue.aidl
@@ -26,10 +26,10 @@
 import android.hardware.security.keymint.PaddingMode;
 import android.hardware.security.keymint.SecurityLevel;
 
+/** @hide */
 @VintfStability
 @RustDerive(Clone=true, Eq=true, PartialEq=true, Ord=true, PartialOrd=true, Hash=true)
 union KeyParameterValue {
-
     /* Represents an invalid value type. */
     int invalid;
 
@@ -45,7 +45,7 @@
     SecurityLevel securityLevel;
 
     /* Other types */
-    boolean boolValue;  // Always true, if present.
+    boolean boolValue; // Always true, if present.
     int integer;
     long longInteger;
     long dateTime;
diff --git a/security/keymint/aidl/android/hardware/security/keymint/KeyPurpose.aidl b/security/keymint/aidl/android/hardware/security/keymint/KeyPurpose.aidl
index 978a027..c874fc3 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/KeyPurpose.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/KeyPurpose.aidl
@@ -18,6 +18,7 @@
 
 /**
  * Possible purposes of a key (or pair).
+ * @hide
  */
 @VintfStability
 @Backing(type="int")
diff --git a/security/keymint/aidl/android/hardware/security/keymint/MacedPublicKey.aidl b/security/keymint/aidl/android/hardware/security/keymint/MacedPublicKey.aidl
index da85a50..a26094c 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/MacedPublicKey.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/MacedPublicKey.aidl
@@ -19,6 +19,7 @@
 /**
  * MacedPublicKey contains a CBOR-encoded public key, MACed by an IRemotelyProvisionedComponent, to
  * prove that the key pair was generated by that component.
+ * @hide
  */
 @VintfStability
 parcelable MacedPublicKey {
@@ -29,7 +30,7 @@
      *
      *     MacedPublicKey = [                     // COSE_Mac0
      *         protected: bstr .cbor { 1 : 5},    // Algorithm : HMAC-256
-     *         unprotected: bstr .size 0,
+     *         unprotected: { },
      *         payload : bstr .cbor PublicKey,
      *         tag : bstr HMAC-256(K_mac, MAC_structure)
      *     ]
diff --git a/security/keymint/aidl/android/hardware/security/keymint/PaddingMode.aidl b/security/keymint/aidl/android/hardware/security/keymint/PaddingMode.aidl
index 80b73bd..fbb373b 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/PaddingMode.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/PaddingMode.aidl
@@ -23,6 +23,7 @@
  * padding modes for both symmetric and asymmetric algorithms.  Note that implementations should not
  * provide all possible combinations of algorithm and padding, only the
  * cryptographically-appropriate pairs.
+ * @hide
  */
 @VintfStability
 @Backing(type="int")
diff --git a/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl b/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl
index 1ec3bf0..44f316f 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl
@@ -19,6 +19,7 @@
 /**
  * ProtectedData contains the encrypted BCC and the ephemeral MAC key used to
  * authenticate the keysToSign (see keysToSignMac output argument).
+ * @hide
  */
 @VintfStability
 parcelable ProtectedData {
@@ -80,7 +81,7 @@
      *         bstr .cbor {                    // Protected params
      *             1 : -8,                     // Algorithm : EdDSA
      *         },
-     *         bstr .size 0,                   // Unprotected params
+     *         { },                            // Unprotected params
      *         bstr .size 32,                  // MAC key
      *         bstr PureEd25519(DK_priv, .cbor SignedMac_structure)
      *     ]
@@ -127,7 +128,7 @@
      *         protected: bstr .cbor {
      *             1 : -8,                    // Algorithm : EdDSA
      *         },
-     *         unprotected: bstr .size 0,
+     *         unprotected: { },
      *         payload: bstr .cbor BccPayload,
      *         // First entry in the chain is signed by DK_pub, the others are each signed by their
      *         // immediate predecessor.  See RFC 8032 for signature representation.
diff --git a/security/keymint/aidl/android/hardware/security/keymint/SecurityLevel.aidl b/security/keymint/aidl/android/hardware/security/keymint/SecurityLevel.aidl
index ecbde8c..80c63b2 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/SecurityLevel.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/SecurityLevel.aidl
@@ -27,6 +27,7 @@
  *     certificates.  This specifies the security level of the weakest environment involved in
  *     enforcing that particular tag, i.e. the sort of security environment an attacker would have
  *     to subvert in order to break the enforcement of that tag.
+ * @hide
  */
 @VintfStability
 @Backing(type="int")
diff --git a/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl b/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl
index aa9aa6f..6243bb9 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl
@@ -25,6 +25,7 @@
 /**
  * Tag specifies various kinds of tags that can be set in KeyParameter to identify what kind of
  * data are stored in KeyParameter.
+ * @hide
  */
 @VintfStability
 @Backing(type="int")
diff --git a/security/keymint/aidl/android/hardware/security/keymint/TagType.aidl b/security/keymint/aidl/android/hardware/security/keymint/TagType.aidl
index a273af3..1ba6ede 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/TagType.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/TagType.aidl
@@ -18,6 +18,7 @@
 
 /**
  * TagType classifies Tags in Tag.aidl into various groups of data.
+ * @hide
  */
 @VintfStability
 @Backing(type="int")
diff --git a/security/keymint/aidl/default/RemotelyProvisionedComponent.cpp b/security/keymint/aidl/default/RemotelyProvisionedComponent.cpp
index 2373b26..749f0bc 100644
--- a/security/keymint/aidl/default/RemotelyProvisionedComponent.cpp
+++ b/security/keymint/aidl/default/RemotelyProvisionedComponent.cpp
@@ -156,7 +156,7 @@
         }
 
         auto protectedParms = macedKeyItem->asArray()->get(kCoseMac0ProtectedParams)->asBstr();
-        auto unprotectedParms = macedKeyItem->asArray()->get(kCoseMac0UnprotectedParams)->asBstr();
+        auto unprotectedParms = macedKeyItem->asArray()->get(kCoseMac0UnprotectedParams)->asMap();
         auto payload = macedKeyItem->asArray()->get(kCoseMac0Payload)->asBstr();
         auto tag = macedKeyItem->asArray()->get(kCoseMac0Tag)->asBstr();
         if (!protectedParms || !unprotectedParms || !payload || !tag) {
diff --git a/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp b/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
index db53a8f..50e6cce 100644
--- a/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
+++ b/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
@@ -97,9 +97,9 @@
     ASSERT_NE(protParms, nullptr);
     ASSERT_EQ(cppbor::prettyPrint(protParms->value()), "{\n  1 : 5,\n}");
 
-    auto unprotParms = coseMac0->asArray()->get(kCoseMac0UnprotectedParams)->asBstr();
+    auto unprotParms = coseMac0->asArray()->get(kCoseMac0UnprotectedParams)->asMap();
     ASSERT_NE(unprotParms, nullptr);
-    ASSERT_EQ(unprotParms->value().size(), 0);
+    ASSERT_EQ(unprotParms->size(), 0);
 
     auto payload = coseMac0->asArray()->get(kCoseMac0Payload)->asBstr();
     ASSERT_NE(payload, nullptr);
@@ -150,9 +150,9 @@
     ASSERT_NE(protParms, nullptr);
     ASSERT_EQ(cppbor::prettyPrint(protParms->value()), "{\n  1 : 5,\n}");
 
-    auto unprotParms = coseMac0->asArray()->get(kCoseMac0UnprotectedParams)->asBstr();
+    auto unprotParms = coseMac0->asArray()->get(kCoseMac0UnprotectedParams)->asMap();
     ASSERT_NE(unprotParms, nullptr);
-    ASSERT_EQ(unprotParms->value().size(), 0);
+    ASSERT_EQ(unprotParms->size(), 0);
 
     auto payload = coseMac0->asArray()->get(kCoseMac0Payload)->asBstr();
     ASSERT_NE(payload, nullptr);
@@ -279,7 +279,7 @@
                                          .add(ALGORITHM, HMAC_256)
                                          .canonicalize()
                                          .encode())
-                            .add(cppbor::Bstr())             // unprotected
+                            .add(cppbor::Map())              // unprotected
                             .add(cppbor::Array().encode())   // payload (keysToSign)
                             .add(std::move(keysToSignMac));  // tag
 
@@ -364,7 +364,7 @@
                                          .add(ALGORITHM, HMAC_256)
                                          .canonicalize()
                                          .encode())
-                            .add(cppbor::Bstr())             // unprotected
+                            .add(cppbor::Map())              // unprotected
                             .add(cborKeysToSign_.encode())   // payload
                             .add(std::move(keysToSignMac));  // tag
 
diff --git a/security/keymint/support/cppcose.cpp b/security/keymint/support/cppcose.cpp
index c626ade..bafb2b6 100644
--- a/security/keymint/support/cppcose.cpp
+++ b/security/keymint/support/cppcose.cpp
@@ -85,7 +85,7 @@
 
     return cppbor::Array()
             .add(cppbor::Map().add(ALGORITHM, HMAC_256).canonicalize().encode())
-            .add(cppbor::Bstr() /* unprotected */)
+            .add(cppbor::Map() /* unprotected */)
             .add(payload)
             .add(tag.moveValue());
 }
@@ -97,7 +97,7 @@
     }
 
     auto protectedParms = mac->get(kCoseMac0ProtectedParams)->asBstr();
-    auto unprotectedParms = mac->get(kCoseMac0UnprotectedParams)->asBstr();
+    auto unprotectedParms = mac->get(kCoseMac0UnprotectedParams)->asMap();
     auto payload = mac->get(kCoseMac0Payload)->asBstr();
     auto tag = mac->get(kCoseMac0Tag)->asBstr();
     if (!protectedParms || !unprotectedParms || !payload || !tag) {
@@ -115,7 +115,7 @@
     }
 
     auto protectedParms = mac->get(kCoseMac0ProtectedParams)->asBstr();
-    auto unprotectedParms = mac->get(kCoseMac0UnprotectedParams)->asBstr();
+    auto unprotectedParms = mac->get(kCoseMac0UnprotectedParams)->asMap();
     auto payload = mac->get(kCoseMac0Payload)->asBstr();
     auto tag = mac->get(kCoseMac0Tag)->asBstr();
     if (!protectedParms || !unprotectedParms || !payload || !tag) {
@@ -168,7 +168,7 @@
 
     return cppbor::Array()
             .add(protParms)
-            .add(bytevec{} /* unprotected parameters */)
+            .add(cppbor::Map() /* unprotected parameters */)
             .add(payload)
             .add(*signature);
 }
@@ -185,7 +185,7 @@
     }
 
     const cppbor::Bstr* protectedParams = coseSign1->get(kCoseSign1ProtectedParams)->asBstr();
-    const cppbor::Bstr* unprotectedParams = coseSign1->get(kCoseSign1UnprotectedParams)->asBstr();
+    const cppbor::Map* unprotectedParams = coseSign1->get(kCoseSign1UnprotectedParams)->asMap();
     const cppbor::Bstr* payload = coseSign1->get(kCoseSign1Payload)->asBstr();
     const cppbor::Bstr* signature = coseSign1->get(kCoseSign1Signature)->asBstr();
 
diff --git a/security/keymint/support/remote_prov_utils.cpp b/security/keymint/support/remote_prov_utils.cpp
index 111cb30..3e4f3f7 100644
--- a/security/keymint/support/remote_prov_utils.cpp
+++ b/security/keymint/support/remote_prov_utils.cpp
@@ -83,7 +83,7 @@
     }
 
     const cppbor::Bstr* protectedParams = coseSign1->get(kCoseSign1ProtectedParams)->asBstr();
-    const cppbor::Bstr* unprotectedParams = coseSign1->get(kCoseSign1UnprotectedParams)->asBstr();
+    const cppbor::Map* unprotectedParams = coseSign1->get(kCoseSign1UnprotectedParams)->asMap();
     const cppbor::Bstr* payload = coseSign1->get(kCoseSign1Payload)->asBstr();
     const cppbor::Bstr* signature = coseSign1->get(kCoseSign1Signature)->asBstr();
 
diff --git a/security/secureclock/aidl/Android.bp b/security/secureclock/aidl/Android.bp
index c8e5c02..c78be3b 100644
--- a/security/secureclock/aidl/Android.bp
+++ b/security/secureclock/aidl/Android.bp
@@ -16,7 +16,8 @@
     stability: "vintf",
     backend: {
         java: {
-            sdk_version: "module_current",
+            platform_apis: true,
+            srcs_available: true,
         },
         ndk: {
             vndk: {
diff --git a/security/secureclock/aidl/aidl_api/android.hardware.security.secureclock/current/android/hardware/security/secureclock/ISecureClock.aidl b/security/secureclock/aidl/aidl_api/android.hardware.security.secureclock/current/android/hardware/security/secureclock/ISecureClock.aidl
index 3778897..4ecc1e4 100644
--- a/security/secureclock/aidl/aidl_api/android.hardware.security.secureclock/current/android/hardware/security/secureclock/ISecureClock.aidl
+++ b/security/secureclock/aidl/aidl_api/android.hardware.security.secureclock/current/android/hardware/security/secureclock/ISecureClock.aidl
@@ -11,7 +11,8 @@
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * limitations under the License.
- *////////////////////////////////////////////////////////////////////////////////
+ */
+///////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -30,6 +31,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.secureclock;
+/* @hide */
 @VintfStability
 interface ISecureClock {
   android.hardware.security.secureclock.TimeStampToken generateTimeStamp(in long challenge);
diff --git a/security/secureclock/aidl/aidl_api/android.hardware.security.secureclock/current/android/hardware/security/secureclock/TimeStampToken.aidl b/security/secureclock/aidl/aidl_api/android.hardware.security.secureclock/current/android/hardware/security/secureclock/TimeStampToken.aidl
index 00a8bb2..d105ac8 100644
--- a/security/secureclock/aidl/aidl_api/android.hardware.security.secureclock/current/android/hardware/security/secureclock/TimeStampToken.aidl
+++ b/security/secureclock/aidl/aidl_api/android.hardware.security.secureclock/current/android/hardware/security/secureclock/TimeStampToken.aidl
@@ -12,7 +12,8 @@
  * WITHOUT 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -31,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.secureclock;
+/* @hide */
 @RustDerive(Clone=true, Eq=true, Hash=true, Ord=true, PartialEq=true, PartialOrd=true) @VintfStability
 parcelable TimeStampToken {
   long challenge;
diff --git a/security/secureclock/aidl/aidl_api/android.hardware.security.secureclock/current/android/hardware/security/secureclock/Timestamp.aidl b/security/secureclock/aidl/aidl_api/android.hardware.security.secureclock/current/android/hardware/security/secureclock/Timestamp.aidl
index bebeb5c..2e0e389 100644
--- a/security/secureclock/aidl/aidl_api/android.hardware.security.secureclock/current/android/hardware/security/secureclock/Timestamp.aidl
+++ b/security/secureclock/aidl/aidl_api/android.hardware.security.secureclock/current/android/hardware/security/secureclock/Timestamp.aidl
@@ -12,7 +12,8 @@
  * WITHOUT 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -31,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.secureclock;
+/* @hide */
 @RustDerive(Clone=true, Eq=true, Hash=true, Ord=true, PartialEq=true, PartialOrd=true) @VintfStability
 parcelable Timestamp {
   long milliSeconds;
diff --git a/security/secureclock/aidl/android/hardware/security/secureclock/ISecureClock.aidl b/security/secureclock/aidl/android/hardware/security/secureclock/ISecureClock.aidl
index 577dd8f..a742ff0 100644
--- a/security/secureclock/aidl/android/hardware/security/secureclock/ISecureClock.aidl
+++ b/security/secureclock/aidl/android/hardware/security/secureclock/ISecureClock.aidl
@@ -25,8 +25,8 @@
  * secret. The shared secret must be available to secure clock service by implementing
  * ISharedSecret aidl. Note: ISecureClock depends on the shared secret, without which the secure
  * time stamp token cannot be generated.
+ * @hide
  */
-
 @VintfStability
 interface ISecureClock {
     /**
diff --git a/security/secureclock/aidl/android/hardware/security/secureclock/TimeStampToken.aidl b/security/secureclock/aidl/android/hardware/security/secureclock/TimeStampToken.aidl
index dd95732..71b4278 100644
--- a/security/secureclock/aidl/android/hardware/security/secureclock/TimeStampToken.aidl
+++ b/security/secureclock/aidl/android/hardware/security/secureclock/TimeStampToken.aidl
@@ -20,8 +20,8 @@
 
 /**
  * TimeStampToken instances are used for secure environments that requires secure time information.
+ * @hide
  */
-
 @VintfStability
 @RustDerive(Clone=true, Eq=true, PartialEq=true, Ord=true, PartialOrd=true, Hash=true)
 parcelable TimeStampToken {
diff --git a/security/secureclock/aidl/android/hardware/security/secureclock/Timestamp.aidl b/security/secureclock/aidl/android/hardware/security/secureclock/Timestamp.aidl
index 27758e1..5061aa4 100644
--- a/security/secureclock/aidl/android/hardware/security/secureclock/Timestamp.aidl
+++ b/security/secureclock/aidl/android/hardware/security/secureclock/Timestamp.aidl
@@ -21,6 +21,7 @@
  * and a secure environment's notion of "current time" must not repeat until the Android device
  * reboots, or until at least 50 million years have elapsed (note that this requirement is satisfied
  * by setting the clock to zero during each boot, and then counting time accurately).
+ * @hide
  */
 @VintfStability
 @RustDerive(Clone=true, Eq=true, PartialEq=true, Ord=true, PartialOrd=true, Hash=true)
diff --git a/security/sharedsecret/aidl/aidl_api/android.hardware.security.sharedsecret/current/android/hardware/security/sharedsecret/ISharedSecret.aidl b/security/sharedsecret/aidl/aidl_api/android.hardware.security.sharedsecret/current/android/hardware/security/sharedsecret/ISharedSecret.aidl
index 2509936..e76efe7 100644
--- a/security/sharedsecret/aidl/aidl_api/android.hardware.security.sharedsecret/current/android/hardware/security/sharedsecret/ISharedSecret.aidl
+++ b/security/sharedsecret/aidl/aidl_api/android.hardware.security.sharedsecret/current/android/hardware/security/sharedsecret/ISharedSecret.aidl
@@ -1,3 +1,17 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * limitations under the License.
+ */
 ///////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
@@ -17,6 +31,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.sharedsecret;
+/* @hide */
 @VintfStability
 interface ISharedSecret {
   android.hardware.security.sharedsecret.SharedSecretParameters getSharedSecretParameters();
diff --git a/security/sharedsecret/aidl/aidl_api/android.hardware.security.sharedsecret/current/android/hardware/security/sharedsecret/SharedSecretParameters.aidl b/security/sharedsecret/aidl/aidl_api/android.hardware.security.sharedsecret/current/android/hardware/security/sharedsecret/SharedSecretParameters.aidl
index 9b65046..e15fd49 100644
--- a/security/sharedsecret/aidl/aidl_api/android.hardware.security.sharedsecret/current/android/hardware/security/sharedsecret/SharedSecretParameters.aidl
+++ b/security/sharedsecret/aidl/aidl_api/android.hardware.security.sharedsecret/current/android/hardware/security/sharedsecret/SharedSecretParameters.aidl
@@ -1,3 +1,18 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 ///////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
@@ -17,7 +32,8 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.sharedsecret;
-@VintfStability
+/* @hide */
+@RustDerive(Clone=true, Eq=true, Hash=true, Ord=true, PartialEq=true, PartialOrd=true) @VintfStability
 parcelable SharedSecretParameters {
   byte[] seed;
   byte[] nonce;
diff --git a/security/sharedsecret/aidl/android/hardware/security/sharedsecret/ISharedSecret.aidl b/security/sharedsecret/aidl/android/hardware/security/sharedsecret/ISharedSecret.aidl
index 906303f..eca8d87 100644
--- a/security/sharedsecret/aidl/android/hardware/security/sharedsecret/ISharedSecret.aidl
+++ b/security/sharedsecret/aidl/android/hardware/security/sharedsecret/ISharedSecret.aidl
@@ -22,8 +22,8 @@
  * An ISharedSecret enables any service that implements this interface to establish a shared secret
  * with one or more other services such as ISecureClock, TEE IKeymintDevice, StrongBox
  * IKeymintDevice, etc. The shared secret is a 256-bit HMAC key and it is further used to generate
- * secure tokens with integrity protection. There are two steps to establish a shared secret between
- * the collaborating services:
+ * secure tokens with integrity protection. There are three steps to establish a shared secret
+ * between the collaborating services:
  *
  * Step 1: During Android startup the system calls each service that implements this interface to
  * get the shared secret parameters. This is done using getSharedSecretParameters method defined
@@ -35,8 +35,8 @@
  * Step 3: The system collects sharing check hash values from each service and evaluates them. If
  * they are all equal, then the shared secret generation is considered to be successful else it is
  * considered to have failed.
+ * @hide
  */
-
 @VintfStability
 interface ISharedSecret {
     /**
@@ -64,11 +64,11 @@
 
     /**
      * This method is the second and final step in the process for agreeing on a shared key.  It is
-     * called by Android during startup.  The system calls it on each of the keymint services, and
-     * sends to it all of the SharedSecretParameters returned by all keymint services.
+     * called by Android during startup.  The system calls it on each of the HAL instances, and
+     * sends to it all of the SharedSecretParameters returned by all HAL instances.
      *
-     * This method computes the shared 32-byte HMAC key ``H'' as follows (all keymint services
-     * instances perform the same computation to arrive at the same result):
+     * This method computes the shared 32-byte HMAC key ``H'' as follows (all HAL instances perform
+     * the same computation to arrive at the same result):
      *
      *     H = CKDF(key = K,
      *              context = P1 || P2 || ... || Pn,
@@ -98,16 +98,16 @@
      * Note that the label "KeymasterSharedMac" is the 18-byte UTF-8 encoding of the string.
      *
      * @param params is an array of SharedSecretParameters The lexicographically sorted
-     * SharedSecretParameters data returned by all keymint services when getSharedSecretParameters
+     * SharedSecretParameters data returned by all HAL instances when getSharedSecretParameters
      * was called.
      *
-     * @return sharingCheck A 32-byte value used to verify that all the keymint services have
+     * @return sharingCheck A 32-byte value used to verify that all the HAL instances have
      *         computed the same shared HMAC key.  The sharingCheck value is computed as follows:
      *
      *             sharingCheck = HMAC(H, KEY_CHECK_LABEL)
      *
      *         The string is UTF-8 encoded, 27 bytes in length.  If the returned values of all
-     *         keymint services don't match, clients must assume that HMAC agreement
+     *         HAL instances don't match, clients must assume that HMAC agreement
      *         failed.
      */
     byte[] computeSharedSecret(in SharedSecretParameters[] params);
diff --git a/security/sharedsecret/aidl/android/hardware/security/sharedsecret/SharedSecretParameters.aidl b/security/sharedsecret/aidl/android/hardware/security/sharedsecret/SharedSecretParameters.aidl
index 691b3f1..8144699 100644
--- a/security/sharedsecret/aidl/android/hardware/security/sharedsecret/SharedSecretParameters.aidl
+++ b/security/sharedsecret/aidl/android/hardware/security/sharedsecret/SharedSecretParameters.aidl
@@ -21,9 +21,10 @@
  * HMAC key between multiple keymint services.  These parameters are returned in by
  * getSharedSecretParameters() and send to computeShareSecret().  See the named methods in
  * ISharedSecret for details of usage.
+ * @hide
  */
-
 @VintfStability
+@RustDerive(Clone=true, Eq=true, PartialEq=true, Ord=true, PartialOrd=true, Hash=true)
 parcelable SharedSecretParameters {
     /**
      * Either empty or contains a non zero persistent value that is associated with the pre-shared
diff --git a/soundtrigger/2.0/default/OWNERS b/soundtrigger/2.0/default/OWNERS
index 6fdc97c..ed739cf 100644
--- a/soundtrigger/2.0/default/OWNERS
+++ b/soundtrigger/2.0/default/OWNERS
@@ -1,3 +1,3 @@
 elaurent@google.com
-krocard@google.com
 mnaganov@google.com
+ytai@google.com
diff --git a/tv/input/1.0/vts/functional/VtsHalTvInputV1_0TargetTest.cpp b/tv/input/1.0/vts/functional/VtsHalTvInputV1_0TargetTest.cpp
index 8092d5e..15ea3e9 100644
--- a/tv/input/1.0/vts/functional/VtsHalTvInputV1_0TargetTest.cpp
+++ b/tv/input/1.0/vts/functional/VtsHalTvInputV1_0TargetTest.cpp
@@ -313,6 +313,9 @@
     tv_input_->openStream(device_id, stream_id,
                           [&result](Result res, const native_handle_t*) { result = res; });
     EXPECT_EQ(Result::INVALID_STATE, result);
+
+    // close stream as subsequent tests assume no open streams
+    EXPECT_EQ(Result::OK, tv_input_->closeStream(device_id, stream_id));
 }
 
 /*
diff --git a/wifi/1.5/Android.bp b/wifi/1.5/Android.bp
index 7c04c69..0887c6b 100644
--- a/wifi/1.5/Android.bp
+++ b/wifi/1.5/Android.bp
@@ -20,6 +20,7 @@
         "IWifiNanIface.hal",
         "IWifiNanIfaceEventCallback.hal",
         "IWifiStaIface.hal",
+        "IWifiEventCallback.hal",
     ],
     interfaces: [
         "android.hardware.wifi@1.0",
diff --git a/wifi/1.5/IWifi.hal b/wifi/1.5/IWifi.hal
index 66d0a9c..28b808e 100644
--- a/wifi/1.5/IWifi.hal
+++ b/wifi/1.5/IWifi.hal
@@ -17,6 +17,8 @@
 package android.hardware.wifi@1.5;
 
 import @1.4::IWifi;
+import IWifiEventCallback;
+import @1.0::WifiStatus;
 
 /**
  * This is the root of the HAL module and is the interface returned when
@@ -24,4 +26,21 @@
  * module loaded in the system.
  * IWifi.getChip() must return @1.5::IWifiChip
  */
-interface IWifi extends @1.4::IWifi {};
+interface IWifi extends @1.4::IWifi {
+  /**
+   * Requests notifications of significant events for the HAL. Multiple calls to
+   * this must register multiple callbacks each of which must receive all
+   * events. |IWifiEventCallback| object registration must be independent of the
+   * state of the rest of the HAL and must persist though stops/starts. These
+   * objects must be deleted when the corresponding client process is dead.
+   *
+   * @param callback An instance of the |IWifiEventCallback| HIDL interface
+   *        object.
+   * @return status WifiStatus of the operation.
+   *         Possible status codes:
+   *         |WifiStatusCode.SUCCESS|,
+   *         |WifiStatusCode.UNKNOWN|
+   */
+  registerEventCallback_1_5(IWifiEventCallback callback)
+      generates (WifiStatus status);
+};
diff --git a/wifi/1.5/IWifiChip.hal b/wifi/1.5/IWifiChip.hal
index 5a3e288..e199850 100644
--- a/wifi/1.5/IWifiChip.hal
+++ b/wifi/1.5/IWifiChip.hal
@@ -303,4 +303,25 @@
     getUsableChannels(WifiBand band, bitfield<WifiIfaceMode> ifaceModeMask,
             bitfield<UsableChannelFilter> filterMask)
         generates (WifiStatus status, vec<WifiUsableChannel> channels);
+
+    /**
+     * Trigger subsystem restart
+     *
+     * If the framework detects a problem (e.g. connection failure),
+     * it must call this function to attempt recovery.
+     *
+     * When the wifi HAL receiveds triggerSubsystemRestart(), it must restart
+     * the wlan subsystem, especially the wlan firmware.
+     *
+     * Regarding the callback function for subsystem restart, refer to documentation of
+     * |IWifiEventCallback.onSubsystemRestart| for details.
+     *
+     * @return status WifiStatus of the operation.
+     *         Possible status codes:
+     *         |WifiStatusCode.SUCCESS|,
+     *         |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|,
+     *         |WifiStatusCode.ERROR_NOT_AVAILABLE|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    triggerSubsystemRestart() generates (WifiStatus status);
 };
diff --git a/wifi/1.5/IWifiEventCallback.hal b/wifi/1.5/IWifiEventCallback.hal
new file mode 100644
index 0000000..ff27630
--- /dev/null
+++ b/wifi/1.5/IWifiEventCallback.hal
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi@1.5;
+
+import @1.0::IWifiEventCallback;
+import @1.0::WifiStatus;
+
+interface IWifiEventCallback extends @1.0::IWifiEventCallback {
+  /**
+    * Must be called when the Wi-Fi subsystem restart completes.
+    * Once this event is received, framework must fully reset the Wi-Fi stack state.
+    */
+  oneway onSubsystemRestart(WifiStatus status);
+};
diff --git a/wifi/1.5/default/wifi.cpp b/wifi/1.5/default/wifi.cpp
index da98db8..b9f20a4 100644
--- a/wifi/1.5/default/wifi.cpp
+++ b/wifi/1.5/default/wifi.cpp
@@ -50,13 +50,21 @@
 }
 
 Return<void> Wifi::registerEventCallback(
-    const sp<IWifiEventCallback>& event_callback,
+    const sp<V1_0::IWifiEventCallback>& event_callback,
     registerEventCallback_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN,
                            &Wifi::registerEventCallbackInternal, hidl_status_cb,
                            event_callback);
 }
 
+Return<void> Wifi::registerEventCallback_1_5(
+    const sp<V1_5::IWifiEventCallback>& event_callback,
+    registerEventCallback_1_5_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN,
+                           &Wifi::registerEventCallbackInternal_1_5,
+                           hidl_status_cb, event_callback);
+}
+
 Return<bool> Wifi::isStarted() { return run_state_ != RunState::STOPPED; }
 
 Return<void> Wifi::start(start_cb hidl_status_cb) {
@@ -95,7 +103,13 @@
 }
 
 WifiStatus Wifi::registerEventCallbackInternal(
-    const sp<IWifiEventCallback>& event_callback) {
+    const sp<V1_0::IWifiEventCallback>& event_callback __unused) {
+    // Deprecated support for this callback.
+    return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
+}
+
+WifiStatus Wifi::registerEventCallbackInternal_1_5(
+    const sp<V1_5::IWifiEventCallback>& event_callback) {
     if (!event_cb_handler_.addCallback(event_callback)) {
         return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
     }
@@ -117,7 +131,7 @@
                 WifiStatus wifi_status =
                     createWifiStatus(WifiStatusCode::ERROR_UNKNOWN, error);
                 for (const auto& callback : event_cb_handler_.getCallbacks()) {
-                    if (!callback->onFailure(wifi_status).isOk()) {
+                    if (!callback->onSubsystemRestart(wifi_status).isOk()) {
                         LOG(ERROR) << "Failed to invoke onFailure callback";
                     }
                 }
diff --git a/wifi/1.5/default/wifi.h b/wifi/1.5/default/wifi.h
index 825c0bc..840bdfd 100644
--- a/wifi/1.5/default/wifi.h
+++ b/wifi/1.5/default/wifi.h
@@ -52,8 +52,11 @@
 
     // HIDL methods exposed.
     Return<void> registerEventCallback(
-        const sp<IWifiEventCallback>& event_callback,
+        const sp<V1_0::IWifiEventCallback>& event_callback,
         registerEventCallback_cb hidl_status_cb) override;
+    Return<void> registerEventCallback_1_5(
+        const sp<V1_5::IWifiEventCallback>& event_callback,
+        registerEventCallback_1_5_cb hidl_status_cb) override;
     Return<bool> isStarted() override;
     Return<void> start(start_cb hidl_status_cb) override;
     Return<void> stop(stop_cb hidl_status_cb) override;
@@ -67,7 +70,9 @@
 
     // Corresponding worker functions for the HIDL methods.
     WifiStatus registerEventCallbackInternal(
-        const sp<IWifiEventCallback>& event_callback);
+        const sp<V1_0::IWifiEventCallback>& event_callback __unused);
+    WifiStatus registerEventCallbackInternal_1_5(
+        const sp<V1_5::IWifiEventCallback>& event_callback);
     WifiStatus startInternal();
     WifiStatus stopInternal(std::unique_lock<std::recursive_mutex>* lock);
     std::pair<WifiStatus, std::vector<ChipId>> getChipIdsInternal();
@@ -87,7 +92,7 @@
     std::shared_ptr<feature_flags::WifiFeatureFlags> feature_flags_;
     RunState run_state_;
     std::vector<sp<WifiChip>> chips_;
-    hidl_callback_util::HidlCallbackHandler<IWifiEventCallback>
+    hidl_callback_util::HidlCallbackHandler<V1_5::IWifiEventCallback>
         event_cb_handler_;
 
     DISALLOW_COPY_AND_ASSIGN(Wifi);
diff --git a/wifi/1.5/default/wifi_chip.cpp b/wifi/1.5/default/wifi_chip.cpp
index 0499f45..961f9da 100644
--- a/wifi/1.5/default/wifi_chip.cpp
+++ b/wifi/1.5/default/wifi_chip.cpp
@@ -747,6 +747,13 @@
                            ifaceModeMask, filterMask);
 }
 
+Return<void> WifiChip::triggerSubsystemRestart(
+    triggerSubsystemRestart_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+                           &WifiChip::triggerSubsystemRestartInternal,
+                           hidl_status_cb);
+}
+
 void WifiChip::invalidateAndRemoveAllIfaces() {
     invalidateAndClearBridgedApAll();
     invalidateAndClearAll(ap_ifaces_);
@@ -1522,6 +1529,11 @@
     return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_usable_channels};
 }
 
+WifiStatus WifiChip::triggerSubsystemRestartInternal() {
+    auto legacy_status = legacy_hal_.lock()->triggerSubsystemRestart();
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
 WifiStatus WifiChip::handleChipConfiguration(
     /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock,
     ChipModeId mode_id) {
diff --git a/wifi/1.5/default/wifi_chip.h b/wifi/1.5/default/wifi_chip.h
index 92d639f..bd40ead 100644
--- a/wifi/1.5/default/wifi_chip.h
+++ b/wifi/1.5/default/wifi_chip.h
@@ -184,6 +184,8 @@
         WifiBand band, hidl_bitfield<WifiIfaceMode> ifaceModeMask,
         hidl_bitfield<UsableChannelFilter> filterMask,
         getUsableChannels_cb _hidl_cb) override;
+    Return<void> triggerSubsystemRestart(
+        triggerSubsystemRestart_cb hidl_status_cb) override;
 
    private:
     void invalidateAndRemoveAllIfaces();
@@ -303,6 +305,7 @@
     void invalidateAndClearBridgedApAll();
     void invalidateAndClearBridgedAp(const std::string& br_name);
     bool findUsingNameFromBridgedApInstances(const std::string& name);
+    WifiStatus triggerSubsystemRestartInternal();
 
     ChipId chip_id_;
     std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
diff --git a/wifi/1.5/default/wifi_legacy_hal.cpp b/wifi/1.5/default/wifi_legacy_hal.cpp
index 45ad84b..848fbd6 100644
--- a/wifi/1.5/default/wifi_legacy_hal.cpp
+++ b/wifi/1.5/default/wifi_legacy_hal.cpp
@@ -1676,6 +1676,10 @@
     return {status, std::move(channels)};
 }
 
+wifi_error WifiLegacyHal::triggerSubsystemRestart() {
+    return global_func_table_.wifi_trigger_subsystem_restart();
+}
+
 void WifiLegacyHal::invalidate() {
     global_handle_ = nullptr;
     iface_name_to_handle_.clear();
diff --git a/wifi/1.5/default/wifi_legacy_hal.h b/wifi/1.5/default/wifi_legacy_hal.h
index 8ebc66a..2bb7631 100644
--- a/wifi/1.5/default/wifi_legacy_hal.h
+++ b/wifi/1.5/default/wifi_legacy_hal.h
@@ -716,6 +716,8 @@
     std::pair<wifi_error, std::vector<wifi_usable_channel>> getUsableChannels(
         uint32_t band_mask, uint32_t iface_mode_mask, uint32_t filter_mask);
 
+    wifi_error triggerSubsystemRestart();
+
    private:
     // Retrieve interface handles for all the available interfaces.
     wifi_error retrieveIfaceHandles();
diff --git a/wifi/1.5/default/wifi_legacy_hal_stubs.cpp b/wifi/1.5/default/wifi_legacy_hal_stubs.cpp
index 6212960..dd860d6 100644
--- a/wifi/1.5/default/wifi_legacy_hal_stubs.cpp
+++ b/wifi/1.5/default/wifi_legacy_hal_stubs.cpp
@@ -160,6 +160,7 @@
     populateStubFor(&hal_fn->wifi_twt_clear_stats);
     populateStubFor(&hal_fn->wifi_set_dtim_config);
     populateStubFor(&hal_fn->wifi_get_usable_channels);
+    populateStubFor(&hal_fn->wifi_trigger_subsystem_restart);
     return true;
 }
 }  // namespace legacy_hal