Merge "Fix 1.5::WifiBand inheritance"
diff --git a/audio/7.0/IDevice.hal b/audio/7.0/IDevice.hal
index d9e0ad2..e423f29 100644
--- a/audio/7.0/IDevice.hal
+++ b/audio/7.0/IDevice.hal
@@ -174,6 +174,9 @@
      * Creates an audio patch between several source and sink ports.  The handle
      * is allocated by the HAL and must be unique for this audio HAL module.
      *
+     * Optional method. HAL must support it if 'supportsAudioPatches' returns
+     * 'true'.
+     *
      * @param sources patch sources.
      * @param sinks patch sinks.
      * @return retval operation completion status.
@@ -189,6 +192,9 @@
      * as the HAL module can figure out a way of switching the route without
      * causing audio disruption.
      *
+     * Optional method. HAL must support it if 'supportsAudioPatches' returns
+     * 'true'.
+     *
      * @param previousPatch handle of the previous patch to update.
      * @param sources new patch sources.
      * @param sinks new patch sinks.
@@ -204,6 +210,9 @@
     /**
      * Release an audio patch.
      *
+     * Optional method. HAL must support it if 'supportsAudioPatches' returns
+     * 'true'.
+     *
      * @param patch patch handle.
      * @return retval operation completion status.
      */
diff --git a/audio/core/all-versions/default/Android.bp b/audio/core/all-versions/default/Android.bp
index e0f0860..c75c779 100644
--- a/audio/core/all-versions/default/Android.bp
+++ b/audio/core/all-versions/default/Android.bp
@@ -51,6 +51,7 @@
         "libaudio_system_headers",
         "libhardware_headers",
         "libmedia_headers",
+        "libmediautils_headers",
     ],
 
     export_header_lib_headers: [
diff --git a/audio/core/all-versions/default/Device.cpp b/audio/core/all-versions/default/Device.cpp
index 05c1066..7caed44 100644
--- a/audio/core/all-versions/default/Device.cpp
+++ b/audio/core/all-versions/default/Device.cpp
@@ -325,11 +325,17 @@
         const hidl_vec<AudioPortConfig>& sinks) {
     Result retval(Result::NOT_SUPPORTED);
     if (version() >= AUDIO_DEVICE_API_VERSION_3_0) {
-        std::unique_ptr<audio_port_config[]> halSources;
-        HidlUtils::audioPortConfigsToHal(sources, &halSources);
-        std::unique_ptr<audio_port_config[]> halSinks;
-        HidlUtils::audioPortConfigsToHal(sinks, &halSinks);
         audio_patch_handle_t halPatch = static_cast<audio_patch_handle_t>(patch);
+        std::unique_ptr<audio_port_config[]> halSources;
+        if (status_t status = HidlUtils::audioPortConfigsToHal(sources, &halSources);
+            status != NO_ERROR) {
+            return {analyzeStatus("audioPortConfigsToHal;sources", status), patch};
+        }
+        std::unique_ptr<audio_port_config[]> halSinks;
+        if (status_t status = HidlUtils::audioPortConfigsToHal(sinks, &halSinks);
+            status != NO_ERROR) {
+            return {analyzeStatus("audioPortConfigsToHal;sinks", status), patch};
+        }
         retval = analyzeStatus("create_audio_patch",
                                mDevice->create_audio_patch(mDevice, sources.size(), &halSources[0],
                                                            sinks.size(), &halSinks[0], &halPatch));
@@ -364,7 +370,10 @@
 Return<Result> Device::setAudioPortConfig(const AudioPortConfig& config) {
     if (version() >= AUDIO_DEVICE_API_VERSION_3_0) {
         struct audio_port_config halPortConfig;
-        HidlUtils::audioPortConfigToHal(config, &halPortConfig);
+        if (status_t status = HidlUtils::audioPortConfigToHal(config, &halPortConfig);
+            status != NO_ERROR) {
+            return analyzeStatus("audioPortConfigToHal", status);
+        }
         return analyzeStatus("set_audio_port_config",
                              mDevice->set_audio_port_config(mDevice, &halPortConfig));
     }
diff --git a/audio/core/all-versions/default/StreamOut.cpp b/audio/core/all-versions/default/StreamOut.cpp
index ffd3b6b..357fd94 100644
--- a/audio/core/all-versions/default/StreamOut.cpp
+++ b/audio/core/all-versions/default/StreamOut.cpp
@@ -163,7 +163,7 @@
         status_t status = EventFlag::deleteEventFlag(&mEfGroup);
         ALOGE_IF(status, "write MQ event flag deletion error: %s", strerror(-status));
     }
-    mCallback.clear();
+    mCallback = nullptr;
 #if MAJOR_VERSION <= 5
     mDevice->closeOutputStream(mStream);
     // Closing the output stream in the HAL waits for the callback to finish,
@@ -462,7 +462,7 @@
 
 Return<Result> StreamOut::clearCallback() {
     if (mStream->set_callback == NULL) return Result::NOT_SUPPORTED;
-    mCallback.clear();
+    mCallback = nullptr;
     return Result::OK;
 }
 
@@ -477,7 +477,7 @@
     // It's correct to hold an sp<> to callback because the reference
     // in the StreamOut instance can be cleared in the meantime. There is
     // no difference on which thread to run IStreamOutCallback's destructor.
-    sp<IStreamOutCallback> callback = self->mCallback;
+    sp<IStreamOutCallback> callback = self->mCallback.load();
     if (callback.get() == nullptr) return 0;
     ALOGV("asyncCallback() event %d", event);
     Return<void> result;
@@ -698,7 +698,7 @@
 // static
 int StreamOut::asyncEventCallback(stream_event_callback_type_t event, void* param, void* cookie) {
     StreamOut* self = reinterpret_cast<StreamOut*>(cookie);
-    sp<IStreamOutEventCallback> eventCallback = self->mEventCallback;
+    sp<IStreamOutEventCallback> eventCallback = self->mEventCallback.load();
     if (eventCallback.get() == nullptr) return 0;
     ALOGV("%s event %d", __func__, event);
     Return<void> result;
diff --git a/audio/core/all-versions/default/include/core/default/StreamOut.h b/audio/core/all-versions/default/include/core/default/StreamOut.h
index b8e8515..02d8e89 100644
--- a/audio/core/all-versions/default/include/core/default/StreamOut.h
+++ b/audio/core/all-versions/default/include/core/default/StreamOut.h
@@ -29,6 +29,7 @@
 #include <fmq/MessageQueue.h>
 #include <hidl/MQDescriptor.h>
 #include <hidl/Status.h>
+#include <mediautils/Synchronization.h>
 #include <utils/Thread.h>
 
 namespace android {
@@ -158,9 +159,9 @@
     audio_stream_out_t* mStream;
     const sp<Stream> mStreamCommon;
     const sp<StreamMmap<audio_stream_out_t>> mStreamMmap;
-    sp<IStreamOutCallback> mCallback;  // Callback for non-blocking write and drain
+    mediautils::atomic_sp<IStreamOutCallback> mCallback;  // for non-blocking write and drain
 #if MAJOR_VERSION >= 6
-    sp<IStreamOutEventCallback> mEventCallback;
+    mediautils::atomic_sp<IStreamOutEventCallback> mEventCallback;
 #endif
     std::unique_ptr<CommandMQ> mCommandMQ;
     std::unique_ptr<DataMQ> mDataMQ;
diff --git a/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp b/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp
index 94fa92a..0f0cdcf 100644
--- a/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp
@@ -116,75 +116,33 @@
 }
 #endif  // MAJOR_VERSION <= 6
 
-class SingleOutputConfigTest : public AudioHidlTestWithDeviceConfigParameter {};
-TEST_P(SingleOutputConfigTest, CloseDeviceWithOpenedOutputStreams) {
+class SingleConfigOutputStreamTest : public OutputStreamTest {};
+TEST_P(SingleConfigOutputStreamTest, CloseDeviceWithOpenedOutputStreams) {
     doc::test("Verify that a device can't be closed if there are output streams opened");
-#if MAJOR_VERSION <= 6
-    DeviceAddress address{.device = AudioDevice::OUT_DEFAULT};
-    SourceMetadata initMetadata = {{{AudioUsage::MEDIA, AudioContentType::MUSIC, 1 /* gain */}}};
-#elif MAJOR_VERSION >= 7
-    DeviceAddress address{.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_OUT_DEFAULT)};
-    SourceMetadata initMetadata = {{{toString(xsd::AudioUsage::AUDIO_USAGE_MEDIA),
-                                     toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_MUSIC),
-                                     {} /* tags */,
-                                     toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO),
-                                     1 /* gain */}}};
-#endif
-    const AudioConfig& config = getConfig();
-    auto flags = getOutputFlags();
-    sp<IStreamOut> stream;
-    StreamHelper<IStreamOut> helper(stream);
-    AudioConfig suggestedConfig{};
-    ASSERT_NO_FATAL_FAILURE(helper.open(
-            [&](AudioIoHandle handle, AudioConfig config, auto cb) {
-                return getDevice()->openOutputStream(handle, address, config, flags, initMetadata,
-                                                     cb);
-            },
-            config, &res, &suggestedConfig));
+    // Opening of the stream is done in SetUp.
     ASSERT_RESULT(Result::INVALID_STATE, getDevice()->close());
-    ASSERT_NO_FATAL_FAILURE(helper.close(true /*clear*/, &res));
+    ASSERT_OK(closeStream(true /*clear*/));
     ASSERT_OK(getDevice()->close());
     ASSERT_TRUE(resetDevice());
 }
-INSTANTIATE_TEST_CASE_P(SingleOutputConfig, SingleOutputConfigTest,
+INSTANTIATE_TEST_CASE_P(SingleConfigOutputStream, SingleConfigOutputStreamTest,
                         ::testing::ValuesIn(getOutputDeviceSingleConfigParameters()),
                         &DeviceConfigParameterToString);
-GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SingleOutputConfig);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SingleConfigOutputStream);
 
-class SingleInputConfigTest : public AudioHidlTestWithDeviceConfigParameter {};
-TEST_P(SingleInputConfigTest, CloseDeviceWithOpenedInputStreams) {
+class SingleConfigInputStreamTest : public InputStreamTest {};
+TEST_P(SingleConfigInputStreamTest, CloseDeviceWithOpenedInputStreams) {
     doc::test("Verify that a device can't be closed if there are input streams opened");
-#if MAJOR_VERSION <= 6
-    DeviceAddress address{.device = AudioDevice::IN_DEFAULT};
-    SinkMetadata initMetadata = {{{.source = AudioSource::MIC, .gain = 1}}};
-#elif MAJOR_VERSION >= 7
-    DeviceAddress address{.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_IN_DEFAULT)};
-    SinkMetadata initMetadata = {
-            {{.source = toString(xsd::AudioSource::AUDIO_SOURCE_MIC),
-              .gain = 1,
-              .tags = {},
-              .channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_IN_MONO)}}};
-#endif
-    const AudioConfig& config = getConfig();
-    auto flags = getInputFlags();
-    sp<IStreamIn> stream;
-    StreamHelper<IStreamIn> helper(stream);
-    AudioConfig suggestedConfig{};
-    ASSERT_NO_FATAL_FAILURE(helper.open(
-            [&](AudioIoHandle handle, AudioConfig config, auto cb) {
-                return getDevice()->openInputStream(handle, address, config, flags, initMetadata,
-                                                    cb);
-            },
-            config, &res, &suggestedConfig));
+    // Opening of the stream is done in SetUp.
     ASSERT_RESULT(Result::INVALID_STATE, getDevice()->close());
-    ASSERT_NO_FATAL_FAILURE(helper.close(true /*clear*/, &res));
+    ASSERT_OK(closeStream(true /*clear*/));
     ASSERT_OK(getDevice()->close());
     ASSERT_TRUE(resetDevice());
 }
-INSTANTIATE_TEST_CASE_P(SingleInputConfig, SingleInputConfigTest,
+INSTANTIATE_TEST_CASE_P(SingleConfigInputStream, SingleConfigInputStreamTest,
                         ::testing::ValuesIn(getInputDeviceSingleConfigParameters()),
                         &DeviceConfigParameterToString);
-GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SingleInputConfig);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SingleConfigInputStream);
 
 TEST_P(AudioPatchHidlTest, UpdatePatchInvalidHandle) {
     doc::test("Verify that passing an invalid handle to updateAudioPatch is checked");
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 3b6d5f2..ef4daba 100644
--- a/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp
@@ -298,6 +298,166 @@
         &DeviceConfigParameterToString);
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(InputBufferSizeInvalidConfig);
 
+static const DeviceAddress& getValidInputDeviceAddress() {
+    static const DeviceAddress valid = {
+            .deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_IN_DEFAULT)};
+    return valid;
+}
+
+static const DeviceAddress& getValidOutputDeviceAddress() {
+    static const DeviceAddress valid = {
+            .deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_OUT_DEFAULT)};
+    return valid;
+}
+
+static const DeviceAddress& getInvalidDeviceAddress() {
+    static const DeviceAddress valid = {.deviceType = "random_string"};
+    return valid;
+}
+
+TEST_P(AudioHidlDeviceTest, SetConnectedStateInvalidDeviceAddress) {
+    doc::test("Check that invalid device address is rejected by IDevice::setConnectedState");
+    EXPECT_RESULT(Result::INVALID_ARGUMENTS,
+                  getDevice()->setConnectedState(getInvalidDeviceAddress(), true));
+    EXPECT_RESULT(Result::INVALID_ARGUMENTS,
+                  getDevice()->setConnectedState(getInvalidDeviceAddress(), false));
+}
+
+static std::vector<AudioPortConfig>& generatePortConfigs(bool valid) {
+    enum {  // Note: This is for convenience when deriving "invalid" configs from "valid".
+        PORT_CONF_MINIMAL,
+        PORT_CONF_WITH_GAIN,
+        PORT_CONF_EXT_DEVICE,
+        PORT_CONF_EXT_MIX_SOURCE,
+        PORT_CONF_EXT_MIX_SINK,
+        PORT_CONF_EXT_SESSION
+    };
+    static std::vector<AudioPortConfig> valids = [] {
+        std::vector<AudioPortConfig> result;
+        result.reserve(PORT_CONF_EXT_SESSION + 1);
+        result.push_back(AudioPortConfig{});
+        AudioPortConfig configWithGain{};
+        configWithGain.gain.config(AudioGainConfig{
+                .index = 0,
+                .mode = {toString(xsd::AudioGainMode::AUDIO_GAIN_MODE_JOINT)},
+                .channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_MONO),
+                .rampDurationMs = 1});
+        configWithGain.gain.config().values.resize(1);
+        configWithGain.gain.config().values[0] = 1000;
+        result.push_back(std::move(configWithGain));
+        AudioPortConfig configWithPortExtDevice{};
+        configWithPortExtDevice.ext.device(getValidOutputDeviceAddress());
+        result.push_back(std::move(configWithPortExtDevice));
+        AudioPortConfig configWithPortExtMixSource{};
+        configWithPortExtMixSource.ext.mix({});
+        configWithPortExtMixSource.ext.mix().useCase.stream(
+                toString(xsd::AudioStreamType::AUDIO_STREAM_VOICE_CALL));
+        result.push_back(std::move(configWithPortExtMixSource));
+        AudioPortConfig configWithPortExtMixSink{};
+        configWithPortExtMixSink.ext.mix({});
+        configWithPortExtMixSink.ext.mix().useCase.source(
+                toString(xsd::AudioSource::AUDIO_SOURCE_DEFAULT));
+        result.push_back(std::move(configWithPortExtMixSink));
+        AudioPortConfig configWithPortExtSession{};
+        configWithPortExtSession.ext.session(
+                static_cast<AudioSession>(AudioSessionConsts::OUTPUT_MIX));
+        result.push_back(std::move(configWithPortExtSession));
+        return result;
+    }();
+    static std::vector<AudioPortConfig> invalids = [&] {
+        std::vector<AudioPortConfig> result;
+        AudioPortConfig invalidBaseChannelMask = valids[PORT_CONF_MINIMAL];
+        invalidBaseChannelMask.base.channelMask = "random_string";
+        result.push_back(std::move(invalidBaseChannelMask));
+        AudioPortConfig invalidBaseFormat = valids[PORT_CONF_MINIMAL];
+        invalidBaseFormat.base.format = "random_string";
+        result.push_back(std::move(invalidBaseFormat));
+        AudioPortConfig invalidGainMode = valids[PORT_CONF_WITH_GAIN];
+        invalidGainMode.gain.config().mode = {{"random_string"}};
+        result.push_back(std::move(invalidGainMode));
+        AudioPortConfig invalidGainChannelMask = valids[PORT_CONF_WITH_GAIN];
+        invalidGainChannelMask.gain.config().channelMask = "random_string";
+        result.push_back(std::move(invalidGainChannelMask));
+        AudioPortConfig invalidDeviceType = valids[PORT_CONF_EXT_DEVICE];
+        invalidDeviceType.ext.device().deviceType = "random_string";
+        result.push_back(std::move(invalidDeviceType));
+        AudioPortConfig invalidStreamType = valids[PORT_CONF_EXT_MIX_SOURCE];
+        invalidStreamType.ext.mix().useCase.stream() = "random_string";
+        result.push_back(std::move(invalidStreamType));
+        AudioPortConfig invalidSource = valids[PORT_CONF_EXT_MIX_SINK];
+        invalidSource.ext.mix().useCase.source() = "random_string";
+        result.push_back(std::move(invalidSource));
+        return result;
+    }();
+    return valid ? valids : invalids;
+}
+
+TEST_P(AudioHidlDeviceTest, SetAudioPortConfigInvalidArguments) {
+    doc::test("Check that invalid port configs are rejected by IDevice::setAudioPortConfig");
+    for (const auto& invalidConfig : generatePortConfigs(false /*valid*/)) {
+        EXPECT_RESULT(invalidArgsOrNotSupported, getDevice()->setAudioPortConfig(invalidConfig))
+                << ::testing::PrintToString(invalidConfig);
+    }
+}
+
+TEST_P(AudioPatchHidlTest, CreatePatchInvalidArguments) {
+    doc::test("Check that invalid port configs are rejected by IDevice::createAudioPatch");
+    // Note that HAL actually might reject the proposed source / sink combo
+    // due to other reasons than presence of invalid enum-strings.
+    // TODO: Come up with a way to guarantee validity of a source / sink combo.
+    for (const auto& validSource : generatePortConfigs(true /*valid*/)) {
+        for (const auto& invalidSink : generatePortConfigs(false /*valid*/)) {
+            AudioPatchHandle handle;
+            EXPECT_OK(getDevice()->createAudioPatch(hidl_vec<AudioPortConfig>{validSource},
+                                                    hidl_vec<AudioPortConfig>{invalidSink},
+                                                    returnIn(res, handle)));
+            EXPECT_EQ(Result::INVALID_ARGUMENTS, res)
+                    << "Source: " << ::testing::PrintToString(validSource)
+                    << "; Sink: " << ::testing::PrintToString(invalidSink);
+        }
+    }
+    for (const auto& validSink : generatePortConfigs(true /*valid*/)) {
+        for (const auto& invalidSource : generatePortConfigs(false /*valid*/)) {
+            AudioPatchHandle handle;
+            EXPECT_OK(getDevice()->createAudioPatch(hidl_vec<AudioPortConfig>{invalidSource},
+                                                    hidl_vec<AudioPortConfig>{validSink},
+                                                    returnIn(res, handle)));
+            EXPECT_EQ(Result::INVALID_ARGUMENTS, res)
+                    << "Source: " << ::testing::PrintToString(invalidSource)
+                    << "; Sink: " << ::testing::PrintToString(validSink);
+        }
+    }
+}
+
+TEST_P(AudioPatchHidlTest, UpdatePatchInvalidArguments) {
+    doc::test("Check that invalid port configs are rejected by IDevice::updateAudioPatch");
+    // Note that HAL actually might reject the proposed source / sink combo
+    // due to other reasons than presence of invalid enum-strings.
+    // TODO: Come up with a way to guarantee validity of a source / sink combo.
+    for (const auto& validSource : generatePortConfigs(true /*valid*/)) {
+        for (const auto& invalidSink : generatePortConfigs(false /*valid*/)) {
+            AudioPatchHandle handle{};
+            EXPECT_OK(getDevice()->updateAudioPatch(handle, hidl_vec<AudioPortConfig>{validSource},
+                                                    hidl_vec<AudioPortConfig>{invalidSink},
+                                                    returnIn(res, handle)));
+            EXPECT_EQ(Result::INVALID_ARGUMENTS, res)
+                    << "Source: " << ::testing::PrintToString(validSource)
+                    << "; Sink: " << ::testing::PrintToString(invalidSink);
+        }
+    }
+    for (const auto& validSink : generatePortConfigs(true /*valid*/)) {
+        for (const auto& invalidSource : generatePortConfigs(false /*valid*/)) {
+            AudioPatchHandle handle{};
+            EXPECT_OK(getDevice()->updateAudioPatch(
+                    handle, hidl_vec<AudioPortConfig>{invalidSource},
+                    hidl_vec<AudioPortConfig>{validSink}, returnIn(res, handle)));
+            EXPECT_EQ(Result::INVALID_ARGUMENTS, res)
+                    << "Source: " << ::testing::PrintToString(invalidSource)
+                    << "; Sink: " << ::testing::PrintToString(validSink);
+        }
+    }
+}
+
 enum { PARAM_DEVICE_CONFIG, PARAM_ADDRESS, PARAM_METADATA };
 enum { INDEX_SINK, INDEX_SOURCE };
 using SinkOrSourceMetadata = std::variant<SinkMetadata, SourceMetadata>;
@@ -349,23 +509,6 @@
     }
 };
 
-static const DeviceAddress& getValidInputDeviceAddress() {
-    static const DeviceAddress valid = {
-            .deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_IN_DEFAULT)};
-    return valid;
-}
-
-static const DeviceAddress& getValidOutputDeviceAddress() {
-    static const DeviceAddress valid = {
-            .deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_OUT_DEFAULT)};
-    return valid;
-}
-
-static const DeviceAddress& getInvalidDeviceAddress() {
-    static const DeviceAddress valid = {.deviceType = "random_string"};
-    return valid;
-}
-
 static const RecordTrackMetadata& getValidRecordTrackMetadata() {
     static const RecordTrackMetadata valid = {
             .source = toString(xsd::AudioSource::AUDIO_SOURCE_DEFAULT), .gain = 1};
@@ -567,7 +710,40 @@
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(OutputStreamInvalidAddress);
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(OutputStreamInvalidMetadata);
 
-TEST_P(OutputStreamTest, UpdateInvalidSourceMetadata) {
+#define TEST_SINGLE_CONFIG_IO_STREAM(test_name, documentation, code) \
+    TEST_P(SingleConfigInputStreamTest, test_name) {                 \
+        doc::test(documentation);                                    \
+        code;                                                        \
+    }                                                                \
+    TEST_P(SingleConfigOutputStreamTest, test_name) {                \
+        doc::test(documentation);                                    \
+        code;                                                        \
+    }
+
+static void testSetDevicesInvalidDeviceAddress(IStream* stream) {
+    ASSERT_RESULT(Result::INVALID_ARGUMENTS, stream->setDevices({getInvalidDeviceAddress()}));
+}
+TEST_SINGLE_CONFIG_IO_STREAM(
+        SetDevicesInvalidDeviceAddress,
+        "Verify that invalid device address is rejected by IStream::setDevices",
+        areAudioPatchesSupported() ? doc::partialTest("Audio patches are supported")
+                                   : testSetDevicesInvalidDeviceAddress(stream.get()));
+
+static void testSetAudioPropertiesInvalidArguments(IStream* stream, const AudioConfigBase& base) {
+    AudioConfigBase invalidFormat = base;
+    invalidFormat.format = "random_string";
+    ASSERT_RESULT(invalidArgsOrNotSupported, stream->setAudioProperties(invalidFormat));
+
+    AudioConfigBase invalidChannelMask = base;
+    invalidChannelMask.channelMask = "random_string";
+    ASSERT_RESULT(invalidArgsOrNotSupported, stream->setAudioProperties(invalidChannelMask));
+}
+TEST_SINGLE_CONFIG_IO_STREAM(
+        SetAudioPropertiesInvalidArguments,
+        "Verify that invalid arguments are rejected by IStream::setAudioProperties",
+        testSetAudioPropertiesInvalidArguments(stream.get(), audioConfig.base));
+
+TEST_P(SingleConfigOutputStreamTest, UpdateInvalidSourceMetadata) {
     doc::test("Verify that invalid metadata is rejected by IStreamOut::updateSourceMetadata");
     for (const auto& metadata : getInvalidSourceMetadatas()) {
         ASSERT_RESULT(invalidArgsOrNotSupported, stream->updateSourceMetadata(metadata))
@@ -575,7 +751,7 @@
     }
 }
 
-TEST_P(InputStreamTest, UpdateInvalidSinkMetadata) {
+TEST_P(SingleConfigInputStreamTest, UpdateInvalidSinkMetadata) {
     doc::test("Verify that invalid metadata is rejected by IStreamIn::updateSinkMetadata");
     for (const auto& metadata : getInvalidSinkMetadatas()) {
         ASSERT_RESULT(invalidArgsOrNotSupported, stream->updateSinkMetadata(metadata))
diff --git a/audio/effect/all-versions/vts/functional/VtsHalAudioEffectTargetTest.cpp b/audio/effect/all-versions/vts/functional/VtsHalAudioEffectTargetTest.cpp
index d39fbcd..35ff869 100644
--- a/audio/effect/all-versions/vts/functional/VtsHalAudioEffectTargetTest.cpp
+++ b/audio/effect/all-versions/vts/functional/VtsHalAudioEffectTargetTest.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#include <vector>
+
 #define LOG_TAG "AudioEffectHidlHalTest"
 #include <android-base/logging.h>
 #if MAJOR_VERSION <= 6
@@ -309,6 +311,47 @@
     EXPECT_EQ(Result::OK, ret2);
 }
 
+#if MAJOR_VERSION >= 7
+std::vector<EffectBufferConfig> generateInvalidConfigs(const EffectBufferConfig& src) {
+    std::vector<EffectBufferConfig> result;
+    EffectBufferConfig invalidFormat = src;
+    invalidFormat.base.format = "random_string";
+    result.push_back(std::move(invalidFormat));
+    EffectBufferConfig invalidChannelMask = src;
+    invalidChannelMask.base.channelMask = "random_string";
+    result.push_back(std::move(invalidChannelMask));
+    return result;
+}
+
+TEST_P(AudioEffectHidlTest, SetConfigInvalidArguments) {
+    description("Verify that invalid arguments are rejected by SetConfig");
+    Result retval = Result::NOT_INITIALIZED;
+    EffectConfig currentConfig;
+    Return<void> ret = effect->getConfig([&](Result r, const EffectConfig& conf) {
+        retval = r;
+        if (r == Result::OK) {
+            currentConfig = conf;
+        }
+    });
+    EXPECT_TRUE(ret.isOk());
+    EXPECT_EQ(Result::OK, retval);
+    for (const auto& invalidInputCfg : generateInvalidConfigs(currentConfig.inputCfg)) {
+        EffectConfig invalidConfig = currentConfig;
+        invalidConfig.inputCfg = invalidInputCfg;
+        Return<Result> ret = effect->setConfig(invalidConfig, nullptr, nullptr);
+        EXPECT_TRUE(ret.isOk());
+        EXPECT_EQ(Result::INVALID_ARGUMENTS, ret);
+    }
+    for (const auto& invalidOutputCfg : generateInvalidConfigs(currentConfig.outputCfg)) {
+        EffectConfig invalidConfig = currentConfig;
+        invalidConfig.outputCfg = invalidOutputCfg;
+        Return<Result> ret = effect->setConfig(invalidConfig, nullptr, nullptr);
+        EXPECT_TRUE(ret.isOk());
+        EXPECT_EQ(Result::INVALID_ARGUMENTS, ret);
+    }
+}
+#endif
+
 TEST_P(AudioEffectHidlTest, GetConfigReverse) {
     description("Verify that GetConfigReverse does not crash");
     Return<void> ret = effect->getConfigReverse([&](Result, const EffectConfig&) {});
@@ -413,6 +456,16 @@
     EXPECT_EQ(Result::OK, ret);
 }
 
+#if MAJOR_VERSION >= 7
+TEST_P(AudioEffectHidlTest, SetDeviceInvalidDeviceAddress) {
+    description("Verify that invalid device address is rejected by SetDevice");
+    DeviceAddress device{.deviceType = "random_string"};
+    Return<Result> ret = effect->setDevice(device);
+    EXPECT_TRUE(ret.isOk());
+    EXPECT_EQ(Result::INVALID_ARGUMENTS, ret);
+}
+#endif
+
 TEST_P(AudioEffectHidlTest, SetDevice) {
     description("Verify that SetDevice works for an output chain effect");
 #if MAJOR_VERSION <= 6
@@ -468,6 +521,17 @@
     EXPECT_TRUE(ret.isOk());
 }
 
+#if MAJOR_VERSION >= 7
+TEST_P(AudioEffectHidlTest, SetInputDeviceInvalidDeviceAddress) {
+    description("Verify that invalid device address is rejected by SetInputDevice");
+    DeviceAddress device{.deviceType = "random_string"};
+    Return<Result> ret = effect->setInputDevice(device);
+    EXPECT_TRUE(ret.isOk());
+    EXPECT_TRUE(ret == Result::INVALID_ARGUMENTS || ret == Result::NOT_SUPPORTED)
+            << ::testing::PrintToString(ret);
+}
+#endif
+
 TEST_P(AudioEffectHidlTest, SetInputDevice) {
     description("Verify that SetInputDevice does not crash");
 #if MAJOR_VERSION <= 6
@@ -479,6 +543,16 @@
     EXPECT_TRUE(ret.isOk());
 }
 
+#if MAJOR_VERSION >= 7
+TEST_P(AudioEffectHidlTest, SetInvalidAudioSource) {
+    description("Verify that an invalid audio source is rejected by SetAudioSource");
+    Return<Result> ret = effect->setAudioSource("random_string");
+    ASSERT_TRUE(ret.isOk());
+    EXPECT_TRUE(ret == Result::INVALID_ARGUMENTS || ret == Result::NOT_SUPPORTED)
+            << ::testing::PrintToString(ret);
+}
+#endif
+
 TEST_P(AudioEffectHidlTest, SetAudioSource) {
     description("Verify that SetAudioSource does not crash");
 #if MAJOR_VERSION <= 6
diff --git a/authsecret/aidl/Android.bp b/authsecret/aidl/Android.bp
new file mode 100644
index 0000000..0a05034
--- /dev/null
+++ b/authsecret/aidl/Android.bp
@@ -0,0 +1,16 @@
+aidl_interface {
+    name: "android.hardware.authsecret",
+    vendor_available: true,
+    srcs: ["android/hardware/authsecret/*.aidl"],
+    stability: "vintf",
+    backend: {
+        java: {
+            platform_apis: true,
+        },
+        ndk: {
+            vndk: {
+                enabled: true,
+            },
+        },
+    },
+}
diff --git a/authsecret/aidl/aidl_api/android.hardware.authsecret/current/android/hardware/authsecret/IAuthSecret.aidl b/authsecret/aidl/aidl_api/android.hardware.authsecret/current/android/hardware/authsecret/IAuthSecret.aidl
new file mode 100644
index 0000000..14e8325
--- /dev/null
+++ b/authsecret/aidl/aidl_api/android.hardware.authsecret/current/android/hardware/authsecret/IAuthSecret.aidl
@@ -0,0 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.authsecret;
+@VintfStability
+interface IAuthSecret {
+  oneway void setPrimaryUserCredential(in byte[] secret);
+}
diff --git a/authsecret/aidl/android/hardware/authsecret/IAuthSecret.aidl b/authsecret/aidl/android/hardware/authsecret/IAuthSecret.aidl
new file mode 100644
index 0000000..3849ec0
--- /dev/null
+++ b/authsecret/aidl/android/hardware/authsecret/IAuthSecret.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.authsecret;
+
+/**
+ * This security HAL allows vendor components to be cryptographically tied to
+ * the primary user's credential. For example, security hardware can require
+ * proof that the credential is known before applying updates.
+ *
+ */
+@VintfStability
+interface IAuthSecret {
+    /**
+     * When the primary user is unlocked, this method is passed a secret to
+     * prove that is has been successfully unlocked. The primary user can either
+     * be unlocked by a person entering their credential or by another party
+     * using an escrow token e.g. a device administrator.
+     *
+     * The first time this is called, the secret must be used to provision state
+     * that depends on the primary user's secret. The same secret must be passed
+     * on each call until the next factory reset.
+     *
+     * Upon factory reset, any dependence on the secret must be removed as that
+     * secret is now lost and must never be derived again. A new secret must be
+     * created for the new primary user which must be used to newly provision
+     * state the first time this method is called after factory reset.
+     *
+     * The secret must be at least 16 bytes, or the secret must be dropped.
+     *
+     * @param secret blob derived from the primary user's credential.
+     */
+    oneway void setPrimaryUserCredential(in byte[] secret);
+}
diff --git a/authsecret/aidl/default/Android.bp b/authsecret/aidl/default/Android.bp
new file mode 100644
index 0000000..d598344
--- /dev/null
+++ b/authsecret/aidl/default/Android.bp
@@ -0,0 +1,32 @@
+//
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_binary {
+    name: "android.hardware.authsecret-service.example",
+    relative_install_path: "hw",
+    init_rc: ["android.hardware.authsecret-service.example.rc"],
+    vintf_fragments: ["android.hardware.authsecret-service.example.xml"],
+    vendor: true,
+    srcs: [
+        "service.cpp",
+        "AuthSecret.cpp",
+    ],
+    shared_libs: [
+        "android.hardware.authsecret-ndk_platform",
+        "libbase",
+        "libbinder_ndk",
+    ],
+}
diff --git a/authsecret/aidl/default/AuthSecret.cpp b/authsecret/aidl/default/AuthSecret.cpp
new file mode 100644
index 0000000..9645e4d
--- /dev/null
+++ b/authsecret/aidl/default/AuthSecret.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "AuthSecret.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace authsecret {
+
+// Methods from ::android::hardware::authsecret::IAuthSecret follow.
+::ndk::ScopedAStatus AuthSecret::setPrimaryUserCredential(const std::vector<uint8_t>& in_secret) {
+    (void)in_secret;
+    return ::ndk::ScopedAStatus::ok();
+}
+
+} // namespace authsecret
+} // namespace hardware
+} // namespace android
+} // aidl
diff --git a/authsecret/aidl/default/AuthSecret.h b/authsecret/aidl/default/AuthSecret.h
new file mode 100644
index 0000000..b40fc48
--- /dev/null
+++ b/authsecret/aidl/default/AuthSecret.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/authsecret/BnAuthSecret.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace authsecret {
+
+struct AuthSecret : public BnAuthSecret {
+    AuthSecret() = default;
+
+    // Methods from ::android::hardware::authsecret::IAuthSecret follow.
+    ::ndk::ScopedAStatus setPrimaryUserCredential(const std::vector<uint8_t>& in_secret) override;
+
+};
+
+} // namespace authsecret
+} // namespace hardware
+} // namespace android
+} // aidl
diff --git a/authsecret/aidl/default/android.hardware.authsecret-service.example.rc b/authsecret/aidl/default/android.hardware.authsecret-service.example.rc
new file mode 100644
index 0000000..fef6e24
--- /dev/null
+++ b/authsecret/aidl/default/android.hardware.authsecret-service.example.rc
@@ -0,0 +1,4 @@
+service vendor.authsecret_default /vendor/bin/hw/android.hardware.authsecret-service.example
+    class hal
+    user hsm
+    group hsm
diff --git a/authsecret/aidl/default/android.hardware.authsecret-service.example.xml b/authsecret/aidl/default/android.hardware.authsecret-service.example.xml
new file mode 100644
index 0000000..9d4e162
--- /dev/null
+++ b/authsecret/aidl/default/android.hardware.authsecret-service.example.xml
@@ -0,0 +1,10 @@
+<manifest version="1.0" type="device">
+    <hal format="aidl">
+        <name>android.hardware.authsecret</name>
+        <version>1</version>
+        <interface>
+            <name>IAuthSecret</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+</manifest>
diff --git a/authsecret/aidl/default/service.cpp b/authsecret/aidl/default/service.cpp
new file mode 100644
index 0000000..efecf10
--- /dev/null
+++ b/authsecret/aidl/default/service.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+#include "AuthSecret.h"
+
+using ::aidl::android::hardware::authsecret::AuthSecret;
+
+int main() {
+    ABinderProcess_setThreadPoolMaxThreadCount(0);
+    std::shared_ptr<AuthSecret> authsecret = ndk::SharedRefBase::make<AuthSecret>();
+
+    const std::string instance = std::string() + AuthSecret::descriptor + "/default";
+    binder_status_t status = AServiceManager_addService(authsecret->asBinder().get(), instance.c_str());
+    CHECK(status == STATUS_OK);
+
+    ABinderProcess_joinThreadPool();
+    return -1; // Should never be reached
+}
diff --git a/authsecret/aidl/vts/Android.bp b/authsecret/aidl/vts/Android.bp
new file mode 100644
index 0000000..83a85b2
--- /dev/null
+++ b/authsecret/aidl/vts/Android.bp
@@ -0,0 +1,31 @@
+//
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_test {
+    name: "VtsHalAuthSecretTargetTest",
+    defaults: [
+        "VtsHalTargetTestDefaults",
+        "use_libaidlvintf_gtest_helper_static",
+    ],
+    srcs: ["VtsHalAuthSecretTargetTest.cpp"],
+    static_libs: ["android.hardware.authsecret-ndk_platform"],
+    shared_libs: ["libbinder_ndk"],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
+    require_root: true,
+}
diff --git a/authsecret/aidl/vts/VtsHalAuthSecretTargetTest.cpp b/authsecret/aidl/vts/VtsHalAuthSecretTargetTest.cpp
new file mode 100644
index 0000000..31c2834
--- /dev/null
+++ b/authsecret/aidl/vts/VtsHalAuthSecretTargetTest.cpp
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+
+#include <aidl/android/hardware/authsecret/IAuthSecret.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+using ::aidl::android::hardware::authsecret::IAuthSecret;
+
+using ::ndk::SpAIBinder;
+
+/**
+ * There is no expected behaviour that can be tested so these tests check the
+ * HAL doesn't crash with different execution orders.
+ */
+class AuthSecretAidlTest : public testing::TestWithParam<std::string> {
+  public:
+    virtual void SetUp() override {
+        authsecret = IAuthSecret::fromBinder(
+            SpAIBinder(AServiceManager_waitForService(GetParam().c_str())));
+        ASSERT_NE(authsecret, nullptr);
+
+        // Notify LSS to generate PIN code '1234' and corresponding secret.
+        (void)system("cmd lock_settings set-pin 1234");
+
+        // All tests must enroll the correct secret first as this cannot be changed
+        // without a factory reset and the order of tests could change.
+        authsecret->setPrimaryUserCredential(CORRECT_SECRET);
+    }
+
+    static void TearDownTestSuite() {
+        // clean up PIN code after testing
+        (void)system("cmd lock_settings clear --old 1234");
+    }
+
+    std::shared_ptr<IAuthSecret> authsecret;
+    std::vector<uint8_t> CORRECT_SECRET{61, 93, 124, 240, 5, 0, 7, 201, 9, 129, 11, 12, 0, 14, 0, 16};
+    std::vector<uint8_t> WRONG_SECRET{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
+};
+
+/* Provision the primary user with a secret. */
+TEST_P(AuthSecretAidlTest, provisionPrimaryUserCredential) {
+    // Secret provisioned by SetUp()
+}
+
+/* Provision the primary user with a secret and pass the secret again. */
+TEST_P(AuthSecretAidlTest, provisionPrimaryUserCredentialAndPassAgain) {
+    // Secret provisioned by SetUp()
+    authsecret->setPrimaryUserCredential(CORRECT_SECRET);
+}
+
+/* Provision the primary user with a secret and pass the secret again repeatedly. */
+TEST_P(AuthSecretAidlTest, provisionPrimaryUserCredentialAndPassAgainMultipleTimes) {
+    // Secret provisioned by SetUp()
+    constexpr int N = 5;
+    for (int i = 0; i < N; ++i) {
+        authsecret->setPrimaryUserCredential(CORRECT_SECRET);
+    }
+}
+
+/* Provision the primary user with a secret and then pass the wrong secret. This
+ * should never happen and is an framework bug if it does. As the secret is
+ * wrong, the HAL implementation may not be able to function correctly but it
+ * should fail gracefully. */
+TEST_P(AuthSecretAidlTest, provisionPrimaryUserCredentialAndWrongSecret) {
+    // Secret provisioned by SetUp()
+    authsecret->setPrimaryUserCredential(WRONG_SECRET);
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AuthSecretAidlTest);
+INSTANTIATE_TEST_SUITE_P(
+        PerInstance, AuthSecretAidlTest,
+        testing::ValuesIn(android::getAidlHalInstanceNames(IAuthSecret::descriptor)),
+        android::PrintInstanceNameToString);
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    ABinderProcess_setThreadPoolMaxThreadCount(1);
+    ABinderProcess_startThreadPool();
+    return RUN_ALL_TESTS();
+}
diff --git a/automotive/audiocontrol/aidl/default/Android.bp b/automotive/audiocontrol/aidl/default/Android.bp
index faf7ad2..427709a 100644
--- a/automotive/audiocontrol/aidl/default/Android.bp
+++ b/automotive/audiocontrol/aidl/default/Android.bp
@@ -22,15 +22,18 @@
     generated_sources: ["audio_policy_configuration_V7_0"],
     header_libs: ["libxsdc-utils"],
     shared_libs: [
+        "android.frameworks.automotive.powerpolicy-ndk_platform",
         "android.hardware.automotive.audiocontrol-ndk_platform",
         "libbase",
         "libbinder_ndk",
-        "liblog",
         "libcutils",
+        "liblog",
+        "libpowerpolicyclient",
         "libxml2",
     ],
     srcs: [
         "AudioControl.cpp",
         "main.cpp",
+        "PowerPolicyClient.cpp",
     ],
 }
diff --git a/automotive/audiocontrol/aidl/default/PowerPolicyClient.cpp b/automotive/audiocontrol/aidl/default/PowerPolicyClient.cpp
new file mode 100644
index 0000000..7657337
--- /dev/null
+++ b/automotive/audiocontrol/aidl/default/PowerPolicyClient.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "PowerPolicyClient.h"
+#include "AudioControl.h"
+
+#include <android-base/logging.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace audiocontrol {
+
+namespace aafap = aidl::android::frameworks::automotive::powerpolicy;
+
+using aafap::CarPowerPolicy;
+using aafap::CarPowerPolicyFilter;
+using aafap::PowerComponent;
+using ::android::frameworks::automotive::powerpolicy::hasComponent;
+using ::ndk::ScopedAStatus;
+
+namespace {
+
+constexpr PowerComponent kAudioComponent = PowerComponent::AUDIO;
+
+}  // namespace
+
+PowerPolicyClient::PowerPolicyClient(std::shared_ptr<AudioControl> audioControl)
+    : mAudioControl(audioControl) {}
+
+void PowerPolicyClient::onInitFailed() {
+    LOG(ERROR) << "Initializing power policy client failed";
+}
+
+std::vector<PowerComponent> PowerPolicyClient::getComponentsOfInterest() {
+    std::vector<PowerComponent> components{kAudioComponent};
+    return components;
+}
+
+ScopedAStatus PowerPolicyClient::onPolicyChanged(const CarPowerPolicy& powerPolicy) {
+    if (hasComponent(powerPolicy.enabledComponents, kAudioComponent)) {
+        LOG(DEBUG) << "Power policy: Audio component is enabled";
+        // TODO(b/173719953): Do something when AUDIO is enabled.
+    } else if (hasComponent(powerPolicy.disabledComponents, kAudioComponent)) {
+        LOG(DEBUG) << "Power policy: Audio component is disabled";
+        // TODO(b/173719953): Do something when AUDIO is disabled.
+    }
+    return ScopedAStatus::ok();
+}
+
+}  // namespace audiocontrol
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/automotive/audiocontrol/aidl/default/PowerPolicyClient.h b/automotive/audiocontrol/aidl/default/PowerPolicyClient.h
new file mode 100644
index 0000000..0b4d5b6
--- /dev/null
+++ b/automotive/audiocontrol/aidl/default/PowerPolicyClient.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AUTOMOTIVE_AUDIOCONTROL_AIDL_DEFAULT_POWERPOLICYCLIENT_H_
+#define AUTOMOTIVE_AUDIOCONTROL_AIDL_DEFAULT_POWERPOLICYCLIENT_H_
+
+#include "PowerPolicyClientBase.h"
+
+#include <memory>
+
+namespace aidl::android::hardware::automotive::audiocontrol {
+
+class AudioControl;
+
+class PowerPolicyClient
+    : public ::android::frameworks::automotive::powerpolicy::PowerPolicyClientBase {
+  public:
+    explicit PowerPolicyClient(std::shared_ptr<AudioControl> audioControl);
+
+    void onInitFailed();
+    std::vector<::aidl::android::frameworks::automotive::powerpolicy::PowerComponent>
+    getComponentsOfInterest() override;
+    ::ndk::ScopedAStatus onPolicyChanged(
+            const ::aidl::android::frameworks::automotive::powerpolicy::CarPowerPolicy&) override;
+
+  private:
+    std::shared_ptr<AudioControl> mAudioControl;
+};
+
+}  // namespace aidl::android::hardware::automotive::audiocontrol
+
+#endif  // AUTOMOTIVE_AUDIOCONTROL_AIDL_DEFAULT_POWERPOLICYCLIENT_H_
diff --git a/automotive/audiocontrol/aidl/default/main.cpp b/automotive/audiocontrol/aidl/default/main.cpp
index 996665f..9b259fc 100644
--- a/automotive/audiocontrol/aidl/default/main.cpp
+++ b/automotive/audiocontrol/aidl/default/main.cpp
@@ -15,22 +15,28 @@
  */
 
 #include "AudioControl.h"
+#include "PowerPolicyClient.h"
 
 #include <android-base/logging.h>
 #include <android/binder_manager.h>
 #include <android/binder_process.h>
 
 using aidl::android::hardware::automotive::audiocontrol::AudioControl;
+using aidl::android::hardware::automotive::audiocontrol::PowerPolicyClient;
 
 int main() {
     ABinderProcess_setThreadPoolMaxThreadCount(0);
-    std::shared_ptr<AudioControl> audioControl = ndk::SharedRefBase::make<AudioControl>();
+    std::shared_ptr<AudioControl> audioControl = ::ndk::SharedRefBase::make<AudioControl>();
 
     const std::string instance = std::string() + AudioControl::descriptor + "/default";
     binder_status_t status =
             AServiceManager_addService(audioControl->asBinder().get(), instance.c_str());
     CHECK(status == STATUS_OK);
 
+    std::shared_ptr<PowerPolicyClient> powerPolicyClient =
+            ::ndk::SharedRefBase::make<PowerPolicyClient>(audioControl);
+    powerPolicyClient->init();
+
     ABinderProcess_joinThreadPool();
     return EXIT_FAILURE;  // should not reach
 }
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 8ef2b60..73513f4 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
@@ -1153,6 +1153,47 @@
                                 .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
                         },
         },
+        {
+                .config =
+                        {
+                                .prop = toInt(VehicleProperty::CLUSTER_SWITCH_UI),
+                                .access = VehiclePropertyAccess::READ,
+                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                        },
+        },
+        {
+                .config =
+                        {
+                                .prop = toInt(VehicleProperty::CLUSTER_DISPLAY_STATE),
+                                .access = VehiclePropertyAccess::READ,
+                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                        },
+        },
+        {
+                .config =
+                        {
+                                .prop = toInt(VehicleProperty::CLUSTER_REPORT_STATE),
+                                .access = VehiclePropertyAccess::WRITE,
+                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                                .configArray = {0, 0, 0, 9, 0, 0, 0, 0, 16},
+                        },
+        },
+        {
+                .config =
+                        {
+                                .prop = toInt(VehicleProperty::CLUSTER_REQUEST_DISPLAY),
+                                .access = VehiclePropertyAccess::WRITE,
+                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                        },
+        },
+        {
+                .config =
+                        {
+                                .prop = toInt(VehicleProperty::CLUSTER_NAVIGATION_STATE_LEGACY),
+                                .access = VehiclePropertyAccess::WRITE,
+                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                        },
+        },
 };
 
 }  // impl
diff --git a/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal
index 0488b57..ed75e1d 100644
--- a/automotive/vehicle/2.0/types.hal
+++ b/automotive/vehicle/2.0/types.hal
@@ -3027,6 +3027,115 @@
          | VehiclePropertyGroup:SYSTEM
          | VehiclePropertyType:INT64
          | VehicleArea:GLOBAL),
+
+    /**
+     * Starts the ClusterUI in cluster display.
+     *
+     * int32[0]: the type of ClusterUI to show
+     *    0 indicates ClusterHome, that is a home screen of cluster display, and provides
+     *        the default UI and a kind of launcher functionality for cluster display.
+     *    the other values are followed by OEM's definition.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     */
+     CLUSTER_SWITCH_UI = (
+         0x0F34
+         | VehiclePropertyGroup:SYSTEM
+         | VehiclePropertyType:INT32
+         | VehicleArea:GLOBAL),
+
+    /**
+     * Changes the state of the cluster display.
+     *
+     * int32[0]: on/off: 0 - off, 1 - on, -1 - don't care
+     * int32[1]: width: positive number - actual width in pixels
+                        -1 - don't care (should set "don't care" both width and height)
+     * int32[2]: height: ditto with width
+     * int32[3]: Inset - left: positive number - actual left inset value in pixels
+                               -1 - don't care (should set "don't care" all Inset fields)
+     * int32[4]: Inset - top
+     * int32[5]: Inset - right
+     * int32[6]: Inset - bottom
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     */
+     CLUSTER_DISPLAY_STATE = (
+         0x0F35
+         | VehiclePropertyGroup:SYSTEM
+         | VehiclePropertyType:INT32_VEC
+         | VehicleArea:GLOBAL),
+
+    /**
+     * Reports the current display state and ClusterUI state.
+     *
+     * ClusterHome will send this message when it handles CLUSTER_SWITCH_UI, CLUSTER_DISPLAY_STATE.
+     *
+     * In addition, ClusterHome should send this message when it starts for the first time.
+     * When ClusterOS receives this message and if the internal expectation is different with the
+     * received message, then it should send CLUSTER_SWITCH_UI, CLUSTER_DISPLAY_STATE again to
+     * match the state.
+     *
+     * int32[0]: on/off: 0 - off, 1 - on
+     * int32[1]: width
+     * int32[2]: height
+     * int32[3]: Inset - left
+     * int32[4]: Inset - top
+     * int32[5]: Inset - right
+     * int32[6]: Inset - bottom
+     * int32[7]: the type of ClusterUI in the fullscreen or main screen.
+     *    0 indicates ClusterHome.
+     *    the other values are followed by OEM's definition.
+     * int32[8]: the type of ClusterUI in sub screen if the currently two UIs are shown.
+     *    -1 indicates the area isn't used any more.
+     * bytes: the array to represent the availability of ClusterUI.
+     *     0 indicates non-available and 1 indicates available.
+     *     For example, let's assume a car supports 3 UI like HOME, MAPS, CALL and it only supports
+     *     CALL UI only when the cellular network is available. Then, if the nework is avaibale,
+     *     it'll send [1 1 1], and if it's out of network, it'll send [1 1 0].
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:WRITE
+     */
+     CLUSTER_REPORT_STATE = (
+         0x0F36
+         | VehiclePropertyGroup:SYSTEM
+         | VehiclePropertyType:MIXED
+         | VehicleArea:GLOBAL),
+
+    /**
+     * Requests to change the cluster display state to show some ClusterUI.
+     *
+     * When the current display state is off and ClusterHome sends this message to ClusterOS to
+     * request to turn the display on to show some specific ClusterUI.
+     * ClusterOS should response this with CLUSTER_DISPLAY_STATE.
+     *
+     * int32[0]: the type of ClusterUI to show
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:WRITE
+     */
+     CLUSTER_REQUEST_DISPLAY = (
+         0x0F37
+         | VehiclePropertyGroup:SYSTEM
+         | VehiclePropertyType:INT32
+         | VehicleArea:GLOBAL),
+
+    /**
+     * Informs the current navigation state.
+     *
+     * bytes: the serialized message of NavigationStateProto.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:WRITE
+     */
+     CLUSTER_NAVIGATION_STATE_LEGACY = (
+         0x0F38
+         | VehiclePropertyGroup:SYSTEM
+         | VehiclePropertyType:BYTES
+         | VehicleArea:GLOBAL),
+
 };
 
 /**
@@ -3691,7 +3800,10 @@
  * events.
  */
 struct VehiclePropValue {
-    /** Time is elapsed nanoseconds since boot */
+    /**
+     * Time is elapsed nanoseconds since boot. It's equivalent to
+     * {@code SystemClock.elapsedRealtimeNano()}.
+     */
     int64_t timestamp;
 
     /**
diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/AcquiredInfo.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/AcquiredInfo.aidl
index a05fad9..56d097d 100644
--- a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/AcquiredInfo.aidl
+++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/AcquiredInfo.aidl
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/Error.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/Error.aidl
index 15fcbf9..cba6ec5 100644
--- a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/Error.aidl
+++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/Error.aidl
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/FaceSensorType.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/FaceSensorType.aidl
index 943129e..b08c345 100644
--- a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/FaceSensorType.aidl
+++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/FaceSensorType.aidl
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/IFace.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/IFace.aidl
index 518fb14..65afaa4 100644
--- a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/IFace.aidl
+++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/IFace.aidl
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/ISession.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/ISession.aidl
index 5d9a430..7d70971 100644
--- a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/ISession.aidl
+++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/ISession.aidl
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
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 caf65ae..4cea0f0 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
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
@@ -33,5 +34,5 @@
   void onEnrollmentsEnumerated(in int[] enrollmentIds);
   void onEnrollmentsRemoved(in int[] enrollmentIds);
   void onAuthenticatorIdRetrieved(in long authenticatorId);
-  void onAuthenticatorIdInvalidated();
+  void onAuthenticatorIdInvalidated(in long newAuthenticatorId);
 }
diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/SensorProps.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/SensorProps.aidl
index 365ae58..a52829c 100644
--- a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/SensorProps.aidl
+++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/SensorProps.aidl
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/SessionState.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/SessionState.aidl
index 8e5139b..12a5eab 100644
--- a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/SessionState.aidl
+++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/SessionState.aidl
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/biometrics/face/aidl/android/hardware/biometrics/face/ISessionCallback.aidl b/biometrics/face/aidl/android/hardware/biometrics/face/ISessionCallback.aidl
index fd4a648..d59ce2e 100644
--- a/biometrics/face/aidl/android/hardware/biometrics/face/ISessionCallback.aidl
+++ b/biometrics/face/aidl/android/hardware/biometrics/face/ISessionCallback.aidl
@@ -195,6 +195,9 @@
      * SessionState::INVALIDATING_AUTHENTICATOR_ID.
      *
      * See ISession#invalidateAuthenticatorId for more information.
+     *
+     * @param newAuthenticatorId The new entropy-encoded random identifier associated with the
+     *                           current set of enrollments.
      */
-    void onAuthenticatorIdInvalidated();
+    void onAuthenticatorIdInvalidated(in long newAuthenticatorId);
 }
diff --git a/biometrics/face/aidl/vts/VtsHalBiometricsFaceTargetTest.cpp b/biometrics/face/aidl/vts/VtsHalBiometricsFaceTargetTest.cpp
index 5f10306..f6d0aab 100644
--- a/biometrics/face/aidl/vts/VtsHalBiometricsFaceTargetTest.cpp
+++ b/biometrics/face/aidl/vts/VtsHalBiometricsFaceTargetTest.cpp
@@ -103,7 +103,9 @@
         return ndk::ScopedAStatus::ok();
     }
 
-    ndk::ScopedAStatus onAuthenticatorIdInvalidated() override { return ndk::ScopedAStatus::ok(); }
+    ndk::ScopedAStatus onAuthenticatorIdInvalidated(int64_t /*newAuthenticatorId*/) 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/AcquiredInfo.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl
index df30dca..d5f2ed2 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl
+++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/Error.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/Error.aidl
index 6bd71b2..aec499f 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/Error.aidl
+++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/Error.aidl
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/FingerprintSensorType.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/FingerprintSensorType.aidl
index 14bfece..784e1d0 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/FingerprintSensorType.aidl
+++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/FingerprintSensorType.aidl
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/IFingerprint.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/IFingerprint.aidl
index c5c6786..51b4c63 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/IFingerprint.aidl
+++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/IFingerprint.aidl
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ISession.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ISession.aidl
index 4df7981..185d86f 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ISession.aidl
+++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ISession.aidl
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
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 b7a48a5..cf663a5 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
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
@@ -33,5 +34,5 @@
   void onEnrollmentsEnumerated(in int[] enrollmentIds);
   void onEnrollmentsRemoved(in int[] enrollmentIds);
   void onAuthenticatorIdRetrieved(in long authenticatorId);
-  void onAuthenticatorIdInvalidated();
+  void onAuthenticatorIdInvalidated(in long newAuthenticatorId);
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/SensorProps.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/SensorProps.aidl
index 8c779ab..f8a40a9 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/SensorProps.aidl
+++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/SensorProps.aidl
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/SessionState.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/SessionState.aidl
index e9daef1..3453f93 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/SessionState.aidl
+++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/SessionState.aidl
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISessionCallback.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISessionCallback.aidl
index 4387f98..fde1df7 100644
--- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISessionCallback.aidl
+++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISessionCallback.aidl
@@ -195,6 +195,9 @@
      * SessionState::INVALIDATING_AUTHENTICATOR_ID.
      *
      * See ISession#invalidateAuthenticatorId for more information.
+     *
+     * @param newAuthenticatorId The new entropy-encoded random identifier associated with the
+     *                           current set of enrollments.
      */
-    void onAuthenticatorIdInvalidated();
+    void onAuthenticatorIdInvalidated(in long newAuthenticatorId);
 }
diff --git a/biometrics/fingerprint/aidl/vts/VtsHalBiometricsFingerprintTargetTest.cpp b/biometrics/fingerprint/aidl/vts/VtsHalBiometricsFingerprintTargetTest.cpp
index adb98ac..ddbc0fe 100644
--- a/biometrics/fingerprint/aidl/vts/VtsHalBiometricsFingerprintTargetTest.cpp
+++ b/biometrics/fingerprint/aidl/vts/VtsHalBiometricsFingerprintTargetTest.cpp
@@ -110,7 +110,7 @@
         return ndk::ScopedAStatus::ok();
     }
 
-    ndk::ScopedAStatus onAuthenticatorIdInvalidated() override {
+    ndk::ScopedAStatus onAuthenticatorIdInvalidated(int64_t /*newAuthenticatorId*/) override {
         return ndk::ScopedAStatus::ok();
     }
 
diff --git a/bluetooth/audio/2.1/default/LeAudioAudioProvider.cpp b/bluetooth/audio/2.1/default/LeAudioAudioProvider.cpp
index 1fa2dce..9c2b4fe 100644
--- a/bluetooth/audio/2.1/default/LeAudioAudioProvider.cpp
+++ b/bluetooth/audio/2.1/default/LeAudioAudioProvider.cpp
@@ -91,35 +91,30 @@
 
   uint32_t kDataMqSize = 0;
   switch (audioConfig.pcmConfig().sampleRate) {
+    case SampleRate::RATE_8000:
+      kDataMqSize = 8000;
+      break;
     case SampleRate::RATE_16000:
       kDataMqSize = 16000;
       break;
     case SampleRate::RATE_24000:
       kDataMqSize = 24000;
       break;
+    case SampleRate::RATE_32000:
+      kDataMqSize = 32000;
+      break;
     case SampleRate::RATE_44100:
       kDataMqSize = 44100;
       break;
     case SampleRate::RATE_48000:
       kDataMqSize = 48000;
       break;
-    case SampleRate::RATE_88200:
-      kDataMqSize = 88200;
-      break;
-    case SampleRate::RATE_96000:
-      kDataMqSize = 96000;
-      break;
-    case SampleRate::RATE_176400:
-      kDataMqSize = 176400;
-      break;
-    case SampleRate::RATE_192000:
-      kDataMqSize = 192000;
-      break;
     default:
-      /* This should never happen it would be caught while validating
-       * parameters.
-       */
-      break;
+      LOG(WARNING) << __func__ << " - Unsupported sampling frequency="
+                   << toString(audioConfig.pcmConfig());
+      _hidl_cb(BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION,
+               DataMQ::Descriptor());
+      return Void();
   }
 
   /* Number of samples per millisecond */
diff --git a/bluetooth/audio/2.1/default/session/BluetoothAudioSupportedCodecsDB.cpp b/bluetooth/audio/2.1/default/session/BluetoothAudioSupportedCodecsDB.cpp
index d15db49..0937f44 100644
--- a/bluetooth/audio/2.1/default/session/BluetoothAudioSupportedCodecsDB.cpp
+++ b/bluetooth/audio/2.1/default/session/BluetoothAudioSupportedCodecsDB.cpp
@@ -409,12 +409,14 @@
 }
 
 bool IsSoftwarePcmConfigurationValid_2_1(const PcmParameters& pcm_config) {
-  if ((pcm_config.sampleRate != SampleRate::RATE_44100 &&
-       pcm_config.sampleRate != SampleRate::RATE_48000 &&
+  if ((pcm_config.sampleRate != SampleRate::RATE_96000 &&
        pcm_config.sampleRate != SampleRate::RATE_88200 &&
-       pcm_config.sampleRate != SampleRate::RATE_96000 &&
+       pcm_config.sampleRate != SampleRate::RATE_48000 &&
+       pcm_config.sampleRate != SampleRate::RATE_44100 &&
+       pcm_config.sampleRate != SampleRate::RATE_32000 &&
+       pcm_config.sampleRate != SampleRate::RATE_24000 &&
        pcm_config.sampleRate != SampleRate::RATE_16000 &&
-       pcm_config.sampleRate != SampleRate::RATE_24000) ||
+       pcm_config.sampleRate != SampleRate::RATE_8000) ||
       (pcm_config.bitsPerSample != BitsPerSample::BITS_16 &&
        pcm_config.bitsPerSample != BitsPerSample::BITS_24 &&
        pcm_config.bitsPerSample != BitsPerSample::BITS_32) ||
diff --git a/bluetooth/audio/2.1/vts/functional/VtsHalBluetoothAudioV2_1TargetTest.cpp b/bluetooth/audio/2.1/vts/functional/VtsHalBluetoothAudioV2_1TargetTest.cpp
index 37d1281..95903d1 100644
--- a/bluetooth/audio/2.1/vts/functional/VtsHalBluetoothAudioV2_1TargetTest.cpp
+++ b/bluetooth/audio/2.1/vts/functional/VtsHalBluetoothAudioV2_1TargetTest.cpp
@@ -1005,8 +1005,10 @@
     BluetoothAudioProvidersFactoryHidlTest::TearDown();
   }
 
-  static constexpr SampleRate le_audio_output_sample_rates_[3] = {
-      SampleRate::RATE_UNKNOWN, SampleRate::RATE_16000, SampleRate::RATE_24000};
+  static constexpr SampleRate le_audio_output_sample_rates_[11] = {
+      SampleRate::RATE_UNKNOWN, SampleRate::RATE_8000,  SampleRate::RATE_16000,
+      SampleRate::RATE_24000,   SampleRate::RATE_32000, SampleRate::RATE_44100,
+      SampleRate::RATE_48000};
   static constexpr BitsPerSample le_audio_output_bits_per_samples_[3] = {
       BitsPerSample::BITS_UNKNOWN, BitsPerSample::BITS_16,
       BitsPerSample::BITS_24};
@@ -1097,8 +1099,10 @@
     BluetoothAudioProvidersFactoryHidlTest::TearDown();
   }
 
-  static constexpr SampleRate le_audio_output_sample_rates_[3] = {
-      SampleRate::RATE_UNKNOWN, SampleRate::RATE_16000, SampleRate::RATE_24000};
+  static constexpr SampleRate le_audio_output_sample_rates_[11] = {
+      SampleRate::RATE_UNKNOWN, SampleRate::RATE_8000,  SampleRate::RATE_16000,
+      SampleRate::RATE_24000,   SampleRate::RATE_32000, SampleRate::RATE_44100,
+      SampleRate::RATE_48000};
   static constexpr BitsPerSample le_audio_output_bits_per_samples_[3] = {
       BitsPerSample::BITS_UNKNOWN, BitsPerSample::BITS_16,
       BitsPerSample::BITS_24};
diff --git a/cas/1.0/vts/functional/Android.bp b/cas/1.0/vts/functional/Android.bp
index 82dc568..a065b85 100644
--- a/cas/1.0/vts/functional/Android.bp
+++ b/cas/1.0/vts/functional/Android.bp
@@ -20,6 +20,8 @@
     srcs: ["VtsHalCasV1_0TargetTest.cpp"],
     static_libs: [
         "android.hardware.cas@1.0",
+        "android.hardware.cas@1.1",
+        "android.hardware.cas@1.2",
         "android.hardware.cas.native@1.0",
         "android.hidl.allocator@1.0",
         "android.hidl.memory@1.0",
diff --git a/cas/1.0/vts/functional/VtsHalCasV1_0TargetTest.cpp b/cas/1.0/vts/functional/VtsHalCasV1_0TargetTest.cpp
index 7f5d988..df0c859 100644
--- a/cas/1.0/vts/functional/VtsHalCasV1_0TargetTest.cpp
+++ b/cas/1.0/vts/functional/VtsHalCasV1_0TargetTest.cpp
@@ -22,6 +22,7 @@
 #include <android/hardware/cas/1.0/IDescramblerBase.h>
 #include <android/hardware/cas/1.0/IMediaCasService.h>
 #include <android/hardware/cas/1.0/types.h>
+#include <android/hardware/cas/1.2/IMediaCasService.h>
 #include <android/hardware/cas/native/1.0/IDescrambler.h>
 #include <android/hardware/cas/native/1.0/types.h>
 #include <binder/MemoryDealer.h>
@@ -212,6 +213,10 @@
 class MediaCasHidlTest : public testing::TestWithParam<std::string> {
   public:
     virtual void SetUp() override {
+        if (android::hardware::cas::V1_2::IMediaCasService::getService(GetParam()) == nullptr) {
+            ALOGI("Descrambler is need to be tested before cas@1.2.");
+            mIsTestDescrambler = true;
+        }
         mService = IMediaCasService::getService(GetParam());
         ASSERT_NE(mService, nullptr);
     }
@@ -226,6 +231,7 @@
     sp<ICas> mMediaCas;
     sp<IDescramblerBase> mDescramblerBase;
     sp<MediaCasListener> mCasListener;
+    bool mIsTestDescrambler = false;
     typedef struct _OobInputTestParams {
         const SubSample* subSamples;
         uint32_t numSubSamples;
@@ -270,8 +276,14 @@
 
     auto descramblerStatus = mService->createDescrambler(caSystemId);
     if (!descramblerStatus.isOk()) {
-        return ::testing::AssertionFailure();
+        if (mIsTestDescrambler) {
+            return ::testing::AssertionFailure();
+        } else {
+            ALOGI("Skip Descrambler test since it's not required in cas@1.2.");
+            return ::testing::AssertionSuccess();
+        }
     }
+    mIsTestDescrambler = true;
     mDescramblerBase = descramblerStatus;
     return ::testing::AssertionResult(mDescramblerBase != nullptr);
 }
@@ -494,14 +506,15 @@
     returnStatus = mMediaCas->setSessionPrivateData(streamSessionId, hidlPvtData);
     EXPECT_TRUE(returnStatus.isOk());
     EXPECT_EQ(Status::OK, returnStatus);
+    if (mIsTestDescrambler) {
+        returnStatus = mDescramblerBase->setMediaCasSession(sessionId);
+        EXPECT_TRUE(returnStatus.isOk());
+        EXPECT_EQ(Status::OK, returnStatus);
 
-    returnStatus = mDescramblerBase->setMediaCasSession(sessionId);
-    EXPECT_TRUE(returnStatus.isOk());
-    EXPECT_EQ(Status::OK, returnStatus);
-
-    returnStatus = mDescramblerBase->setMediaCasSession(streamSessionId);
-    EXPECT_TRUE(returnStatus.isOk());
-    EXPECT_EQ(Status::OK, returnStatus);
+        returnStatus = mDescramblerBase->setMediaCasSession(streamSessionId);
+        EXPECT_TRUE(returnStatus.isOk());
+        EXPECT_EQ(Status::OK, returnStatus);
+    }
 
     hidl_vec<uint8_t> hidlNullPtr;
     hidlNullPtr.setToExternal(static_cast<uint8_t*>(nullptr), 0);
@@ -543,29 +556,32 @@
     EXPECT_TRUE(returnStatus.isOk());
     EXPECT_EQ(Status::OK, returnStatus);
 
-    EXPECT_FALSE(mDescramblerBase->requiresSecureDecoderComponent("video/avc"));
+    if (mIsTestDescrambler) {
+        EXPECT_FALSE(mDescramblerBase->requiresSecureDecoderComponent("video/avc"));
 
-    sp<IDescrambler> descrambler;
-    descrambler = IDescrambler::castFrom(mDescramblerBase);
-    ASSERT_NE(descrambler, nullptr);
+        sp<IDescrambler> descrambler;
+        descrambler = IDescrambler::castFrom(mDescramblerBase);
+        ASSERT_NE(descrambler, nullptr);
 
-    Status descrambleStatus = Status::OK;
-    sp<IMemory> dataMemory;
+        Status descrambleStatus = Status::OK;
+        sp<IMemory> dataMemory;
 
-    ASSERT_TRUE(descrambleTestInputBuffer(descrambler, &descrambleStatus, &dataMemory));
-    EXPECT_EQ(Status::OK, descrambleStatus);
+        ASSERT_TRUE(descrambleTestInputBuffer(descrambler, &descrambleStatus, &dataMemory));
+        EXPECT_EQ(Status::OK, descrambleStatus);
 
-    ASSERT_NE(nullptr, dataMemory.get());
-    uint8_t* opBuffer = static_cast<uint8_t*>(static_cast<void*>(dataMemory->unsecurePointer()));
+        ASSERT_NE(nullptr, dataMemory.get());
+        uint8_t* opBuffer =
+                static_cast<uint8_t*>(static_cast<void*>(dataMemory->unsecurePointer()));
 
-    int compareResult =
-        memcmp(static_cast<const void*>(opBuffer), static_cast<const void*>(kOutRefBinaryBuffer),
-               sizeof(kOutRefBinaryBuffer));
-    EXPECT_EQ(0, compareResult);
+        int compareResult =
+                memcmp(static_cast<const void*>(opBuffer),
+                       static_cast<const void*>(kOutRefBinaryBuffer), sizeof(kOutRefBinaryBuffer));
+        EXPECT_EQ(0, compareResult);
 
-    returnStatus = mDescramblerBase->release();
-    EXPECT_TRUE(returnStatus.isOk());
-    EXPECT_EQ(Status::OK, returnStatus);
+        returnStatus = mDescramblerBase->release();
+        EXPECT_TRUE(returnStatus.isOk());
+        EXPECT_EQ(Status::OK, returnStatus);
+    }
 
     returnStatus = mMediaCas->release();
     EXPECT_TRUE(returnStatus.isOk());
@@ -590,13 +606,15 @@
     EXPECT_TRUE(returnStatus.isOk());
     EXPECT_EQ(Status::OK, returnStatus);
 
-    returnStatus = mDescramblerBase->setMediaCasSession(sessionId);
-    EXPECT_TRUE(returnStatus.isOk());
-    EXPECT_EQ(Status::ERROR_CAS_SESSION_NOT_OPENED, returnStatus);
+    if (mIsTestDescrambler) {
+        returnStatus = mDescramblerBase->setMediaCasSession(sessionId);
+        EXPECT_TRUE(returnStatus.isOk());
+        EXPECT_EQ(Status::ERROR_CAS_SESSION_NOT_OPENED, returnStatus);
 
-    returnStatus = mDescramblerBase->setMediaCasSession(streamSessionId);
-    EXPECT_TRUE(returnStatus.isOk());
-    EXPECT_EQ(Status::ERROR_CAS_SESSION_NOT_OPENED, returnStatus);
+        returnStatus = mDescramblerBase->setMediaCasSession(streamSessionId);
+        EXPECT_TRUE(returnStatus.isOk());
+        EXPECT_EQ(Status::ERROR_CAS_SESSION_NOT_OPENED, returnStatus);
+    }
 }
 
 TEST_P(MediaCasHidlTest, TestClearKeyErrors) {
@@ -654,38 +672,40 @@
     EXPECT_TRUE(returnStatus.isOk());
     EXPECT_EQ(Status::ERROR_CAS_UNKNOWN, returnStatus);
 
-    /*
-     * Test MediaDescrambler error codes
-     */
-    // setMediaCasSession should fail with an invalid session id
-    returnStatus = mDescramblerBase->setMediaCasSession(invalidSessionId);
-    EXPECT_TRUE(returnStatus.isOk());
-    EXPECT_EQ(Status::ERROR_CAS_SESSION_NOT_OPENED, returnStatus);
+    if (mIsTestDescrambler) {
+        /*
+         * Test MediaDescrambler error codes
+         */
+        // setMediaCasSession should fail with an invalid session id
+        returnStatus = mDescramblerBase->setMediaCasSession(invalidSessionId);
+        EXPECT_TRUE(returnStatus.isOk());
+        EXPECT_EQ(Status::ERROR_CAS_SESSION_NOT_OPENED, returnStatus);
 
-    // descramble should fail without a valid session
-    sp<IDescrambler> descrambler;
-    descrambler = IDescrambler::castFrom(mDescramblerBase);
-    ASSERT_NE(descrambler, nullptr);
+        // descramble should fail without a valid session
+        sp<IDescrambler> descrambler;
+        descrambler = IDescrambler::castFrom(mDescramblerBase);
+        ASSERT_NE(descrambler, nullptr);
 
-    Status descrambleStatus = Status::OK;
-    sp<IMemory> dataMemory;
+        Status descrambleStatus = Status::OK;
+        sp<IMemory> dataMemory;
 
-    ASSERT_TRUE(descrambleTestInputBuffer(descrambler, &descrambleStatus, &dataMemory));
-    EXPECT_EQ(Status::ERROR_CAS_DECRYPT_UNIT_NOT_INITIALIZED, descrambleStatus);
+        ASSERT_TRUE(descrambleTestInputBuffer(descrambler, &descrambleStatus, &dataMemory));
+        EXPECT_EQ(Status::ERROR_CAS_DECRYPT_UNIT_NOT_INITIALIZED, descrambleStatus);
 
-    // Now set a valid session, should still fail because no valid ecm is processed
-    returnStatus = mDescramblerBase->setMediaCasSession(sessionId);
-    EXPECT_TRUE(returnStatus.isOk());
-    EXPECT_EQ(Status::OK, returnStatus);
+        // Now set a valid session, should still fail because no valid ecm is processed
+        returnStatus = mDescramblerBase->setMediaCasSession(sessionId);
+        EXPECT_TRUE(returnStatus.isOk());
+        EXPECT_EQ(Status::OK, returnStatus);
 
-    ASSERT_TRUE(descrambleTestInputBuffer(descrambler, &descrambleStatus, &dataMemory));
-    EXPECT_EQ(Status::ERROR_CAS_DECRYPT, descrambleStatus);
+        ASSERT_TRUE(descrambleTestInputBuffer(descrambler, &descrambleStatus, &dataMemory));
+        EXPECT_EQ(Status::ERROR_CAS_DECRYPT, descrambleStatus);
 
-    // Verify that requiresSecureDecoderComponent handles empty mime
-    EXPECT_FALSE(mDescramblerBase->requiresSecureDecoderComponent(""));
+        // Verify that requiresSecureDecoderComponent handles empty mime
+        EXPECT_FALSE(mDescramblerBase->requiresSecureDecoderComponent(""));
 
-    // Verify that requiresSecureDecoderComponent handles invalid mime
-    EXPECT_FALSE(mDescramblerBase->requiresSecureDecoderComponent("bad"));
+        // Verify that requiresSecureDecoderComponent handles invalid mime
+        EXPECT_FALSE(mDescramblerBase->requiresSecureDecoderComponent("bad"));
+    }
 }
 
 TEST_P(MediaCasHidlTest, TestClearKeyOobFails) {
@@ -700,9 +720,11 @@
     std::vector<uint8_t> sessionId;
     ASSERT_TRUE(openCasSession(&sessionId));
 
-    returnStatus = mDescramblerBase->setMediaCasSession(sessionId);
-    EXPECT_TRUE(returnStatus.isOk());
-    EXPECT_EQ(Status::OK, returnStatus);
+    if (mIsTestDescrambler) {
+        returnStatus = mDescramblerBase->setMediaCasSession(sessionId);
+        EXPECT_TRUE(returnStatus.isOk());
+        EXPECT_EQ(Status::OK, returnStatus);
+    }
 
     hidl_vec<uint8_t> hidlEcm;
     hidlEcm.setToExternal(const_cast<uint8_t*>(kEcmBinaryBuffer), sizeof(kEcmBinaryBuffer));
@@ -710,126 +732,104 @@
     EXPECT_TRUE(returnStatus.isOk());
     EXPECT_EQ(Status::OK, returnStatus);
 
-    sp<IDescrambler> descrambler = IDescrambler::castFrom(mDescramblerBase);
-    ASSERT_NE(nullptr, descrambler.get());
+    if (mIsTestDescrambler) {
+        sp<IDescrambler> descrambler = IDescrambler::castFrom(mDescramblerBase);
+        ASSERT_NE(nullptr, descrambler.get());
 
-    Status descrambleStatus = Status::OK;
+        Status descrambleStatus = Status::OK;
 
-    // test invalid src buffer offset
-    ASSERT_TRUE(descrambleTestOobInput(
-            descrambler,
-            &descrambleStatus,
-            {
-                .subSamples     = kSubSamples,
-                .numSubSamples  = sizeof(kSubSamples)/sizeof(SubSample),
-                .imemSizeActual = sizeof(kInBinaryBuffer),
-                .imemOffset     = 0xcccccc,
-                .imemSize       = sizeof(kInBinaryBuffer),
-                .srcOffset      = 0,
-                .dstOffset      = 0
-            }));
-    EXPECT_EQ(Status::BAD_VALUE, descrambleStatus);
+        // test invalid src buffer offset
+        ASSERT_TRUE(
+                descrambleTestOobInput(descrambler, &descrambleStatus,
+                                       {.subSamples = kSubSamples,
+                                        .numSubSamples = sizeof(kSubSamples) / sizeof(SubSample),
+                                        .imemSizeActual = sizeof(kInBinaryBuffer),
+                                        .imemOffset = 0xcccccc,
+                                        .imemSize = sizeof(kInBinaryBuffer),
+                                        .srcOffset = 0,
+                                        .dstOffset = 0}));
+        EXPECT_EQ(Status::BAD_VALUE, descrambleStatus);
 
-    // test invalid src buffer size
-    ASSERT_TRUE(descrambleTestOobInput(
-            descrambler,
-            &descrambleStatus,
-            {
-                .subSamples     = kSubSamples,
-                .numSubSamples  = sizeof(kSubSamples)/sizeof(SubSample),
-                .imemSizeActual = sizeof(kInBinaryBuffer),
-                .imemOffset     = 0,
-                .imemSize       = 0xcccccc,
-                .srcOffset      = 0,
-                .dstOffset      = 0
-            }));
-    EXPECT_EQ(Status::BAD_VALUE, descrambleStatus);
+        // test invalid src buffer size
+        ASSERT_TRUE(
+                descrambleTestOobInput(descrambler, &descrambleStatus,
+                                       {.subSamples = kSubSamples,
+                                        .numSubSamples = sizeof(kSubSamples) / sizeof(SubSample),
+                                        .imemSizeActual = sizeof(kInBinaryBuffer),
+                                        .imemOffset = 0,
+                                        .imemSize = 0xcccccc,
+                                        .srcOffset = 0,
+                                        .dstOffset = 0}));
+        EXPECT_EQ(Status::BAD_VALUE, descrambleStatus);
 
-    // test invalid src buffer size
-    ASSERT_TRUE(descrambleTestOobInput(
-            descrambler,
-            &descrambleStatus,
-            {
-                .subSamples     = kSubSamples,
-                .numSubSamples  = sizeof(kSubSamples)/sizeof(SubSample),
-                .imemSizeActual = sizeof(kInBinaryBuffer),
-                .imemOffset     = 1,
-                .imemSize       = (uint64_t)-1,
-                .srcOffset      = 0,
-                .dstOffset      = 0
-            }));
-    EXPECT_EQ(Status::BAD_VALUE, descrambleStatus);
+        // test invalid src buffer size
+        ASSERT_TRUE(
+                descrambleTestOobInput(descrambler, &descrambleStatus,
+                                       {.subSamples = kSubSamples,
+                                        .numSubSamples = sizeof(kSubSamples) / sizeof(SubSample),
+                                        .imemSizeActual = sizeof(kInBinaryBuffer),
+                                        .imemOffset = 1,
+                                        .imemSize = (uint64_t)-1,
+                                        .srcOffset = 0,
+                                        .dstOffset = 0}));
+        EXPECT_EQ(Status::BAD_VALUE, descrambleStatus);
 
-    // test invalid srcOffset
-    ASSERT_TRUE(descrambleTestOobInput(
-            descrambler,
-            &descrambleStatus,
-            {
-                .subSamples     = kSubSamples,
-                .numSubSamples  = sizeof(kSubSamples)/sizeof(SubSample),
-                .imemSizeActual = sizeof(kInBinaryBuffer),
-                .imemOffset     = 0,
-                .imemSize       = sizeof(kInBinaryBuffer),
-                .srcOffset      = 0xcccccc,
-                .dstOffset      = 0
-            }));
-    EXPECT_EQ(Status::BAD_VALUE, descrambleStatus);
+        // test invalid srcOffset
+        ASSERT_TRUE(
+                descrambleTestOobInput(descrambler, &descrambleStatus,
+                                       {.subSamples = kSubSamples,
+                                        .numSubSamples = sizeof(kSubSamples) / sizeof(SubSample),
+                                        .imemSizeActual = sizeof(kInBinaryBuffer),
+                                        .imemOffset = 0,
+                                        .imemSize = sizeof(kInBinaryBuffer),
+                                        .srcOffset = 0xcccccc,
+                                        .dstOffset = 0}));
+        EXPECT_EQ(Status::BAD_VALUE, descrambleStatus);
 
-    // test invalid dstOffset
-    ASSERT_TRUE(descrambleTestOobInput(
-            descrambler,
-            &descrambleStatus,
-            {
-                .subSamples     = kSubSamples,
-                .numSubSamples  = sizeof(kSubSamples)/sizeof(SubSample),
-                .imemSizeActual = sizeof(kInBinaryBuffer),
-                .imemOffset     = 0,
-                .imemSize       = sizeof(kInBinaryBuffer),
-                .srcOffset      = 0,
-                .dstOffset      = 0xcccccc
-            }));
-    EXPECT_EQ(Status::BAD_VALUE, descrambleStatus);
+        // test invalid dstOffset
+        ASSERT_TRUE(
+                descrambleTestOobInput(descrambler, &descrambleStatus,
+                                       {.subSamples = kSubSamples,
+                                        .numSubSamples = sizeof(kSubSamples) / sizeof(SubSample),
+                                        .imemSizeActual = sizeof(kInBinaryBuffer),
+                                        .imemOffset = 0,
+                                        .imemSize = sizeof(kInBinaryBuffer),
+                                        .srcOffset = 0,
+                                        .dstOffset = 0xcccccc}));
+        EXPECT_EQ(Status::BAD_VALUE, descrambleStatus);
 
-    // test detection of oob subsample sizes
-    const SubSample invalidSubSamples1[] =
-        {{162, 0}, {0, 184}, {0, 0xdddddd}};
+        // test detection of oob subsample sizes
+        const SubSample invalidSubSamples1[] = {{162, 0}, {0, 184}, {0, 0xdddddd}};
 
-    ASSERT_TRUE(descrambleTestOobInput(
-            descrambler,
-            &descrambleStatus,
-            {
-                .subSamples     = invalidSubSamples1,
-                .numSubSamples  = sizeof(invalidSubSamples1)/sizeof(SubSample),
-                .imemSizeActual = sizeof(kInBinaryBuffer),
-                .imemOffset     = 0,
-                .imemSize       = sizeof(kInBinaryBuffer),
-                .srcOffset      = 0,
-                .dstOffset      = 0
-            }));
-    EXPECT_EQ(Status::BAD_VALUE, descrambleStatus);
+        ASSERT_TRUE(descrambleTestOobInput(
+                descrambler, &descrambleStatus,
+                {.subSamples = invalidSubSamples1,
+                 .numSubSamples = sizeof(invalidSubSamples1) / sizeof(SubSample),
+                 .imemSizeActual = sizeof(kInBinaryBuffer),
+                 .imemOffset = 0,
+                 .imemSize = sizeof(kInBinaryBuffer),
+                 .srcOffset = 0,
+                 .dstOffset = 0}));
+        EXPECT_EQ(Status::BAD_VALUE, descrambleStatus);
 
-    // test detection of overflowing subsample sizes
-    const SubSample invalidSubSamples2[] =
-        {{162, 0}, {0, 184}, {2, (uint32_t)-1}};
+        // test detection of overflowing subsample sizes
+        const SubSample invalidSubSamples2[] = {{162, 0}, {0, 184}, {2, (uint32_t)-1}};
 
-    ASSERT_TRUE(descrambleTestOobInput(
-            descrambler,
-            &descrambleStatus,
-            {
-                .subSamples     = invalidSubSamples2,
-                .numSubSamples  = sizeof(invalidSubSamples2)/sizeof(SubSample),
-                .imemSizeActual = sizeof(kInBinaryBuffer),
-                .imemOffset     = 0,
-                .imemSize       = sizeof(kInBinaryBuffer),
-                .srcOffset      = 0,
-                .dstOffset      = 0
-            }));
-    EXPECT_EQ(Status::BAD_VALUE, descrambleStatus);
+        ASSERT_TRUE(descrambleTestOobInput(
+                descrambler, &descrambleStatus,
+                {.subSamples = invalidSubSamples2,
+                 .numSubSamples = sizeof(invalidSubSamples2) / sizeof(SubSample),
+                 .imemSizeActual = sizeof(kInBinaryBuffer),
+                 .imemOffset = 0,
+                 .imemSize = sizeof(kInBinaryBuffer),
+                 .srcOffset = 0,
+                 .dstOffset = 0}));
+        EXPECT_EQ(Status::BAD_VALUE, descrambleStatus);
 
-    returnStatus = mDescramblerBase->release();
-    EXPECT_TRUE(returnStatus.isOk());
-    EXPECT_EQ(Status::OK, returnStatus);
-
+        returnStatus = mDescramblerBase->release();
+        EXPECT_TRUE(returnStatus.isOk());
+        EXPECT_EQ(Status::OK, returnStatus);
+    }
     returnStatus = mMediaCas->release();
     EXPECT_TRUE(returnStatus.isOk());
     EXPECT_EQ(Status::OK, returnStatus);
diff --git a/cas/1.1/vts/functional/Android.bp b/cas/1.1/vts/functional/Android.bp
index de223c8..0647d12a 100644
--- a/cas/1.1/vts/functional/Android.bp
+++ b/cas/1.1/vts/functional/Android.bp
@@ -21,6 +21,7 @@
     static_libs: [
         "android.hardware.cas@1.0",
         "android.hardware.cas@1.1",
+        "android.hardware.cas@1.2",
         "android.hardware.cas.native@1.0",
         "android.hidl.allocator@1.0",
         "android.hidl.memory@1.0",
diff --git a/cas/1.1/vts/functional/VtsHalCasV1_1TargetTest.cpp b/cas/1.1/vts/functional/VtsHalCasV1_1TargetTest.cpp
index b657f07..6797506 100644
--- a/cas/1.1/vts/functional/VtsHalCasV1_1TargetTest.cpp
+++ b/cas/1.1/vts/functional/VtsHalCasV1_1TargetTest.cpp
@@ -22,6 +22,7 @@
 #include <android/hardware/cas/1.1/ICas.h>
 #include <android/hardware/cas/1.1/ICasListener.h>
 #include <android/hardware/cas/1.1/IMediaCasService.h>
+#include <android/hardware/cas/1.2/IMediaCasService.h>
 #include <android/hardware/cas/native/1.0/IDescrambler.h>
 #include <android/hardware/cas/native/1.0/types.h>
 #include <binder/MemoryDealer.h>
@@ -255,6 +256,10 @@
 class MediaCasHidlTest : public testing::TestWithParam<std::string> {
   public:
     virtual void SetUp() override {
+        if (android::hardware::cas::V1_2::IMediaCasService::getService(GetParam()) == nullptr) {
+            ALOGI("Descrambler is need to be tested before cas@1.2.");
+            mIsTestDescrambler = true;
+        }
         mService = IMediaCasService::getService(GetParam());
         ASSERT_NE(mService, nullptr);
     }
@@ -269,6 +274,7 @@
     sp<ICas> mMediaCas;
     sp<IDescramblerBase> mDescramblerBase;
     sp<MediaCasListener> mCasListener;
+    bool mIsTestDescrambler = false;
     typedef struct _OobInputTestParams {
         const SubSample* subSamples;
         uint32_t numSubSamples;
@@ -311,8 +317,15 @@
 
     auto descramblerStatus = mService->createDescrambler(caSystemId);
     if (!descramblerStatus.isOk()) {
-        return ::testing::AssertionFailure();
+        if (mIsTestDescrambler) {
+            return ::testing::AssertionFailure();
+        } else {
+            ALOGI("Skip Descrambler test since it's not required in cas@1.2.");
+            return ::testing::AssertionSuccess();
+        }
     }
+    mIsTestDescrambler = true;
+
     mDescramblerBase = descramblerStatus;
     return ::testing::AssertionResult(mDescramblerBase != nullptr);
 }
@@ -468,13 +481,15 @@
     EXPECT_TRUE(returnStatus.isOk());
     EXPECT_EQ(Status::OK, returnStatus);
 
-    returnStatus = mDescramblerBase->setMediaCasSession(sessionId);
-    EXPECT_TRUE(returnStatus.isOk());
-    EXPECT_EQ(Status::OK, returnStatus);
+    if (mIsTestDescrambler) {
+        returnStatus = mDescramblerBase->setMediaCasSession(sessionId);
+        EXPECT_TRUE(returnStatus.isOk());
+        EXPECT_EQ(Status::OK, returnStatus);
 
-    returnStatus = mDescramblerBase->setMediaCasSession(streamSessionId);
-    EXPECT_TRUE(returnStatus.isOk());
-    EXPECT_EQ(Status::OK, returnStatus);
+        returnStatus = mDescramblerBase->setMediaCasSession(streamSessionId);
+        EXPECT_TRUE(returnStatus.isOk());
+        EXPECT_EQ(Status::OK, returnStatus);
+    }
 
     hidl_vec<uint8_t> hidlNullPtr;
     hidlNullPtr.setToExternal(static_cast<uint8_t*>(nullptr), 0);
@@ -518,29 +533,31 @@
     EXPECT_TRUE(returnStatus.isOk());
     EXPECT_EQ(Status::OK, returnStatus);
 
-    EXPECT_FALSE(mDescramblerBase->requiresSecureDecoderComponent("video/avc"));
+    if (mIsTestDescrambler) {
+        EXPECT_FALSE(mDescramblerBase->requiresSecureDecoderComponent("video/avc"));
 
-    sp<IDescrambler> descrambler;
-    descrambler = IDescrambler::castFrom(mDescramblerBase);
-    ASSERT_NE(descrambler, nullptr);
+        sp<IDescrambler> descrambler;
+        descrambler = IDescrambler::castFrom(mDescramblerBase);
+        ASSERT_NE(descrambler, nullptr);
 
-    Status descrambleStatus = Status::OK;
-    sp<IMemory> dataMemory;
+        Status descrambleStatus = Status::OK;
+        sp<IMemory> dataMemory;
 
-    ASSERT_TRUE(descrambleTestInputBuffer(descrambler, &descrambleStatus, &dataMemory));
-    EXPECT_EQ(Status::OK, descrambleStatus);
+        ASSERT_TRUE(descrambleTestInputBuffer(descrambler, &descrambleStatus, &dataMemory));
+        EXPECT_EQ(Status::OK, descrambleStatus);
 
-    ASSERT_NE(nullptr, dataMemory.get());
-    uint8_t* opBuffer = static_cast<uint8_t*>(static_cast<void*>(dataMemory->unsecurePointer()));
+        ASSERT_NE(nullptr, dataMemory.get());
+        uint8_t* opBuffer = static_cast<uint8_t*>(static_cast<void*>(dataMemory->unsecurePointer()));
 
-    int compareResult =
-            memcmp(static_cast<const void*>(opBuffer),
-                   static_cast<const void*>(kOutRefBinaryBuffer), sizeof(kOutRefBinaryBuffer));
-    EXPECT_EQ(0, compareResult);
+        int compareResult =
+                memcmp(static_cast<const void*>(opBuffer),
+                       static_cast<const void*>(kOutRefBinaryBuffer), sizeof(kOutRefBinaryBuffer));
+        EXPECT_EQ(0, compareResult);
 
-    returnStatus = mDescramblerBase->release();
-    EXPECT_TRUE(returnStatus.isOk());
-    EXPECT_EQ(Status::OK, returnStatus);
+        returnStatus = mDescramblerBase->release();
+        EXPECT_TRUE(returnStatus.isOk());
+        EXPECT_EQ(Status::OK, returnStatus);
+    }
 
     returnStatus = mMediaCas->release();
     EXPECT_TRUE(returnStatus.isOk());
diff --git a/cas/1.2/vts/functional/VtsHalCasV1_2TargetTest.cpp b/cas/1.2/vts/functional/VtsHalCasV1_2TargetTest.cpp
index f436b8b..333dea6 100644
--- a/cas/1.2/vts/functional/VtsHalCasV1_2TargetTest.cpp
+++ b/cas/1.2/vts/functional/VtsHalCasV1_2TargetTest.cpp
@@ -311,6 +311,7 @@
     sp<ICas> mMediaCas;
     sp<IDescramblerBase> mDescramblerBase;
     sp<MediaCasListener> mCasListener;
+    bool mIsTestDescrambler = false;
     typedef struct _OobInputTestParams {
         const SubSample* subSamples;
         uint32_t numSubSamples;
@@ -355,8 +356,11 @@
 
     auto descramblerStatus = mService->createDescrambler(caSystemId);
     if (!descramblerStatus.isOk()) {
-        return ::testing::AssertionFailure();
+        ALOGI("Skip Descrambler test since it's not required in cas@1.2.");
+        return ::testing::AssertionSuccess();
     }
+    mIsTestDescrambler = true;
+
     mDescramblerBase = descramblerStatus;
     return ::testing::AssertionResult(mDescramblerBase != nullptr);
 }
@@ -512,14 +516,15 @@
     EXPECT_TRUE(returnStatus.isOk());
     EXPECT_EQ(Status::OK, returnStatus);
 
-    returnStatus = mDescramblerBase->setMediaCasSession(sessionId);
-    EXPECT_TRUE(returnStatus.isOk());
-    EXPECT_EQ(Status::OK, returnStatus);
+    if (mIsTestDescrambler) {
+        returnStatus = mDescramblerBase->setMediaCasSession(sessionId);
+        EXPECT_TRUE(returnStatus.isOk());
+        EXPECT_EQ(Status::OK, returnStatus);
 
-    returnStatus = mDescramblerBase->setMediaCasSession(streamSessionId);
-    EXPECT_TRUE(returnStatus.isOk());
-    EXPECT_EQ(Status::OK, returnStatus);
-
+        returnStatus = mDescramblerBase->setMediaCasSession(streamSessionId);
+        EXPECT_TRUE(returnStatus.isOk());
+        EXPECT_EQ(Status::OK, returnStatus);
+    }
     hidl_vec<uint8_t> hidlNullPtr;
     hidlNullPtr.setToExternal(static_cast<uint8_t*>(nullptr), 0);
     returnStatus = mMediaCas->refreshEntitlements(3, hidlNullPtr);
@@ -566,29 +571,31 @@
     EXPECT_TRUE(returnStatus.isOk());
     EXPECT_EQ(Status::OK, returnStatus);
 
-    EXPECT_FALSE(mDescramblerBase->requiresSecureDecoderComponent("video/avc"));
+    if (mIsTestDescrambler) {
+        EXPECT_FALSE(mDescramblerBase->requiresSecureDecoderComponent("video/avc"));
 
-    sp<IDescrambler> descrambler;
-    descrambler = IDescrambler::castFrom(mDescramblerBase);
-    ASSERT_NE(descrambler, nullptr);
+        sp<IDescrambler> descrambler;
+        descrambler = IDescrambler::castFrom(mDescramblerBase);
+        ASSERT_NE(descrambler, nullptr);
 
-    Status descrambleStatus = Status::OK;
-    sp<IMemory> dataMemory;
+        Status descrambleStatus = Status::OK;
+        sp<IMemory> dataMemory;
 
-    ASSERT_TRUE(descrambleTestInputBuffer(descrambler, &descrambleStatus, &dataMemory));
-    EXPECT_EQ(Status::OK, descrambleStatus);
+        ASSERT_TRUE(descrambleTestInputBuffer(descrambler, &descrambleStatus, &dataMemory));
+        EXPECT_EQ(Status::OK, descrambleStatus);
 
-    ASSERT_NE(nullptr, dataMemory.get());
-    uint8_t* opBuffer = static_cast<uint8_t*>(static_cast<void*>(dataMemory->unsecurePointer()));
+        ASSERT_NE(nullptr, dataMemory.get());
+        uint8_t* opBuffer = static_cast<uint8_t*>(static_cast<void*>(dataMemory->unsecurePointer()));
 
-    int compareResult =
-            memcmp(static_cast<const void*>(opBuffer),
-                   static_cast<const void*>(kOutRefBinaryBuffer), sizeof(kOutRefBinaryBuffer));
-    EXPECT_EQ(0, compareResult);
+        int compareResult =
+                memcmp(static_cast<const void*>(opBuffer),
+                       static_cast<const void*>(kOutRefBinaryBuffer), sizeof(kOutRefBinaryBuffer));
+        EXPECT_EQ(0, compareResult);
 
-    returnStatus = mDescramblerBase->release();
-    EXPECT_TRUE(returnStatus.isOk());
-    EXPECT_EQ(Status::OK, returnStatus);
+        returnStatus = mDescramblerBase->release();
+        EXPECT_TRUE(returnStatus.isOk());
+        EXPECT_EQ(Status::OK, returnStatus);
+    }
 
     returnStatus = mMediaCas->release();
     EXPECT_TRUE(returnStatus.isOk());
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index 609d78d..b8676b0 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -27,6 +27,14 @@
             <instance>default</instance>
         </interface>
     </hal>
+    <hal format="aidl" optional="true">
+         <name>android.hardware.authsecret</name>
+         <version>1</version>
+         <interface>
+             <name>IAuthSecret</name>
+             <instance>default</instance>
+         </interface>
+    </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.authsecret</name>
         <version>1.0</version>
@@ -286,6 +294,14 @@
             <instance>default</instance>
         </interface>
     </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.oemlock</name>
+        <version>1</version>
+        <interface>
+            <name>IOemLock</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.ir</name>
         <version>1.0</version>
@@ -469,6 +485,20 @@
             <regex-instance>SIM[1-9][0-9]*</regex-instance>
         </interface>
     </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.security.secureclock</name>
+        <interface>
+            <name>ISecureClock</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.security.sharedsecret</name>
+        <interface>
+            <name>ISharedSecret</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.sensors</name>
         <version>1.0</version>
@@ -553,6 +583,7 @@
     </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.vibrator</name>
+        <version>1-2</version>
         <interface>
             <name>IVibrator</name>
             <instance>default</instance>
diff --git a/contexthub/1.0/IContexthub.hal b/contexthub/1.0/IContexthub.hal
index 8dccd67..950e081 100644
--- a/contexthub/1.0/IContexthub.hal
+++ b/contexthub/1.0/IContexthub.hal
@@ -41,7 +41,7 @@
      * registration.
      *
      * @param hubId    identifier for the hub
-     *        callback an implementation of the IContextHubCallbacks
+     * @param callback an implementation of the IContextHubCallbacks
      *
      * @return result OK on success
      *                BAD_VALUE if parameters are not sane
@@ -53,7 +53,7 @@
      * Send a message to a hub
      *
      * @param hubId identifier for hub to send message to
-     *        msg   message to be sent
+     * @param msg   message to be sent
      *
      * @return result OK if successful, error code otherwise
      *                BAD_VALUE if parameters are not sane
@@ -77,9 +77,9 @@
      * device.
      *
      * @param hubId identifer of the contextHub
-     *        appBinary contains the binary representation of the nanoApp, plus
+     * @param appBinary contains the binary representation of the nanoApp, plus
      *                  metadata
-     *        transactionId transactionId for this call
+     * @param transactionId transactionId for this call
      *
      * @return result OK if transation started
      *                BAD_VALUE if parameters are not sane
@@ -101,8 +101,8 @@
      * Unloading a nanoapp must not take more than 5 seconds.
      *
      * @param hubId identifer of the contextHub
-     *        appId appIdentifier returned by the HAL
-     *        msg   message to be sent
+     * @param appId appIdentifier returned by the HAL
+     * @param msg   message to be sent
      *
      * @return result OK if transation started
      *                BAD_VALUE if parameters are not sane
@@ -122,8 +122,8 @@
      * Enabling a nanoapp must not take more than 5 seconds.
      *
      * @param hubId identifer of the contextHub
-     *        appId appIdentifier returned by the HAL
-     *        msg   message to be sent
+     * @param appId appIdentifier returned by the HAL
+     * @param msg   message to be sent
      *
      * @return result OK if transation started
      *                BAD_VALUE if parameters are not sane
@@ -143,8 +143,8 @@
      * Disabling a nanoapp must not take more than 5 seconds.
      *
      * @param hubId identifer of the contextHub
-     *        appId appIdentifier returned by the HAL
-     *        msg   message to be sent
+     * @param appId appIdentifier returned by the HAL
+     * @param msg   message to be sent
      *
      * @return result OK if transation started
      *                BAD_VALUE if parameters are not sane
diff --git a/contexthub/1.0/IContexthubCallback.hal b/contexthub/1.0/IContexthubCallback.hal
index 264f84c..70750f8 100644
--- a/contexthub/1.0/IContexthubCallback.hal
+++ b/contexthub/1.0/IContexthubCallback.hal
@@ -22,7 +22,7 @@
      * implementation to allow the HAL to send asynchronous messages back
      * to the service and registered clients of the ContextHub service.
      *
-     * @params msg : message
+     * @param msg message being sent from the contexthub
      *
      */
      handleClientMsg(ContextHubMsg msg);
@@ -32,9 +32,9 @@
      * implementation to allow the HAL to send the response for a
      * transaction.
      *
-     * @params txnId : transaction id whose result is being sent
-     *                 passed in by the service at start of transacation.
-     *         result: result of transaction.
+     * @param txnId transaction id whose result is being sent
+     *              passed in by the service at start of transacation.
+     * @param result result of transaction.
      *
      */
      handleTxnResult(uint32_t txnId, TransactionResult result);
@@ -44,7 +44,7 @@
      * implementation to allow the HAL to send an asynchronous event
      * to the ContextHub service.
      *
-     * @params msg : message
+     * @param evt event being sent from the contexthub
      *
      */
      handleHubEvent(AsyncEventType evt);
@@ -55,8 +55,8 @@
      * that a nanp-app has aborted.
      * This method must be called when a nanoapp invokes chreAbort(...)).
      *
-     * @params appId : app identifier
-     *               : abortCode code passed by the nanoApp.
+     * @param appId app identifier
+     * @param abortCode code passed by the nanoApp.
      *
      * Also see chreAbort(...)
      *
@@ -68,12 +68,11 @@
       * implementation to allow the HAL to send information about the
       * currently loaded and active nanoapps on the hub.
       *
-      * @params appInfo : vector of HubAppinfo structure for each nanoApp
-      *                   on the hub that can be enabled, disabled and
-      *                   unloaded by the service. Any nanoApps that cannot
-      *                   be controlled by the service must not be reported.
-      *                   All nanoApps that can be controlled by the service
-      *                   must be reported.
+      * @param appInfo vector of HubAppinfo structure for each nanoApp on the
+      *                hub that can be enabled, disabled and unloaded by the
+      *                service. Any nanoApps that cannot be controlled by the
+      *                service must not be reported. All nanoApps that can be
+      *                controlled by the service must be reported.
       */
       handleAppsInfo(vec<HubAppInfo> appInfo);
 };
diff --git a/contexthub/1.2/types.hal b/contexthub/1.2/types.hal
index e6c8acc..5a11efe 100644
--- a/contexthub/1.2/types.hal
+++ b/contexthub/1.2/types.hal
@@ -33,6 +33,12 @@
      */
     WIFI_AVAILABLE,
     AIRPLANE_MODE,
+
+    /**
+     * Indicates if the microphone access was turned off globally by the user,
+     * in which case audio data cannot be used and propagated by CHRE.
+     */
+    GLOBAL_MIC_DISABLE,
 };
 
 struct ContextHubMsg {
diff --git a/contexthub/1.2/vts/functional/VtsHalContexthubV1_2TargetTest.cpp b/contexthub/1.2/vts/functional/VtsHalContexthubV1_2TargetTest.cpp
index 77883c2..782edae 100644
--- a/contexthub/1.2/vts/functional/VtsHalContexthubV1_2TargetTest.cpp
+++ b/contexthub/1.2/vts/functional/VtsHalContexthubV1_2TargetTest.cpp
@@ -62,6 +62,13 @@
     ASSERT_OK(registerCallback(nullptr));
 }
 
+TEST_P(ContexthubHidlTest, TestOnGlobalMicDisableSettingChanged) {
+    ASSERT_OK(registerCallback(new ContexthubCallbackBase()));
+    hubApi->onSettingChanged_1_2(Setting::GLOBAL_MIC_DISABLE, SettingValue::DISABLED);
+    hubApi->onSettingChanged_1_2(Setting::GLOBAL_MIC_DISABLE, SettingValue::ENABLED);
+    ASSERT_OK(registerCallback(nullptr));
+}
+
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ContexthubHidlTest);
 INSTANTIATE_TEST_SUITE_P(HubIdSpecificTests, ContexthubHidlTest, testing::ValuesIn(kTestParameters),
                          android::hardware::PrintInstanceTupleNameToString<>);
diff --git a/current.txt b/current.txt
index 0b88a7a..bf6829a 100644
--- a/current.txt
+++ b/current.txt
@@ -767,6 +767,8 @@
 98592d193a717066facf91428426e5abe211e3bd718bc372e29fb944ddbe6e7c android.hardware.wifi.supplicant@1.3::types
 
 # ABI preserving changes to HALs during Android S
+e042522daa4b5f7fd4a0a19bcdadb93c79a1b04c09ef2c9813a3a8941032f3f5 android.hardware.contexthub@1.0::IContexthub
+c2f64133b83ede65c9939ef97ab5bd867b73faf3dba0e7e69f77c3c43d9e487e android.hardware.contexthub@1.0::IContexthubCallback
 1ca372cd67d197df099e87616a613ba6ede6552638a603e18f86c8834302c3d1 android.hardware.gnss@1.0::IGnssMeasurementCallback
 6a271e493907e8ba20912e42771bd0d99ae45431a851d5675ef9496d02510a34 android.hardware.gnss@1.1::IGnssMeasurementCallback
 2c331a9605f3a08d9c1e0a36169ca57758bc43c11a78ef3f3730509885e52c15 android.hardware.graphics.composer@2.4::IComposerClient
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/BlocklistedSource.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/BlocklistedSource.aidl
index 89f5d53..0302676 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/BlocklistedSource.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/BlocklistedSource.aidl
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/CorrelationVector.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/CorrelationVector.aidl
new file mode 100644
index 0000000..1f713fa
--- /dev/null
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/CorrelationVector.aidl
@@ -0,0 +1,26 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.gnss;
+@VintfStability
+parcelable CorrelationVector {
+  int frequencyOffsetMps;
+  double samplingWidthM;
+  double samplingStartM;
+  int[] magnitude;
+}
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/ElapsedRealtime.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/ElapsedRealtime.aidl
index a0e8de4..933f659 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/ElapsedRealtime.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/ElapsedRealtime.aidl
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssClock.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssClock.aidl
index 42b940e..53ac0ef 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssClock.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssClock.aidl
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssConstellationType.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssConstellationType.aidl
index 30d0227..18fdfa9 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssConstellationType.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssConstellationType.aidl
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssData.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssData.aidl
index 7ffabd2..73ead10 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssData.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssData.aidl
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssMeasurement.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssMeasurement.aidl
index 73d8a86..3d287e4 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssMeasurement.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssMeasurement.aidl
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
@@ -42,6 +43,8 @@
   double fullInterSignalBiasUncertaintyNs;
   double satelliteInterSignalBiasNs;
   double satelliteInterSignalBiasUncertaintyNs;
+  android.hardware.gnss.SatellitePvt satellitePvt;
+  android.hardware.gnss.CorrelationVector[] correlationVectors;
   const int HAS_SNR = 1;
   const int HAS_CARRIER_FREQUENCY = 512;
   const int HAS_CARRIER_CYCLES = 1024;
@@ -52,6 +55,8 @@
   const int HAS_FULL_ISB_UNCERTAINTY = 131072;
   const int HAS_SATELLITE_ISB = 262144;
   const int HAS_SATELLITE_ISB_UNCERTAINTY = 524288;
+  const int HAS_SATELLITE_PVT = 1048576;
+  const int HAS_CORRELATION_VECTOR = 2097152;
   const int STATE_UNKNOWN = 0;
   const int STATE_CODE_LOCK = 1;
   const int STATE_BIT_SYNC = 2;
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssMultipathIndicator.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssMultipathIndicator.aidl
index 75ca3af..5da60f7 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssMultipathIndicator.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssMultipathIndicator.aidl
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssPowerStats.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssPowerStats.aidl
index d385fd4..358b570 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssPowerStats.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssPowerStats.aidl
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssSignalType.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssSignalType.aidl
index f10b943..b2a498d 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssSignalType.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssSignalType.aidl
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnss.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnss.aidl
index 10ac150..bd6f1ff 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnss.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnss.aidl
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssCallback.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssCallback.aidl
index 62870d6..a0c4255 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssCallback.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssCallback.aidl
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
@@ -19,5 +20,7 @@
 @VintfStability
 interface IGnssCallback {
   void gnssSetCapabilitiesCb(in int capabilities);
-  const int CAPABILITY_SATELLITE_BLOCKLIST = 1;
+  const int CAPABILITY_SATELLITE_BLOCKLIST = 512;
+  const int CAPABILITY_CORRELATION_VECTOR = 4096;
+  const int CAPABILITY_SATELLITE_PVT = 8192;
 }
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssConfiguration.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssConfiguration.aidl
index 5af30cf..eb4ad82 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssConfiguration.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssConfiguration.aidl
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssMeasurementCallback.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssMeasurementCallback.aidl
index e05e9b9..764b896 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssMeasurementCallback.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssMeasurementCallback.aidl
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssMeasurementInterface.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssMeasurementInterface.aidl
index 9576205..7cb7395 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssMeasurementInterface.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssMeasurementInterface.aidl
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
@@ -18,6 +19,6 @@
 package android.hardware.gnss;
 @VintfStability
 interface IGnssMeasurementInterface {
-  void setCallback(in android.hardware.gnss.IGnssMeasurementCallback callback, in boolean enableFullTracking);
+  void setCallback(in android.hardware.gnss.IGnssMeasurementCallback callback, in boolean enableFullTracking, in boolean enableCorrVecOutputs);
   void close();
 }
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPowerIndication.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPowerIndication.aidl
index 843489e..c44903e 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPowerIndication.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPowerIndication.aidl
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPowerIndicationCallback.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPowerIndicationCallback.aidl
index 5281d29..12e6762 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPowerIndicationCallback.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPowerIndicationCallback.aidl
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPsds.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPsds.aidl
index ddef928..cae2ea6 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPsds.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPsds.aidl
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPsdsCallback.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPsdsCallback.aidl
index 8413d2c..6888632 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPsdsCallback.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPsdsCallback.aidl
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/PsdsType.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/PsdsType.aidl
index 9d1984e..d348c63 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/PsdsType.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/PsdsType.aidl
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatelliteClockInfo.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatelliteClockInfo.aidl
new file mode 100644
index 0000000..bdba667
--- /dev/null
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatelliteClockInfo.aidl
@@ -0,0 +1,25 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.gnss;
+@VintfStability
+parcelable SatelliteClockInfo {
+  double satHardwareCodeBiasMeters;
+  double satTimeCorrectionMeters;
+  double satClkDriftMps;
+}
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatellitePositionEcef.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatellitePositionEcef.aidl
new file mode 100644
index 0000000..550fa4d
--- /dev/null
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatellitePositionEcef.aidl
@@ -0,0 +1,26 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.gnss;
+@VintfStability
+parcelable SatellitePositionEcef {
+  double posXMeters;
+  double posYMeters;
+  double posZMeters;
+  double ureMeters;
+}
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatellitePvt.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatellitePvt.aidl
new file mode 100644
index 0000000..4ff025e
--- /dev/null
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatellitePvt.aidl
@@ -0,0 +1,27 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.gnss;
+@VintfStability
+parcelable SatellitePvt {
+  android.hardware.gnss.SatellitePositionEcef satPosEcef;
+  android.hardware.gnss.SatelliteVelocityEcef satVelEcef;
+  android.hardware.gnss.SatelliteClockInfo satClockInfo;
+  double ionoDelayMeters;
+  double tropoDelayMeters;
+}
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatelliteVelocityEcef.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatelliteVelocityEcef.aidl
new file mode 100644
index 0000000..7db7ee6
--- /dev/null
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatelliteVelocityEcef.aidl
@@ -0,0 +1,26 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.gnss;
+@VintfStability
+parcelable SatelliteVelocityEcef {
+  double velXMps;
+  double velYMps;
+  double velZMps;
+  double ureRateMps;
+}
diff --git a/gnss/aidl/android/hardware/gnss/CorrelationVector.aidl b/gnss/aidl/android/hardware/gnss/CorrelationVector.aidl
new file mode 100644
index 0000000..22a80ce
--- /dev/null
+++ b/gnss/aidl/android/hardware/gnss/CorrelationVector.aidl
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.gnss;
+
+/**
+ * Contains info about the correlation output of incoming GNSS signal and a local copy of
+ * its corresponding spreading code at a given frequency offset.
+ */
+@VintfStability
+parcelable CorrelationVector {
+
+    /**
+     * Frequency offset from reported pseudorange rate for this Correlation Vector.
+     */
+    int frequencyOffsetMps;
+
+    /**
+     * Space between correlation samples in meters.
+     */
+    double samplingWidthM;
+
+    /**
+     * Offset of the first sampling bin in meters.
+     * The following sampling bins are located at positive offsets from this value as follows:
+     * samplingStartM, samplingStartM + samplingWidthM, ... , samplingStartM +
+     * (magnitude.size-1) * samplingWidthM.
+     */
+    double samplingStartM;
+
+    /**
+     * Normalized correlation magnitude values from -1 to 1, the reported value must be encoded as
+     * signed 16 bit integer where 1 is represented by 32767 and -1 is represented by -32768.
+     *
+     * The length of the array is defined by the GNSS chipset.
+     */
+    int[] magnitude;
+}
\ No newline at end of file
diff --git a/gnss/aidl/android/hardware/gnss/GnssMeasurement.aidl b/gnss/aidl/android/hardware/gnss/GnssMeasurement.aidl
index ce88647..2c56a41 100644
--- a/gnss/aidl/android/hardware/gnss/GnssMeasurement.aidl
+++ b/gnss/aidl/android/hardware/gnss/GnssMeasurement.aidl
@@ -16,8 +16,10 @@
 
 package android.hardware.gnss;
 
+import android.hardware.gnss.CorrelationVector;
 import android.hardware.gnss.GnssSignalType;
 import android.hardware.gnss.GnssMultipathIndicator;
+import android.hardware.gnss.SatellitePvt;
 
 /**
  * Represents a GNSS Measurement, it contains raw and computed information.
@@ -57,6 +59,14 @@
      * GnssMeasurement.
      */
     const int HAS_SATELLITE_ISB_UNCERTAINTY  = 1 << 19;
+    /**
+     * Bit mask indicating a valid satellite PVT is stored in the GnssMeasurement.
+     */
+    const int HAS_SATELLITE_PVT              = 1 << 20;
+    /**
+     * Bit mask indicating valid correlation vectors are stored in the GnssMeasurement.
+     */
+    const int HAS_CORRELATION_VECTOR         = 1 << 21;
 
     /**
      * A bitfield of flags indicating the validity of the fields in this GnssMeasurement. The bit
@@ -612,4 +622,21 @@
      * 1-sigma uncertainty associated with the satellite inter-signal bias in nanoseconds.
      */
     double satelliteInterSignalBiasUncertaintyNs;
+
+    /**
+     * The GNSS satellite position, velocity and time information at the signal transmission time
+     * receivedSvTimeInNs.
+     *
+     * If the data is available, gnssMeasurementFlags must contain HAS_SATELLITE_PVT.
+     */
+    SatellitePvt satellitePvt;
+
+    /**
+     * A list of Correlation Vectors with each vector corresponding to a frequency offset.
+     *
+     * To represent correlation values over a 2D spaces (delay and frequency), a CorrelationVector
+     * is required per frequency offset, and each CorrelationVector contains correlation values
+     * at equally spaced spatial offsets.
+     */
+    CorrelationVector[] correlationVectors;
 }
\ No newline at end of file
diff --git a/gnss/aidl/android/hardware/gnss/IGnssCallback.aidl b/gnss/aidl/android/hardware/gnss/IGnssCallback.aidl
index a46a018..8881ea7 100644
--- a/gnss/aidl/android/hardware/gnss/IGnssCallback.aidl
+++ b/gnss/aidl/android/hardware/gnss/IGnssCallback.aidl
@@ -27,8 +27,14 @@
 @VintfStability
 interface IGnssCallback {
 
-    /** Capability bit mask indicating GNSS supports blocklisting satellites */
-    const int CAPABILITY_SATELLITE_BLOCKLIST = 1 << 0;
+    /** Capability bit mask indicating that GNSS supports blocklisting satellites */
+    const int CAPABILITY_SATELLITE_BLOCKLIST = 1 << 9;
+
+    /** Capability bit mask indicating that GNSS supports correlation vector */
+    const int CAPABILITY_CORRELATION_VECTOR =  1 << 12;
+
+    /** Capability bit mask indicating that GNSS supports satellite PVT */
+    const int CAPABILITY_SATELLITE_PVT       = 1 << 13;
 
     /**
      * Callback to inform framework of the GNSS HAL implementation's capabilities.
@@ -36,4 +42,4 @@
      * @param capabilities Capability parameter is a bit field of the Capability bit masks.
      */
     void gnssSetCapabilitiesCb(in int capabilities);
-}
\ No newline at end of file
+}
diff --git a/gnss/aidl/android/hardware/gnss/IGnssMeasurementInterface.aidl b/gnss/aidl/android/hardware/gnss/IGnssMeasurementInterface.aidl
index fdeebde..04cdf64 100644
--- a/gnss/aidl/android/hardware/gnss/IGnssMeasurementInterface.aidl
+++ b/gnss/aidl/android/hardware/gnss/IGnssMeasurementInterface.aidl
@@ -37,12 +37,16 @@
      *     The GNSS chipset is allowed to consume more power in this mode. If false, API must
      *     optimize power via duty cycling, constellations and frequency limits, etc.
      *
+     * @param enableCorrVecOutputs If true, enable correlation vectors as part of the raw GNSS
+     *     measurements outputs. If false, disable correlation vectors.
+     *
      * @return initRet Returns SUCCESS if successful. Returns ERROR_ALREADY_INIT if a callback has
      *     already been registered without a corresponding call to 'close'. Returns ERROR_GENERIC
      *     for any other error. The HAL must not generate any other updates upon returning this
      *     error code.
      */
-    void setCallback(in IGnssMeasurementCallback callback, in boolean enableFullTracking);
+    void setCallback(in IGnssMeasurementCallback callback, in boolean enableFullTracking,
+                     in boolean enableCorrVecOutputs);
 
     /**
      * Stops updates from the HAL, and unregisters the callback routines. After a call to close(),
diff --git a/gnss/aidl/android/hardware/gnss/SatelliteClockInfo.aidl b/gnss/aidl/android/hardware/gnss/SatelliteClockInfo.aidl
new file mode 100644
index 0000000..844fd1c
--- /dev/null
+++ b/gnss/aidl/android/hardware/gnss/SatelliteClockInfo.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.gnss;
+
+/**
+ * Contains estimates of the satellite clock info.
+ */
+@VintfStability
+parcelable SatelliteClockInfo {
+    /**
+     * Satellite hardware code bias of the reported code type w.r.t
+     * ionosphere-free measurement in meters.
+     */
+    double satHardwareCodeBiasMeters;
+
+    /**
+     * Satellite time correction for ionospheric-free signal measurement
+     * (meters). The satellite clock correction for the given signal type
+     * = satTimeCorrectionMeters - satHardwareCodeBiasMeters.
+     */
+    double satTimeCorrectionMeters;
+
+    /** Satellite clock drift (meters per second). */
+    double satClkDriftMps;
+}
\ No newline at end of file
diff --git a/gnss/aidl/android/hardware/gnss/SatellitePositionEcef.aidl b/gnss/aidl/android/hardware/gnss/SatellitePositionEcef.aidl
new file mode 100644
index 0000000..4b3615e
--- /dev/null
+++ b/gnss/aidl/android/hardware/gnss/SatellitePositionEcef.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.gnss;
+
+/**
+ * Contains estimates of the satellite position fields in ECEF coordinate frame.
+ */
+@VintfStability
+parcelable SatellitePositionEcef {
+    /** Satellite position X in WGS84 ECEF (meters). */
+    double posXMeters;
+
+    /** Satellite position Y in WGS84 ECEF (meters). */
+    double posYMeters;
+
+    /** Satellite position Z in WGS84 ECEF (meters). */
+    double posZMeters;
+
+    /**
+     * The Signal in Space User Range Error (URE) (meters).
+     *
+     * It covers satellite position and clock errors projected to the pseudorange measurements.
+     */
+    double ureMeters;
+}
\ No newline at end of file
diff --git a/gnss/aidl/android/hardware/gnss/SatellitePvt.aidl b/gnss/aidl/android/hardware/gnss/SatellitePvt.aidl
new file mode 100644
index 0000000..ea55f0c
--- /dev/null
+++ b/gnss/aidl/android/hardware/gnss/SatellitePvt.aidl
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.gnss;
+
+import android.hardware.gnss.SatellitePositionEcef;
+import android.hardware.gnss.SatelliteVelocityEcef;
+import android.hardware.gnss.SatelliteClockInfo;
+
+/**
+ * Contains estimates of the satellite position, velocity and time in the
+ * ECEF coordinate frame.
+ */
+@VintfStability
+parcelable SatellitePvt {
+    /**
+     * Satellite position in WGS84 ECEF. See comments of
+     * SatellitePositionEcef for units.
+     */
+    SatellitePositionEcef satPosEcef;
+
+    /**
+     * Satellite velocity in WGS84 ECEF. See comments of
+     * SatelliteVelocityEcef for units.
+     */
+    SatelliteVelocityEcef satVelEcef;
+
+    /** Satellite clock bias and drift info. */
+    SatelliteClockInfo satClockInfo;
+
+    /** Ionospheric delay in meters. */
+    double ionoDelayMeters;
+
+    /** Tropospheric delay in meters. */
+    double tropoDelayMeters;
+}
\ No newline at end of file
diff --git a/gnss/aidl/android/hardware/gnss/SatelliteVelocityEcef.aidl b/gnss/aidl/android/hardware/gnss/SatelliteVelocityEcef.aidl
new file mode 100644
index 0000000..25ece3a
--- /dev/null
+++ b/gnss/aidl/android/hardware/gnss/SatelliteVelocityEcef.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.gnss;
+
+/**
+ * Contains estimates of the satellite velocity fields in the ECEF coordinate frame.
+ */
+@VintfStability
+parcelable SatelliteVelocityEcef {
+    /** Satellite velocity X in WGS84 ECEF (meters per second). */
+    double velXMps;
+
+    /** Satellite velocity Y in WGS84 ECEF (meters per second). */
+    double velYMps;
+
+    /** Satellite velocity Z in WGS84 ECEF (meters per second). */
+    double velZMps;
+
+    /**
+     * The Signal in Space User Range Error Rate (URE Rate) (meters per second).
+     *
+     * It covers satellite velocity error and Satellite clock drift
+     * projected to the pseudorange rate measurements.
+     */
+    double ureRateMps;
+}
\ No newline at end of file
diff --git a/gnss/aidl/default/Gnss.cpp b/gnss/aidl/default/Gnss.cpp
index 02bad60..435afa3 100644
--- a/gnss/aidl/default/Gnss.cpp
+++ b/gnss/aidl/default/Gnss.cpp
@@ -36,7 +36,10 @@
 
     sGnssCallback = callback;
 
-    int capabilities = (int)IGnssCallback::CAPABILITY_SATELLITE_BLOCKLIST;
+    int capabilities = (int)(IGnssCallback::CAPABILITY_SATELLITE_BLOCKLIST |
+                             IGnssCallback::CAPABILITY_SATELLITE_PVT |
+                             IGnssCallback::CAPABILITY_CORRELATION_VECTOR);
+
     auto status = sGnssCallback->gnssSetCapabilitiesCb(capabilities);
     if (!status.isOk()) {
         ALOGE("%s: Unable to invoke callback.gnssSetCapabilities", __func__);
diff --git a/gnss/aidl/default/GnssMeasurementInterface.cpp b/gnss/aidl/default/GnssMeasurementInterface.cpp
index d726d95..cae9499 100644
--- a/gnss/aidl/default/GnssMeasurementInterface.cpp
+++ b/gnss/aidl/default/GnssMeasurementInterface.cpp
@@ -34,8 +34,10 @@
 }
 
 ndk::ScopedAStatus GnssMeasurementInterface::setCallback(
-        const std::shared_ptr<IGnssMeasurementCallback>& callback, const bool enableFullTracking) {
-    ALOGD("setCallback: enableFullTracking: %d", (int)enableFullTracking);
+        const std::shared_ptr<IGnssMeasurementCallback>& callback, const bool enableFullTracking,
+        const bool enableCorrVecOutputs) {
+    ALOGD("setCallback: enableFullTracking: %d enableCorrVecOutputs: %d", (int)enableFullTracking,
+          (int)enableCorrVecOutputs);
     std::unique_lock<std::mutex> lock(mMutex);
     sCallback = callback;
 
@@ -43,7 +45,7 @@
         ALOGW("GnssMeasurement callback already set. Resetting the callback...");
         stop();
     }
-    start();
+    start(enableCorrVecOutputs);
 
     return ndk::ScopedAStatus::ok();
 }
@@ -56,12 +58,12 @@
     return ndk::ScopedAStatus::ok();
 }
 
-void GnssMeasurementInterface::start() {
+void GnssMeasurementInterface::start(const bool enableCorrVecOutputs) {
     ALOGD("start");
     mIsActive = true;
-    mThread = std::thread([this]() {
+    mThread = std::thread([this, enableCorrVecOutputs]() {
         while (mIsActive == true) {
-            auto measurement = Utils::getMockMeasurement();
+            auto measurement = Utils::getMockMeasurement(enableCorrVecOutputs);
             this->reportMeasurement(measurement);
 
             std::this_thread::sleep_for(std::chrono::milliseconds(mMinIntervalMillis));
diff --git a/gnss/aidl/default/GnssMeasurementInterface.h b/gnss/aidl/default/GnssMeasurementInterface.h
index 69cd871..db63515 100644
--- a/gnss/aidl/default/GnssMeasurementInterface.h
+++ b/gnss/aidl/default/GnssMeasurementInterface.h
@@ -29,11 +29,12 @@
     GnssMeasurementInterface();
     ~GnssMeasurementInterface();
     ndk::ScopedAStatus setCallback(const std::shared_ptr<IGnssMeasurementCallback>& callback,
-                                   const bool enableFullTracking) override;
+                                   const bool enableFullTracking,
+                                   const bool enableCorrVecOutputs) override;
     ndk::ScopedAStatus close() override;
 
   private:
-    void start();
+    void start(const bool enableCorrVecOutputs);
     void stop();
     void reportMeasurement(const GnssData&);
 
diff --git a/gnss/aidl/vts/gnss_hal_test_cases.cpp b/gnss/aidl/vts/gnss_hal_test_cases.cpp
index 857c742..ae0551d 100644
--- a/gnss/aidl/vts/gnss_hal_test_cases.cpp
+++ b/gnss/aidl/vts/gnss_hal_test_cases.cpp
@@ -69,14 +69,21 @@
  * 2. Sets a GnssMeasurementCallback, waits for a measurement, and verifies fields are valid.
  */
 TEST_P(GnssHalTest, TestGnssMeasurementExtension) {
+    const bool kIsCorrelationVectorSupported = aidl_gnss_cb_->last_capabilities_ &
+                                               (int)GnssCallbackAidl::CAPABILITY_CORRELATION_VECTOR;
     const int kFirstGnssMeasurementTimeoutSeconds = 10;
+
+    bool has_capability_satpvt = false;
+
     sp<IGnssMeasurementInterface> iGnssMeasurement;
     auto status = aidl_gnss_hal_->getExtensionGnssMeasurement(&iGnssMeasurement);
     ASSERT_TRUE(status.isOk());
     ASSERT_TRUE(iGnssMeasurement != nullptr);
 
     auto callback = sp<GnssMeasurementCallbackAidl>::make();
-    status = iGnssMeasurement->setCallback(callback, /* enableFullTracking= */ true);
+    status =
+            iGnssMeasurement->setCallback(callback, /* enableFullTracking= */ true,
+                                          /* enableCorrVecOutputs */ kIsCorrelationVectorSupported);
     ASSERT_TRUE(status.isOk());
 
     android::hardware::gnss::GnssData lastMeasurement;
@@ -102,6 +109,10 @@
                          GnssClock::HAS_FULL_BIAS | GnssClock::HAS_BIAS |
                          GnssClock::HAS_BIAS_UNCERTAINTY | GnssClock::HAS_DRIFT |
                          GnssClock::HAS_DRIFT_UNCERTAINTY));
+
+    if (aidl_gnss_cb_->last_capabilities_ & (int)GnssCallbackAidl::CAPABILITY_SATELLITE_PVT) {
+        has_capability_satpvt = true;
+    }
     for (const auto& measurement : lastMeasurement.measurements) {
         ASSERT_TRUE(
                 measurement.flags >= 0 &&
@@ -112,7 +123,41 @@
                          GnssMeasurement::HAS_AUTOMATIC_GAIN_CONTROL |
                          GnssMeasurement::HAS_FULL_ISB | GnssMeasurement::HAS_FULL_ISB_UNCERTAINTY |
                          GnssMeasurement::HAS_SATELLITE_ISB |
-                         GnssMeasurement::HAS_SATELLITE_ISB_UNCERTAINTY));
+                         GnssMeasurement::HAS_SATELLITE_ISB_UNCERTAINTY |
+                         GnssMeasurement::HAS_SATELLITE_PVT |
+                         GnssMeasurement::HAS_CORRELATION_VECTOR));
+
+        if ((measurement.flags & GnssMeasurement::HAS_SATELLITE_PVT) &&
+            (has_capability_satpvt == true)) {
+            ASSERT_TRUE(measurement.satellitePvt.satPosEcef.posXMeters >= -43000000 &&
+                        measurement.satellitePvt.satPosEcef.posXMeters <= 43000000);
+            ASSERT_TRUE(measurement.satellitePvt.satPosEcef.posYMeters >= -43000000 &&
+                        measurement.satellitePvt.satPosEcef.posYMeters <= 43000000);
+            ASSERT_TRUE(measurement.satellitePvt.satPosEcef.posZMeters >= -43000000 &&
+                        measurement.satellitePvt.satPosEcef.posZMeters <= 43000000);
+            ASSERT_TRUE(measurement.satellitePvt.satPosEcef.ureMeters > 0);
+            ASSERT_TRUE(measurement.satellitePvt.satVelEcef.velXMps >= -4000 &&
+                        measurement.satellitePvt.satVelEcef.velXMps <= 4000);
+            ASSERT_TRUE(measurement.satellitePvt.satVelEcef.velYMps >= -4000 &&
+                        measurement.satellitePvt.satVelEcef.velYMps <= 4000);
+            ASSERT_TRUE(measurement.satellitePvt.satVelEcef.velZMps >= -4000 &&
+                        measurement.satellitePvt.satVelEcef.velZMps <= 4000);
+            ASSERT_TRUE(measurement.satellitePvt.satVelEcef.ureRateMps > 0);
+        }
+
+        if (kIsCorrelationVectorSupported &&
+            measurement.flags & GnssMeasurement::HAS_CORRELATION_VECTOR) {
+            ASSERT_TRUE(measurement.correlationVectors.size() > 0);
+            for (const auto& correlationVector : measurement.correlationVectors) {
+                ASSERT_GE(correlationVector.frequencyOffsetMps, 0);
+                ASSERT_GT(correlationVector.samplingWidthM, 0);
+                ASSERT_GE(correlationVector.samplingStartM, 0);
+                ASSERT_TRUE(correlationVector.magnitude.size() > 0);
+                for (const auto& magnitude : correlationVector.magnitude) {
+                    ASSERT_TRUE(magnitude >= -32768 && magnitude <= 32767);
+                }
+            }
+        }
     }
 
     status = iGnssMeasurement->close();
diff --git a/gnss/common/utils/default/Utils.cpp b/gnss/common/utils/default/Utils.cpp
index 21282f4..ccc7145 100644
--- a/gnss/common/utils/default/Utils.cpp
+++ b/gnss/common/utils/default/Utils.cpp
@@ -140,7 +140,7 @@
     return gnssData;
 }
 
-GnssData Utils::getMockMeasurement() {
+GnssData Utils::getMockMeasurement(const bool enableCorrVecOutputs) {
     aidl::android::hardware::gnss::GnssSignalType signalType = {
             .constellation = aidl::android::hardware::gnss::GnssConstellationType::GLONASS,
             .carrierFrequencyHz = 1.59975e+09,
@@ -152,10 +152,10 @@
                      GnssMeasurement::HAS_CARRIER_PHASE_UNCERTAINTY |
                      GnssMeasurement::HAS_FULL_ISB | GnssMeasurement::HAS_FULL_ISB_UNCERTAINTY |
                      GnssMeasurement::HAS_SATELLITE_ISB |
-                     GnssMeasurement::HAS_SATELLITE_ISB_UNCERTAINTY,
+                     GnssMeasurement::HAS_SATELLITE_ISB_UNCERTAINTY |
+                     GnssMeasurement::HAS_SATELLITE_PVT,
             .svid = 13,
             .signalType = signalType,
-            .timeOffsetNs = 0.0,
             .receivedSvTimeInNs = 8195997131077,
             .receivedSvTimeUncertaintyInNs = 15,
             .antennaCN0DbHz = 30.0,
@@ -175,7 +175,20 @@
             .fullInterSignalBiasUncertaintyNs = 792.0,
             .satelliteInterSignalBiasNs = 233.9,
             .satelliteInterSignalBiasUncertaintyNs = 921.2,
-    };
+            .satellitePvt = {.satPosEcef = {.posXMeters = 10442993.1153328,
+                                            .posYMeters = -19926932.8051666,
+                                            .posZMeters = -12034295.0216203,
+                                            .ureMeters = 1000.2345678},
+                             .satVelEcef = {.velXMps = -478.667183715732,
+                                            .velYMps = 1580.68371984114,
+                                            .velZMps = -3030.52994449997,
+                                            .ureRateMps = 10.2345678},
+                             .satClockInfo = {.satHardwareCodeBiasMeters = 1.396983861923e-09,
+                                              .satTimeCorrectionMeters = -7113.08964331,
+                                              .satClkDriftMps = 0},
+                             .ionoDelayMeters = 3.069949602639317e-08,
+                             .tropoDelayMeters = 3.882265204404031},
+            .correlationVectors = {}};
 
     GnssClock clock = {.gnssClockFlags = GnssClock::HAS_FULL_BIAS | GnssClock::HAS_FULL_BIAS |
                                          GnssClock::HAS_BIAS_UNCERTAINTY | GnssClock::HAS_DRIFT |
@@ -196,6 +209,21 @@
             // or don't set the field.
             .timeUncertaintyNs = 1020400};
 
+    if (enableCorrVecOutputs) {
+        aidl::android::hardware::gnss::CorrelationVector correlationVector1 = {
+                .frequencyOffsetMps = 10,
+                .samplingWidthM = 30,
+                .samplingStartM = 0,
+                .magnitude = {0, 5000, 10000, 5000, 0, 0, 3000, 0}};
+        aidl::android::hardware::gnss::CorrelationVector correlationVector2 = {
+                .frequencyOffsetMps = 20,
+                .samplingWidthM = 30,
+                .samplingStartM = 0,
+                .magnitude = {0, 3000, 5000, 3000, 0, 0, 1000, 0}};
+        measurement.correlationVectors = {correlationVector1, correlationVector2};
+        measurement.flags |= GnssMeasurement::HAS_CORRELATION_VECTOR;
+    }
+
     GnssData gnssData = {
             .measurements = {measurement}, .clock = clock, .elapsedRealtime = timestamp};
     return gnssData;
diff --git a/gnss/common/utils/default/include/Utils.h b/gnss/common/utils/default/include/Utils.h
index 0ca1b00..771d39d 100644
--- a/gnss/common/utils/default/include/Utils.h
+++ b/gnss/common/utils/default/include/Utils.h
@@ -30,7 +30,8 @@
 namespace common {
 
 struct Utils {
-    static aidl::android::hardware::gnss::GnssData getMockMeasurement();
+    static aidl::android::hardware::gnss::GnssData getMockMeasurement(
+            const bool enableCorrVecOutputs);
     static V2_0::IGnssMeasurementCallback::GnssData getMockMeasurementV2_0();
     static V2_1::IGnssMeasurementCallback::GnssData getMockMeasurementV2_1();
     static V2_0::GnssLocation getMockLocationV2_0();
diff --git a/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Burst.h b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Burst.h
new file mode 100644
index 0000000..f2cbe93
--- /dev/null
+++ b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Burst.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_0_UTILS_BURST_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_0_UTILS_BURST_H
+
+#include <nnapi/IBurst.h>
+#include <nnapi/IPreparedModel.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+
+#include <memory>
+#include <optional>
+#include <utility>
+
+// See hardware/interfaces/neuralnetworks/utils/README.md for more information on HIDL interface
+// lifetimes across processes and for protecting asynchronous calls across HIDL.
+
+namespace android::hardware::neuralnetworks::V1_0::utils {
+
+// Class that adapts nn::IPreparedModel to nn::IBurst.
+class Burst final : public nn::IBurst {
+    struct PrivateConstructorTag {};
+
+  public:
+    static nn::GeneralResult<std::shared_ptr<const Burst>> create(
+            nn::SharedPreparedModel preparedModel);
+
+    Burst(PrivateConstructorTag tag, nn::SharedPreparedModel preparedModel);
+
+    OptionalCacheHold cacheMemory(const nn::Memory& memory) const override;
+
+    nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> execute(
+            const nn::Request& request, nn::MeasureTiming measure) const override;
+
+  private:
+    const nn::SharedPreparedModel kPreparedModel;
+};
+
+}  // namespace android::hardware::neuralnetworks::V1_0::utils
+
+#endif  // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_0_UTILS_BURST_H
diff --git a/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Device.h b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Device.h
index db3b2ad..4681b9e 100644
--- a/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Device.h
+++ b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Device.h
@@ -52,6 +52,7 @@
     const std::string& getVersionString() const override;
     nn::Version getFeatureLevel() const override;
     nn::DeviceType getType() const override;
+    bool isUpdatable() const override;
     const std::vector<nn::Extension>& getSupportedExtensions() const override;
     const nn::Capabilities& getCapabilities() const override;
     std::pair<uint32_t, uint32_t> getNumberOfCacheFilesNeeded() const override;
diff --git a/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/PreparedModel.h b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/PreparedModel.h
index 2de1828..8853eea 100644
--- a/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/PreparedModel.h
+++ b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/PreparedModel.h
@@ -35,7 +35,8 @@
 namespace android::hardware::neuralnetworks::V1_0::utils {
 
 // Class that adapts V1_0::IPreparedModel to nn::IPreparedModel.
-class PreparedModel final : public nn::IPreparedModel {
+class PreparedModel final : public nn::IPreparedModel,
+                            public std::enable_shared_from_this<PreparedModel> {
     struct PrivateConstructorTag {};
 
   public:
@@ -56,6 +57,8 @@
             const nn::OptionalDuration& loopTimeoutDuration,
             const nn::OptionalDuration& timeoutDurationAfterFence) const override;
 
+    nn::GeneralResult<nn::SharedBurst> configureExecutionBurst() const override;
+
     std::any getUnderlyingResource() const override;
 
   private:
diff --git a/neuralnetworks/1.0/utils/src/Burst.cpp b/neuralnetworks/1.0/utils/src/Burst.cpp
new file mode 100644
index 0000000..384bd9b
--- /dev/null
+++ b/neuralnetworks/1.0/utils/src/Burst.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Burst.h"
+
+#include <android-base/logging.h>
+#include <nnapi/IBurst.h>
+#include <nnapi/IPreparedModel.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+
+#include <memory>
+#include <optional>
+#include <utility>
+
+namespace android::hardware::neuralnetworks::V1_0::utils {
+
+nn::GeneralResult<std::shared_ptr<const Burst>> Burst::create(
+        nn::SharedPreparedModel preparedModel) {
+    if (preparedModel == nullptr) {
+        return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
+               << "V1_0::utils::Burst::create must have non-null preparedModel";
+    }
+
+    return std::make_shared<const Burst>(PrivateConstructorTag{}, std::move(preparedModel));
+}
+
+Burst::Burst(PrivateConstructorTag /*tag*/, nn::SharedPreparedModel preparedModel)
+    : kPreparedModel(std::move(preparedModel)) {
+    CHECK(kPreparedModel != nullptr);
+}
+
+Burst::OptionalCacheHold Burst::cacheMemory(const nn::Memory& /*memory*/) const {
+    return nullptr;
+}
+
+nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> Burst::execute(
+        const nn::Request& request, nn::MeasureTiming measure) const {
+    return kPreparedModel->execute(request, measure, {}, {});
+}
+
+}  // namespace android::hardware::neuralnetworks::V1_0::utils
diff --git a/neuralnetworks/1.0/utils/src/Device.cpp b/neuralnetworks/1.0/utils/src/Device.cpp
index 93bd81a..bb31a26 100644
--- a/neuralnetworks/1.0/utils/src/Device.cpp
+++ b/neuralnetworks/1.0/utils/src/Device.cpp
@@ -106,6 +106,10 @@
     return nn::DeviceType::OTHER;
 }
 
+bool Device::isUpdatable() const {
+    return false;
+}
+
 const std::vector<nn::Extension>& Device::getSupportedExtensions() const {
     return kExtensions;
 }
diff --git a/neuralnetworks/1.0/utils/src/PreparedModel.cpp b/neuralnetworks/1.0/utils/src/PreparedModel.cpp
index c0c22fb..858571d 100644
--- a/neuralnetworks/1.0/utils/src/PreparedModel.cpp
+++ b/neuralnetworks/1.0/utils/src/PreparedModel.cpp
@@ -16,6 +16,7 @@
 
 #include "PreparedModel.h"
 
+#include "Burst.h"
 #include "Callbacks.h"
 #include "Conversions.h"
 #include "Utils.h"
@@ -90,6 +91,10 @@
            << "IPreparedModel::executeFenced is not supported on 1.0 HAL service";
 }
 
+nn::GeneralResult<nn::SharedBurst> PreparedModel::configureExecutionBurst() const {
+    return Burst::create(shared_from_this());
+}
+
 std::any PreparedModel::getUnderlyingResource() const {
     sp<V1_0::IPreparedModel> resource = kPreparedModel;
     return resource;
diff --git a/neuralnetworks/1.1/utils/include/nnapi/hal/1.1/Device.h b/neuralnetworks/1.1/utils/include/nnapi/hal/1.1/Device.h
index 5e224b5..3aec8ee 100644
--- a/neuralnetworks/1.1/utils/include/nnapi/hal/1.1/Device.h
+++ b/neuralnetworks/1.1/utils/include/nnapi/hal/1.1/Device.h
@@ -52,6 +52,7 @@
     const std::string& getVersionString() const override;
     nn::Version getFeatureLevel() const override;
     nn::DeviceType getType() const override;
+    bool isUpdatable() const override;
     const std::vector<nn::Extension>& getSupportedExtensions() const override;
     const nn::Capabilities& getCapabilities() const override;
     std::pair<uint32_t, uint32_t> getNumberOfCacheFilesNeeded() const override;
diff --git a/neuralnetworks/1.1/utils/src/Device.cpp b/neuralnetworks/1.1/utils/src/Device.cpp
index 3197ef4..d2ef57f 100644
--- a/neuralnetworks/1.1/utils/src/Device.cpp
+++ b/neuralnetworks/1.1/utils/src/Device.cpp
@@ -106,6 +106,10 @@
     return nn::DeviceType::UNKNOWN;
 }
 
+bool Device::isUpdatable() const {
+    return false;
+}
+
 const std::vector<nn::Extension>& Device::getSupportedExtensions() const {
     return kExtensions;
 }
diff --git a/neuralnetworks/1.2/utils/Android.bp b/neuralnetworks/1.2/utils/Android.bp
index 0fec41c..6959056 100644
--- a/neuralnetworks/1.2/utils/Android.bp
+++ b/neuralnetworks/1.2/utils/Android.bp
@@ -18,6 +18,7 @@
     name: "neuralnetworks_utils_hal_1_2",
     defaults: ["neuralnetworks_utils_defaults"],
     srcs: ["src/*"],
+    exclude_srcs: ["src/ExecutionBurst*"],
     local_include_dirs: ["include/nnapi/hal/1.2/"],
     export_include_dirs: ["include"],
     cflags: ["-Wthread-safety"],
diff --git a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Device.h b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Device.h
index b4bef5e..489f857 100644
--- a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Device.h
+++ b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Device.h
@@ -71,6 +71,7 @@
     const std::string& getVersionString() const override;
     nn::Version getFeatureLevel() const override;
     nn::DeviceType getType() const override;
+    bool isUpdatable() const override;
     const std::vector<nn::Extension>& getSupportedExtensions() const override;
     const nn::Capabilities& getCapabilities() const override;
     std::pair<uint32_t, uint32_t> getNumberOfCacheFilesNeeded() const override;
diff --git a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/ExecutionBurstController.h b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/ExecutionBurstController.h
new file mode 100644
index 0000000..5356a91
--- /dev/null
+++ b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/ExecutionBurstController.h
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_FRAMEWORKS_ML_NN_COMMON_EXECUTION_BURST_CONTROLLER_H
+#define ANDROID_FRAMEWORKS_ML_NN_COMMON_EXECUTION_BURST_CONTROLLER_H
+
+#include "ExecutionBurstUtils.h"
+
+#include <android-base/macros.h>
+#include <android/hardware/neuralnetworks/1.0/types.h>
+#include <android/hardware/neuralnetworks/1.1/types.h>
+#include <android/hardware/neuralnetworks/1.2/IBurstCallback.h>
+#include <android/hardware/neuralnetworks/1.2/IBurstContext.h>
+#include <android/hardware/neuralnetworks/1.2/IPreparedModel.h>
+#include <android/hardware/neuralnetworks/1.2/types.h>
+#include <fmq/MessageQueue.h>
+#include <hidl/MQDescriptor.h>
+
+#include <atomic>
+#include <chrono>
+#include <map>
+#include <memory>
+#include <mutex>
+#include <stack>
+#include <tuple>
+#include <utility>
+#include <vector>
+
+namespace android::nn {
+
+/**
+ * The ExecutionBurstController class manages both the serialization and
+ * deserialization of data across FMQ, making it appear to the runtime as a
+ * regular synchronous inference. Additionally, this class manages the burst's
+ * memory cache.
+ */
+class ExecutionBurstController {
+    DISALLOW_IMPLICIT_CONSTRUCTORS(ExecutionBurstController);
+
+  public:
+    /**
+     * NN runtime burst callback object and memory cache.
+     *
+     * ExecutionBurstCallback associates a hidl_memory object with a slot number
+     * to be passed across FMQ. The ExecutionBurstServer can use this callback
+     * to retrieve this hidl_memory corresponding to the slot via HIDL.
+     *
+     * Whenever a hidl_memory object is copied, it will duplicate the underlying
+     * file descriptor. Because the NN runtime currently copies the hidl_memory
+     * on each execution, it is difficult to associate hidl_memory objects with
+     * previously cached hidl_memory objects. For this reason, callers of this
+     * class must pair each hidl_memory object with an associated key. For
+     * efficiency, if two hidl_memory objects represent the same underlying
+     * buffer, they must use the same key.
+     */
+    class ExecutionBurstCallback : public hardware::neuralnetworks::V1_2::IBurstCallback {
+        DISALLOW_COPY_AND_ASSIGN(ExecutionBurstCallback);
+
+      public:
+        ExecutionBurstCallback() = default;
+
+        hardware::Return<void> getMemories(const hardware::hidl_vec<int32_t>& slots,
+                                           getMemories_cb cb) override;
+
+        /**
+         * This function performs one of two different actions:
+         * 1) If a key corresponding to a memory resource is unrecognized by the
+         *    ExecutionBurstCallback object, the ExecutionBurstCallback object
+         *    will allocate a slot, bind the memory to the slot, and return the
+         *    slot identifier.
+         * 2) If a key corresponding to a memory resource is recognized by the
+         *    ExecutionBurstCallback object, the ExecutionBurstCallback object
+         *    will return the existing slot identifier.
+         *
+         * @param memories Memory resources used in an inference.
+         * @param keys Unique identifiers where each element corresponds to a
+         *     memory resource element in "memories".
+         * @return Unique slot identifiers where each returned slot element
+         *     corresponds to a memory resource element in "memories".
+         */
+        std::vector<int32_t> getSlots(const hardware::hidl_vec<hardware::hidl_memory>& memories,
+                                      const std::vector<intptr_t>& keys);
+
+        /*
+         * This function performs two different actions:
+         * 1) Removes an entry from the cache (if present), including the local
+         *    storage of the hidl_memory object. Note that this call does not
+         *    free any corresponding hidl_memory object in ExecutionBurstServer,
+         *    which is separately freed via IBurstContext::freeMemory.
+         * 2) Return whether a cache entry was removed and which slot was removed if
+         *    found. If the key did not to correspond to any entry in the cache, a
+         *    slot number of 0 is returned. The slot number and whether the entry
+         *    existed is useful so the same slot can be freed in the
+         *    ExecutionBurstServer's cache via IBurstContext::freeMemory.
+         */
+        std::pair<bool, int32_t> freeMemory(intptr_t key);
+
+      private:
+        int32_t getSlotLocked(const hardware::hidl_memory& memory, intptr_t key);
+        int32_t allocateSlotLocked();
+
+        std::mutex mMutex;
+        std::stack<int32_t, std::vector<int32_t>> mFreeSlots;
+        std::map<intptr_t, int32_t> mMemoryIdToSlot;
+        std::vector<hardware::hidl_memory> mMemoryCache;
+    };
+
+    /**
+     * Creates a burst controller on a prepared model.
+     *
+     * Prefer this over ExecutionBurstController's constructor.
+     *
+     * @param preparedModel Model prepared for execution to execute on.
+     * @param pollingTimeWindow How much time (in microseconds) the
+     *     ExecutionBurstController is allowed to poll the FMQ before waiting on
+     *     the blocking futex. Polling may result in lower latencies at the
+     *     potential cost of more power usage.
+     * @return ExecutionBurstController Execution burst controller object.
+     */
+    static std::unique_ptr<ExecutionBurstController> create(
+            const sp<hardware::neuralnetworks::V1_2::IPreparedModel>& preparedModel,
+            std::chrono::microseconds pollingTimeWindow);
+
+    // prefer calling ExecutionBurstController::create
+    ExecutionBurstController(const std::shared_ptr<RequestChannelSender>& requestChannelSender,
+                             const std::shared_ptr<ResultChannelReceiver>& resultChannelReceiver,
+                             const sp<hardware::neuralnetworks::V1_2::IBurstContext>& burstContext,
+                             const sp<ExecutionBurstCallback>& callback,
+                             const sp<hardware::hidl_death_recipient>& deathHandler = nullptr);
+
+    // explicit destructor to unregister the death recipient
+    ~ExecutionBurstController();
+
+    /**
+     * Execute a request on a model.
+     *
+     * @param request Arguments to be executed on a model.
+     * @param measure Whether to collect timing measurements, either YES or NO
+     * @param memoryIds Identifiers corresponding to each memory object in the
+     *     request's pools.
+     * @return A tuple of:
+     *     - result code of the execution
+     *     - dynamic output shapes from the execution
+     *     - any execution time measurements of the execution
+     *     - whether or not a failed burst execution should be re-run using a
+     *       different path (e.g., IPreparedModel::executeSynchronously)
+     */
+    std::tuple<int, std::vector<hardware::neuralnetworks::V1_2::OutputShape>,
+               hardware::neuralnetworks::V1_2::Timing, bool>
+    compute(const hardware::neuralnetworks::V1_0::Request& request,
+            hardware::neuralnetworks::V1_2::MeasureTiming measure,
+            const std::vector<intptr_t>& memoryIds);
+
+    /**
+     * Propagate a user's freeing of memory to the service.
+     *
+     * @param key Key corresponding to the memory object.
+     */
+    void freeMemory(intptr_t key);
+
+  private:
+    std::mutex mMutex;
+    const std::shared_ptr<RequestChannelSender> mRequestChannelSender;
+    const std::shared_ptr<ResultChannelReceiver> mResultChannelReceiver;
+    const sp<hardware::neuralnetworks::V1_2::IBurstContext> mBurstContext;
+    const sp<ExecutionBurstCallback> mMemoryCache;
+    const sp<hardware::hidl_death_recipient> mDeathHandler;
+};
+
+}  // namespace android::nn
+
+#endif  // ANDROID_FRAMEWORKS_ML_NN_COMMON_EXECUTION_BURST_CONTROLLER_H
diff --git a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/ExecutionBurstServer.h b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/ExecutionBurstServer.h
new file mode 100644
index 0000000..2e109b2
--- /dev/null
+++ b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/ExecutionBurstServer.h
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_FRAMEWORKS_ML_NN_COMMON_EXECUTION_BURST_SERVER_H
+#define ANDROID_FRAMEWORKS_ML_NN_COMMON_EXECUTION_BURST_SERVER_H
+
+#include "ExecutionBurstUtils.h"
+
+#include <android-base/macros.h>
+#include <android/hardware/neuralnetworks/1.0/types.h>
+#include <android/hardware/neuralnetworks/1.1/types.h>
+#include <android/hardware/neuralnetworks/1.2/IBurstCallback.h>
+#include <android/hardware/neuralnetworks/1.2/IPreparedModel.h>
+#include <android/hardware/neuralnetworks/1.2/types.h>
+#include <fmq/MessageQueue.h>
+#include <hidl/MQDescriptor.h>
+
+#include <atomic>
+#include <chrono>
+#include <memory>
+#include <optional>
+#include <thread>
+#include <tuple>
+#include <vector>
+
+namespace android::nn {
+
+/**
+ * The ExecutionBurstServer class is responsible for waiting for and
+ * deserializing a request object from a FMQ, performing the inference, and
+ * serializing the result back across another FMQ.
+ */
+class ExecutionBurstServer : public hardware::neuralnetworks::V1_2::IBurstContext {
+    DISALLOW_IMPLICIT_CONSTRUCTORS(ExecutionBurstServer);
+
+  public:
+    /**
+     * IBurstExecutorWithCache is a callback object passed to
+     * ExecutionBurstServer's factory function that is used to perform an
+     * execution. Because some memory resources are needed across multiple
+     * executions, this object also contains a local cache that can directly be
+     * used in the execution.
+     *
+     * ExecutionBurstServer will never access its IBurstExecutorWithCache object
+     * with concurrent calls.
+     */
+    class IBurstExecutorWithCache {
+        DISALLOW_COPY_AND_ASSIGN(IBurstExecutorWithCache);
+
+      public:
+        IBurstExecutorWithCache() = default;
+        virtual ~IBurstExecutorWithCache() = default;
+
+        /**
+         * Checks if a cache entry specified by a slot is present in the cache.
+         *
+         * @param slot Identifier of the cache entry.
+         * @return 'true' if the cache entry is present in the cache, 'false'
+         *     otherwise.
+         */
+        virtual bool isCacheEntryPresent(int32_t slot) const = 0;
+
+        /**
+         * Adds an entry specified by a slot to the cache.
+         *
+         * The caller of this function must ensure that the cache entry that is
+         * being added is not already present in the cache. This can be checked
+         * via isCacheEntryPresent.
+         *
+         * @param memory Memory resource to be cached.
+         * @param slot Slot identifier corresponding to the memory resource.
+         */
+        virtual void addCacheEntry(const hardware::hidl_memory& memory, int32_t slot) = 0;
+
+        /**
+         * Removes an entry specified by a slot from the cache.
+         *
+         * If the cache entry corresponding to the slot number does not exist,
+         * the call does nothing.
+         *
+         * @param slot Slot identifier corresponding to the memory resource.
+         */
+        virtual void removeCacheEntry(int32_t slot) = 0;
+
+        /**
+         * Perform an execution.
+         *
+         * @param request Request object with inputs and outputs specified.
+         *     Request::pools is empty, and DataLocation::poolIndex instead
+         *     refers to the 'slots' argument as if it were Request::pools.
+         * @param slots Slots corresponding to the cached memory entries to be
+         *     used.
+         * @param measure Whether timing information is requested for the
+         *     execution.
+         * @return Result of the execution, including the status of the
+         *     execution, dynamic output shapes, and any timing information.
+         */
+        virtual std::tuple<hardware::neuralnetworks::V1_0::ErrorStatus,
+                           hardware::hidl_vec<hardware::neuralnetworks::V1_2::OutputShape>,
+                           hardware::neuralnetworks::V1_2::Timing>
+        execute(const hardware::neuralnetworks::V1_0::Request& request,
+                const std::vector<int32_t>& slots,
+                hardware::neuralnetworks::V1_2::MeasureTiming measure) = 0;
+    };
+
+    /**
+     * Create automated context to manage FMQ-based executions.
+     *
+     * This function is intended to be used by a service to automatically:
+     * 1) Receive data from a provided FMQ
+     * 2) Execute a model with the given information
+     * 3) Send the result to the created FMQ
+     *
+     * @param callback Callback used to retrieve memories corresponding to
+     *     unrecognized slots.
+     * @param requestChannel Input FMQ channel through which the client passes the
+     *     request to the service.
+     * @param resultChannel Output FMQ channel from which the client can retrieve
+     *     the result of the execution.
+     * @param executorWithCache Object which maintains a local cache of the
+     *     memory pools and executes using the cached memory pools.
+     * @param pollingTimeWindow How much time (in microseconds) the
+     *     ExecutionBurstServer is allowed to poll the FMQ before waiting on
+     *     the blocking futex. Polling may result in lower latencies at the
+     *     potential cost of more power usage.
+     * @result IBurstContext Handle to the burst context.
+     */
+    static sp<ExecutionBurstServer> create(
+            const sp<hardware::neuralnetworks::V1_2::IBurstCallback>& callback,
+            const FmqRequestDescriptor& requestChannel, const FmqResultDescriptor& resultChannel,
+            std::shared_ptr<IBurstExecutorWithCache> executorWithCache,
+            std::chrono::microseconds pollingTimeWindow = std::chrono::microseconds{0});
+
+    /**
+     * Create automated context to manage FMQ-based executions.
+     *
+     * This function is intended to be used by a service to automatically:
+     * 1) Receive data from a provided FMQ
+     * 2) Execute a model with the given information
+     * 3) Send the result to the created FMQ
+     *
+     * @param callback Callback used to retrieve memories corresponding to
+     *     unrecognized slots.
+     * @param requestChannel Input FMQ channel through which the client passes the
+     *     request to the service.
+     * @param resultChannel Output FMQ channel from which the client can retrieve
+     *     the result of the execution.
+     * @param preparedModel PreparedModel that the burst object was created from.
+     *     IPreparedModel::executeSynchronously will be used to perform the
+     *     execution.
+     * @param pollingTimeWindow How much time (in microseconds) the
+     *     ExecutionBurstServer is allowed to poll the FMQ before waiting on
+     *     the blocking futex. Polling may result in lower latencies at the
+     *     potential cost of more power usage.
+     * @result IBurstContext Handle to the burst context.
+     */
+    static sp<ExecutionBurstServer> create(
+            const sp<hardware::neuralnetworks::V1_2::IBurstCallback>& callback,
+            const FmqRequestDescriptor& requestChannel, const FmqResultDescriptor& resultChannel,
+            hardware::neuralnetworks::V1_2::IPreparedModel* preparedModel,
+            std::chrono::microseconds pollingTimeWindow = std::chrono::microseconds{0});
+
+    ExecutionBurstServer(const sp<hardware::neuralnetworks::V1_2::IBurstCallback>& callback,
+                         std::unique_ptr<RequestChannelReceiver> requestChannel,
+                         std::unique_ptr<ResultChannelSender> resultChannel,
+                         std::shared_ptr<IBurstExecutorWithCache> cachedExecutor);
+    ~ExecutionBurstServer();
+
+    // Used by the NN runtime to preemptively remove any stored memory.
+    hardware::Return<void> freeMemory(int32_t slot) override;
+
+  private:
+    // Ensures all cache entries contained in mExecutorWithCache are present in
+    // the cache. If they are not present, they are retrieved (via
+    // IBurstCallback::getMemories) and added to mExecutorWithCache.
+    //
+    // This method is locked via mMutex when it is called.
+    void ensureCacheEntriesArePresentLocked(const std::vector<int32_t>& slots);
+
+    // Work loop that will continue processing execution requests until the
+    // ExecutionBurstServer object is freed.
+    void task();
+
+    std::thread mWorker;
+    std::mutex mMutex;
+    std::atomic<bool> mTeardown{false};
+    const sp<hardware::neuralnetworks::V1_2::IBurstCallback> mCallback;
+    const std::unique_ptr<RequestChannelReceiver> mRequestChannelReceiver;
+    const std::unique_ptr<ResultChannelSender> mResultChannelSender;
+    const std::shared_ptr<IBurstExecutorWithCache> mExecutorWithCache;
+};
+
+}  // namespace android::nn
+
+#endif  // ANDROID_FRAMEWORKS_ML_NN_COMMON_EXECUTION_BURST_SERVER_H
diff --git a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/ExecutionBurstUtils.h b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/ExecutionBurstUtils.h
new file mode 100644
index 0000000..8a41591
--- /dev/null
+++ b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/ExecutionBurstUtils.h
@@ -0,0 +1,335 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_2_UTILS_EXECUTION_BURST_UTILS_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_2_UTILS_EXECUTION_BURST_UTILS_H
+
+#include <android/hardware/neuralnetworks/1.0/types.h>
+#include <android/hardware/neuralnetworks/1.1/types.h>
+#include <android/hardware/neuralnetworks/1.2/types.h>
+#include <fmq/MessageQueue.h>
+#include <hidl/MQDescriptor.h>
+
+#include <atomic>
+#include <chrono>
+#include <memory>
+#include <optional>
+#include <tuple>
+#include <utility>
+#include <vector>
+
+namespace android::hardware::neuralnetworks::V1_2::utils {
+
+/**
+ * Number of elements in the FMQ.
+ */
+constexpr const size_t kExecutionBurstChannelLength = 1024;
+
+using FmqRequestDescriptor = MQDescriptorSync<FmqRequestDatum>;
+using FmqResultDescriptor = MQDescriptorSync<FmqResultDatum>;
+
+/**
+ * Function to serialize a request.
+ *
+ * Prefer calling RequestChannelSender::send.
+ *
+ * @param request Request object without the pool information.
+ * @param measure Whether to collect timing information for the execution.
+ * @param memoryIds Slot identifiers corresponding to memory resources for the
+ *     request.
+ * @return Serialized FMQ request data.
+ */
+std::vector<hardware::neuralnetworks::V1_2::FmqRequestDatum> serialize(
+        const hardware::neuralnetworks::V1_0::Request& request,
+        hardware::neuralnetworks::V1_2::MeasureTiming measure, const std::vector<int32_t>& slots);
+
+/**
+ * Deserialize the FMQ request data.
+ *
+ * The three resulting fields are the Request object (where Request::pools is
+ * empty), slot identifiers (which are stand-ins for Request::pools), and
+ * whether timing information must be collected for the run.
+ *
+ * @param data Serialized FMQ request data.
+ * @return Request object if successfully deserialized, std::nullopt otherwise.
+ */
+std::optional<std::tuple<hardware::neuralnetworks::V1_0::Request, std::vector<int32_t>,
+                         hardware::neuralnetworks::V1_2::MeasureTiming>>
+deserialize(const std::vector<hardware::neuralnetworks::V1_2::FmqRequestDatum>& data);
+
+/**
+ * Function to serialize results.
+ *
+ * Prefer calling ResultChannelSender::send.
+ *
+ * @param errorStatus Status of the execution.
+ * @param outputShapes Dynamic shapes of the output tensors.
+ * @param timing Timing information of the execution.
+ * @return Serialized FMQ result data.
+ */
+std::vector<hardware::neuralnetworks::V1_2::FmqResultDatum> serialize(
+        hardware::neuralnetworks::V1_0::ErrorStatus errorStatus,
+        const std::vector<hardware::neuralnetworks::V1_2::OutputShape>& outputShapes,
+        hardware::neuralnetworks::V1_2::Timing timing);
+
+/**
+ * Deserialize the FMQ result data.
+ *
+ * The three resulting fields are the status of the execution, the dynamic
+ * shapes of the output tensors, and the timing information of the execution.
+ *
+ * @param data Serialized FMQ result data.
+ * @return Result object if successfully deserialized, std::nullopt otherwise.
+ */
+std::optional<std::tuple<hardware::neuralnetworks::V1_0::ErrorStatus,
+                         std::vector<hardware::neuralnetworks::V1_2::OutputShape>,
+                         hardware::neuralnetworks::V1_2::Timing>>
+deserialize(const std::vector<hardware::neuralnetworks::V1_2::FmqResultDatum>& data);
+
+/**
+ * Convert result code to error status.
+ *
+ * @param resultCode Result code to be converted.
+ * @return ErrorStatus Resultant error status.
+ */
+hardware::neuralnetworks::V1_0::ErrorStatus legacyConvertResultCodeToErrorStatus(int resultCode);
+
+/**
+ * RequestChannelSender is responsible for serializing the result packet of
+ * information, sending it on the result channel, and signaling that the data is
+ * available.
+ */
+class RequestChannelSender {
+    using FmqRequestDescriptor =
+            hardware::MQDescriptorSync<hardware::neuralnetworks::V1_2::FmqRequestDatum>;
+    using FmqRequestChannel =
+            hardware::MessageQueue<hardware::neuralnetworks::V1_2::FmqRequestDatum,
+                                   hardware::kSynchronizedReadWrite>;
+
+  public:
+    /**
+     * Create the sending end of a request channel.
+     *
+     * Prefer this call over the constructor.
+     *
+     * @param channelLength Number of elements in the FMQ.
+     * @return A pair of ResultChannelReceiver and the FMQ descriptor on
+     *     successful creation, both nullptr otherwise.
+     */
+    static std::pair<std::unique_ptr<RequestChannelSender>, const FmqRequestDescriptor*> create(
+            size_t channelLength);
+
+    /**
+     * Send the request to the channel.
+     *
+     * @param request Request object without the pool information.
+     * @param measure Whether to collect timing information for the execution.
+     * @param memoryIds Slot identifiers corresponding to memory resources for
+     *     the request.
+     * @return 'true' on successful send, 'false' otherwise.
+     */
+    bool send(const hardware::neuralnetworks::V1_0::Request& request,
+              hardware::neuralnetworks::V1_2::MeasureTiming measure,
+              const std::vector<int32_t>& slots);
+
+    /**
+     * Method to mark the channel as invalid, causing all future calls to
+     * RequestChannelSender::send to immediately return false without attempting
+     * to send a message across the FMQ.
+     */
+    void invalidate();
+
+    // prefer calling RequestChannelSender::send
+    bool sendPacket(const std::vector<hardware::neuralnetworks::V1_2::FmqRequestDatum>& packet);
+
+    RequestChannelSender(std::unique_ptr<FmqRequestChannel> fmqRequestChannel);
+
+  private:
+    const std::unique_ptr<FmqRequestChannel> mFmqRequestChannel;
+    std::atomic<bool> mValid{true};
+};
+
+/**
+ * RequestChannelReceiver is responsible for waiting on the channel until the
+ * packet is available, extracting the packet from the channel, and
+ * deserializing the packet.
+ *
+ * Because the receiver can wait on a packet that may never come (e.g., because
+ * the sending side of the packet has been closed), this object can be
+ * invalidated, unblocking the receiver.
+ */
+class RequestChannelReceiver {
+    using FmqRequestChannel =
+            hardware::MessageQueue<hardware::neuralnetworks::V1_2::FmqRequestDatum,
+                                   hardware::kSynchronizedReadWrite>;
+
+  public:
+    /**
+     * Create the receiving end of a request channel.
+     *
+     * Prefer this call over the constructor.
+     *
+     * @param requestChannel Descriptor for the request channel.
+     * @param pollingTimeWindow How much time (in microseconds) the
+     *     RequestChannelReceiver is allowed to poll the FMQ before waiting on
+     *     the blocking futex. Polling may result in lower latencies at the
+     *     potential cost of more power usage.
+     * @return RequestChannelReceiver on successful creation, nullptr otherwise.
+     */
+    static std::unique_ptr<RequestChannelReceiver> create(
+            const FmqRequestDescriptor& requestChannel,
+            std::chrono::microseconds pollingTimeWindow);
+
+    /**
+     * Get the request from the channel.
+     *
+     * This method will block until either:
+     * 1) The packet has been retrieved, or
+     * 2) The receiver has been invalidated
+     *
+     * @return Request object if successfully received, std::nullopt if error or
+     *     if the receiver object was invalidated.
+     */
+    std::optional<std::tuple<hardware::neuralnetworks::V1_0::Request, std::vector<int32_t>,
+                             hardware::neuralnetworks::V1_2::MeasureTiming>>
+    getBlocking();
+
+    /**
+     * Method to mark the channel as invalid, unblocking any current or future
+     * calls to RequestChannelReceiver::getBlocking.
+     */
+    void invalidate();
+
+    RequestChannelReceiver(std::unique_ptr<FmqRequestChannel> fmqRequestChannel,
+                           std::chrono::microseconds pollingTimeWindow);
+
+  private:
+    std::optional<std::vector<hardware::neuralnetworks::V1_2::FmqRequestDatum>> getPacketBlocking();
+
+    const std::unique_ptr<FmqRequestChannel> mFmqRequestChannel;
+    std::atomic<bool> mTeardown{false};
+    const std::chrono::microseconds kPollingTimeWindow;
+};
+
+/**
+ * ResultChannelSender is responsible for serializing the result packet of
+ * information, sending it on the result channel, and signaling that the data is
+ * available.
+ */
+class ResultChannelSender {
+    using FmqResultChannel = hardware::MessageQueue<hardware::neuralnetworks::V1_2::FmqResultDatum,
+                                                    hardware::kSynchronizedReadWrite>;
+
+  public:
+    /**
+     * Create the sending end of a result channel.
+     *
+     * Prefer this call over the constructor.
+     *
+     * @param resultChannel Descriptor for the result channel.
+     * @return ResultChannelSender on successful creation, nullptr otherwise.
+     */
+    static std::unique_ptr<ResultChannelSender> create(const FmqResultDescriptor& resultChannel);
+
+    /**
+     * Send the result to the channel.
+     *
+     * @param errorStatus Status of the execution.
+     * @param outputShapes Dynamic shapes of the output tensors.
+     * @param timing Timing information of the execution.
+     * @return 'true' on successful send, 'false' otherwise.
+     */
+    bool send(hardware::neuralnetworks::V1_0::ErrorStatus errorStatus,
+              const std::vector<hardware::neuralnetworks::V1_2::OutputShape>& outputShapes,
+              hardware::neuralnetworks::V1_2::Timing timing);
+
+    // prefer calling ResultChannelSender::send
+    bool sendPacket(const std::vector<hardware::neuralnetworks::V1_2::FmqResultDatum>& packet);
+
+    ResultChannelSender(std::unique_ptr<FmqResultChannel> fmqResultChannel);
+
+  private:
+    const std::unique_ptr<FmqResultChannel> mFmqResultChannel;
+};
+
+/**
+ * ResultChannelReceiver is responsible for waiting on the channel until the
+ * packet is available, extracting the packet from the channel, and
+ * deserializing the packet.
+ *
+ * Because the receiver can wait on a packet that may never come (e.g., because
+ * the sending side of the packet has been closed), this object can be
+ * invalidated, unblocking the receiver.
+ */
+class ResultChannelReceiver {
+    using FmqResultDescriptor =
+            hardware::MQDescriptorSync<hardware::neuralnetworks::V1_2::FmqResultDatum>;
+    using FmqResultChannel = hardware::MessageQueue<hardware::neuralnetworks::V1_2::FmqResultDatum,
+                                                    hardware::kSynchronizedReadWrite>;
+
+  public:
+    /**
+     * Create the receiving end of a result channel.
+     *
+     * Prefer this call over the constructor.
+     *
+     * @param channelLength Number of elements in the FMQ.
+     * @param pollingTimeWindow How much time (in microseconds) the
+     *     ResultChannelReceiver is allowed to poll the FMQ before waiting on
+     *     the blocking futex. Polling may result in lower latencies at the
+     *     potential cost of more power usage.
+     * @return A pair of ResultChannelReceiver and the FMQ descriptor on
+     *     successful creation, both nullptr otherwise.
+     */
+    static std::pair<std::unique_ptr<ResultChannelReceiver>, const FmqResultDescriptor*> create(
+            size_t channelLength, std::chrono::microseconds pollingTimeWindow);
+
+    /**
+     * Get the result from the channel.
+     *
+     * This method will block until either:
+     * 1) The packet has been retrieved, or
+     * 2) The receiver has been invalidated
+     *
+     * @return Result object if successfully received, std::nullopt if error or
+     *     if the receiver object was invalidated.
+     */
+    std::optional<std::tuple<hardware::neuralnetworks::V1_0::ErrorStatus,
+                             std::vector<hardware::neuralnetworks::V1_2::OutputShape>,
+                             hardware::neuralnetworks::V1_2::Timing>>
+    getBlocking();
+
+    /**
+     * Method to mark the channel as invalid, unblocking any current or future
+     * calls to ResultChannelReceiver::getBlocking.
+     */
+    void invalidate();
+
+    // prefer calling ResultChannelReceiver::getBlocking
+    std::optional<std::vector<hardware::neuralnetworks::V1_2::FmqResultDatum>> getPacketBlocking();
+
+    ResultChannelReceiver(std::unique_ptr<FmqResultChannel> fmqResultChannel,
+                          std::chrono::microseconds pollingTimeWindow);
+
+  private:
+    const std::unique_ptr<FmqResultChannel> mFmqResultChannel;
+    std::atomic<bool> mValid{true};
+    const std::chrono::microseconds kPollingTimeWindow;
+};
+
+}  // namespace android::hardware::neuralnetworks::V1_2::utils
+
+#endif  // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_2_UTILS_EXECUTION_BURST_UTILS_H
diff --git a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/PreparedModel.h b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/PreparedModel.h
index 6a56a82..fb11130 100644
--- a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/PreparedModel.h
+++ b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/PreparedModel.h
@@ -36,7 +36,8 @@
 namespace android::hardware::neuralnetworks::V1_2::utils {
 
 // Class that adapts V1_2::IPreparedModel to nn::IPreparedModel.
-class PreparedModel final : public nn::IPreparedModel {
+class PreparedModel final : public nn::IPreparedModel,
+                            public std::enable_shared_from_this<PreparedModel> {
     struct PrivateConstructorTag {};
 
   public:
@@ -57,6 +58,8 @@
             const nn::OptionalDuration& loopTimeoutDuration,
             const nn::OptionalDuration& timeoutDurationAfterFence) const override;
 
+    nn::GeneralResult<nn::SharedBurst> configureExecutionBurst() const override;
+
     std::any getUnderlyingResource() const override;
 
   private:
diff --git a/neuralnetworks/1.2/utils/src/Device.cpp b/neuralnetworks/1.2/utils/src/Device.cpp
index 9fe0de2..1954dfa 100644
--- a/neuralnetworks/1.2/utils/src/Device.cpp
+++ b/neuralnetworks/1.2/utils/src/Device.cpp
@@ -199,6 +199,10 @@
     return kDeviceType;
 }
 
+bool Device::isUpdatable() const {
+    return false;
+}
+
 const std::vector<nn::Extension>& Device::getSupportedExtensions() const {
     return kExtensions;
 }
diff --git a/neuralnetworks/1.2/utils/src/ExecutionBurstController.cpp b/neuralnetworks/1.2/utils/src/ExecutionBurstController.cpp
new file mode 100644
index 0000000..2265861
--- /dev/null
+++ b/neuralnetworks/1.2/utils/src/ExecutionBurstController.cpp
@@ -0,0 +1,299 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "ExecutionBurstController"
+
+#include "ExecutionBurstController.h"
+
+#include <android-base/logging.h>
+
+#include <algorithm>
+#include <cstring>
+#include <limits>
+#include <memory>
+#include <string>
+#include <tuple>
+#include <utility>
+#include <vector>
+
+#include "ExecutionBurstUtils.h"
+#include "HalInterfaces.h"
+#include "Tracing.h"
+#include "Utils.h"
+
+namespace android::nn {
+namespace {
+
+class BurstContextDeathHandler : public hardware::hidl_death_recipient {
+  public:
+    using Callback = std::function<void()>;
+
+    BurstContextDeathHandler(const Callback& onDeathCallback) : mOnDeathCallback(onDeathCallback) {
+        CHECK(onDeathCallback != nullptr);
+    }
+
+    void serviceDied(uint64_t /*cookie*/, const wp<hidl::base::V1_0::IBase>& /*who*/) override {
+        LOG(ERROR) << "BurstContextDeathHandler::serviceDied -- service unexpectedly died!";
+        mOnDeathCallback();
+    }
+
+  private:
+    const Callback mOnDeathCallback;
+};
+
+}  // anonymous namespace
+
+hardware::Return<void> ExecutionBurstController::ExecutionBurstCallback::getMemories(
+        const hardware::hidl_vec<int32_t>& slots, getMemories_cb cb) {
+    std::lock_guard<std::mutex> guard(mMutex);
+
+    // get all memories
+    hardware::hidl_vec<hardware::hidl_memory> memories(slots.size());
+    std::transform(slots.begin(), slots.end(), memories.begin(), [this](int32_t slot) {
+        return slot < mMemoryCache.size() ? mMemoryCache[slot] : hardware::hidl_memory{};
+    });
+
+    // ensure all memories are valid
+    if (!std::all_of(memories.begin(), memories.end(),
+                     [](const hardware::hidl_memory& memory) { return memory.valid(); })) {
+        cb(V1_0::ErrorStatus::INVALID_ARGUMENT, {});
+        return hardware::Void();
+    }
+
+    // return successful
+    cb(V1_0::ErrorStatus::NONE, std::move(memories));
+    return hardware::Void();
+}
+
+std::vector<int32_t> ExecutionBurstController::ExecutionBurstCallback::getSlots(
+        const hardware::hidl_vec<hardware::hidl_memory>& memories,
+        const std::vector<intptr_t>& keys) {
+    std::lock_guard<std::mutex> guard(mMutex);
+
+    // retrieve (or bind) all slots corresponding to memories
+    std::vector<int32_t> slots;
+    slots.reserve(memories.size());
+    for (size_t i = 0; i < memories.size(); ++i) {
+        slots.push_back(getSlotLocked(memories[i], keys[i]));
+    }
+    return slots;
+}
+
+std::pair<bool, int32_t> ExecutionBurstController::ExecutionBurstCallback::freeMemory(
+        intptr_t key) {
+    std::lock_guard<std::mutex> guard(mMutex);
+
+    auto iter = mMemoryIdToSlot.find(key);
+    if (iter == mMemoryIdToSlot.end()) {
+        return {false, 0};
+    }
+    const int32_t slot = iter->second;
+    mMemoryIdToSlot.erase(key);
+    mMemoryCache[slot] = {};
+    mFreeSlots.push(slot);
+    return {true, slot};
+}
+
+int32_t ExecutionBurstController::ExecutionBurstCallback::getSlotLocked(
+        const hardware::hidl_memory& memory, intptr_t key) {
+    auto iter = mMemoryIdToSlot.find(key);
+    if (iter == mMemoryIdToSlot.end()) {
+        const int32_t slot = allocateSlotLocked();
+        mMemoryIdToSlot[key] = slot;
+        mMemoryCache[slot] = memory;
+        return slot;
+    } else {
+        const int32_t slot = iter->second;
+        return slot;
+    }
+}
+
+int32_t ExecutionBurstController::ExecutionBurstCallback::allocateSlotLocked() {
+    constexpr size_t kMaxNumberOfSlots = std::numeric_limits<int32_t>::max();
+
+    // if there is a free slot, use it
+    if (mFreeSlots.size() > 0) {
+        const int32_t slot = mFreeSlots.top();
+        mFreeSlots.pop();
+        return slot;
+    }
+
+    // otherwise use a slot for the first time
+    CHECK(mMemoryCache.size() < kMaxNumberOfSlots) << "Exceeded maximum number of slots!";
+    const int32_t slot = static_cast<int32_t>(mMemoryCache.size());
+    mMemoryCache.emplace_back();
+
+    return slot;
+}
+
+std::unique_ptr<ExecutionBurstController> ExecutionBurstController::create(
+        const sp<V1_2::IPreparedModel>& preparedModel,
+        std::chrono::microseconds pollingTimeWindow) {
+    // check inputs
+    if (preparedModel == nullptr) {
+        LOG(ERROR) << "ExecutionBurstController::create passed a nullptr";
+        return nullptr;
+    }
+
+    // create callback object
+    sp<ExecutionBurstCallback> callback = new ExecutionBurstCallback();
+
+    // create FMQ objects
+    auto [requestChannelSenderTemp, requestChannelDescriptor] =
+            RequestChannelSender::create(kExecutionBurstChannelLength);
+    auto [resultChannelReceiverTemp, resultChannelDescriptor] =
+            ResultChannelReceiver::create(kExecutionBurstChannelLength, pollingTimeWindow);
+    std::shared_ptr<RequestChannelSender> requestChannelSender =
+            std::move(requestChannelSenderTemp);
+    std::shared_ptr<ResultChannelReceiver> resultChannelReceiver =
+            std::move(resultChannelReceiverTemp);
+
+    // check FMQ objects
+    if (!requestChannelSender || !resultChannelReceiver || !requestChannelDescriptor ||
+        !resultChannelDescriptor) {
+        LOG(ERROR) << "ExecutionBurstController::create failed to create FastMessageQueue";
+        return nullptr;
+    }
+
+    // configure burst
+    V1_0::ErrorStatus errorStatus;
+    sp<IBurstContext> burstContext;
+    const hardware::Return<void> ret = preparedModel->configureExecutionBurst(
+            callback, *requestChannelDescriptor, *resultChannelDescriptor,
+            [&errorStatus, &burstContext](V1_0::ErrorStatus status,
+                                          const sp<IBurstContext>& context) {
+                errorStatus = status;
+                burstContext = context;
+            });
+
+    // check burst
+    if (!ret.isOk()) {
+        LOG(ERROR) << "IPreparedModel::configureExecutionBurst failed with description "
+                   << ret.description();
+        return nullptr;
+    }
+    if (errorStatus != V1_0::ErrorStatus::NONE) {
+        LOG(ERROR) << "IPreparedModel::configureExecutionBurst failed with status "
+                   << toString(errorStatus);
+        return nullptr;
+    }
+    if (burstContext == nullptr) {
+        LOG(ERROR) << "IPreparedModel::configureExecutionBurst returned nullptr for burst";
+        return nullptr;
+    }
+
+    // create death handler object
+    BurstContextDeathHandler::Callback onDeathCallback = [requestChannelSender,
+                                                          resultChannelReceiver] {
+        requestChannelSender->invalidate();
+        resultChannelReceiver->invalidate();
+    };
+    const sp<BurstContextDeathHandler> deathHandler = new BurstContextDeathHandler(onDeathCallback);
+
+    // linkToDeath registers a callback that will be invoked on service death to
+    // proactively handle service crashes. If the linkToDeath call fails,
+    // asynchronous calls are susceptible to hangs if the service crashes before
+    // providing the response.
+    const hardware::Return<bool> deathHandlerRet = burstContext->linkToDeath(deathHandler, 0);
+    if (!deathHandlerRet.isOk() || deathHandlerRet != true) {
+        LOG(ERROR) << "ExecutionBurstController::create -- Failed to register a death recipient "
+                      "for the IBurstContext object.";
+        return nullptr;
+    }
+
+    // make and return controller
+    return std::make_unique<ExecutionBurstController>(requestChannelSender, resultChannelReceiver,
+                                                      burstContext, callback, deathHandler);
+}
+
+ExecutionBurstController::ExecutionBurstController(
+        const std::shared_ptr<RequestChannelSender>& requestChannelSender,
+        const std::shared_ptr<ResultChannelReceiver>& resultChannelReceiver,
+        const sp<IBurstContext>& burstContext, const sp<ExecutionBurstCallback>& callback,
+        const sp<hardware::hidl_death_recipient>& deathHandler)
+    : mRequestChannelSender(requestChannelSender),
+      mResultChannelReceiver(resultChannelReceiver),
+      mBurstContext(burstContext),
+      mMemoryCache(callback),
+      mDeathHandler(deathHandler) {}
+
+ExecutionBurstController::~ExecutionBurstController() {
+    // It is safe to ignore any errors resulting from this unlinkToDeath call
+    // because the ExecutionBurstController object is already being destroyed
+    // and its underlying IBurstContext object is no longer being used by the NN
+    // runtime.
+    if (mDeathHandler) {
+        mBurstContext->unlinkToDeath(mDeathHandler).isOk();
+    }
+}
+
+static std::tuple<int, std::vector<V1_2::OutputShape>, V1_2::Timing, bool> getExecutionResult(
+        V1_0::ErrorStatus status, std::vector<V1_2::OutputShape> outputShapes, V1_2::Timing timing,
+        bool fallback) {
+    auto [n, checkedOutputShapes, checkedTiming] =
+            getExecutionResult(convertToV1_3(status), std::move(outputShapes), timing);
+    return {n, convertToV1_2(checkedOutputShapes), convertToV1_2(checkedTiming), fallback};
+}
+
+std::tuple<int, std::vector<V1_2::OutputShape>, V1_2::Timing, bool>
+ExecutionBurstController::compute(const V1_0::Request& request, V1_2::MeasureTiming measure,
+                                  const std::vector<intptr_t>& memoryIds) {
+    // This is the first point when we know an execution is occurring, so begin
+    // to collect systraces. Note that the first point we can begin collecting
+    // systraces in ExecutionBurstServer is when the RequestChannelReceiver
+    // realizes there is data in the FMQ, so ExecutionBurstServer collects
+    // systraces at different points in the code.
+    NNTRACE_FULL(NNTRACE_LAYER_IPC, NNTRACE_PHASE_EXECUTION, "ExecutionBurstController::compute");
+
+    std::lock_guard<std::mutex> guard(mMutex);
+
+    // send request packet
+    const std::vector<int32_t> slots = mMemoryCache->getSlots(request.pools, memoryIds);
+    const bool success = mRequestChannelSender->send(request, measure, slots);
+    if (!success) {
+        LOG(ERROR) << "Error sending FMQ packet";
+        // only use fallback execution path if the packet could not be sent
+        return getExecutionResult(V1_0::ErrorStatus::GENERAL_FAILURE, {}, kNoTiming12,
+                                  /*fallback=*/true);
+    }
+
+    // get result packet
+    const auto result = mResultChannelReceiver->getBlocking();
+    if (!result) {
+        LOG(ERROR) << "Error retrieving FMQ packet";
+        // only use fallback execution path if the packet could not be sent
+        return getExecutionResult(V1_0::ErrorStatus::GENERAL_FAILURE, {}, kNoTiming12,
+                                  /*fallback=*/false);
+    }
+
+    // unpack results and return (only use fallback execution path if the
+    // packet could not be sent)
+    auto [status, outputShapes, timing] = std::move(*result);
+    return getExecutionResult(status, std::move(outputShapes), timing, /*fallback=*/false);
+}
+
+void ExecutionBurstController::freeMemory(intptr_t key) {
+    std::lock_guard<std::mutex> guard(mMutex);
+
+    bool valid;
+    int32_t slot;
+    std::tie(valid, slot) = mMemoryCache->freeMemory(key);
+    if (valid) {
+        mBurstContext->freeMemory(slot).isOk();
+    }
+}
+
+}  // namespace android::nn
diff --git a/neuralnetworks/1.2/utils/src/ExecutionBurstServer.cpp b/neuralnetworks/1.2/utils/src/ExecutionBurstServer.cpp
new file mode 100644
index 0000000..022548d
--- /dev/null
+++ b/neuralnetworks/1.2/utils/src/ExecutionBurstServer.cpp
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "ExecutionBurstServer"
+
+#include "ExecutionBurstServer.h"
+
+#include <android-base/logging.h>
+
+#include <algorithm>
+#include <cstring>
+#include <limits>
+#include <map>
+#include <memory>
+#include <tuple>
+#include <utility>
+#include <vector>
+
+#include "ExecutionBurstUtils.h"
+#include "HalInterfaces.h"
+#include "Tracing.h"
+
+namespace android::nn {
+namespace {
+
+// DefaultBurstExecutorWithCache adapts an IPreparedModel so that it can be
+// used as an IBurstExecutorWithCache. Specifically, the cache simply stores the
+// hidl_memory object, and the execution forwards calls to the provided
+// IPreparedModel's "executeSynchronously" method. With this class, hidl_memory
+// must be mapped and unmapped for each execution.
+class DefaultBurstExecutorWithCache : public ExecutionBurstServer::IBurstExecutorWithCache {
+  public:
+    DefaultBurstExecutorWithCache(V1_2::IPreparedModel* preparedModel)
+        : mpPreparedModel(preparedModel) {}
+
+    bool isCacheEntryPresent(int32_t slot) const override {
+        const auto it = mMemoryCache.find(slot);
+        return (it != mMemoryCache.end()) && it->second.valid();
+    }
+
+    void addCacheEntry(const hardware::hidl_memory& memory, int32_t slot) override {
+        mMemoryCache[slot] = memory;
+    }
+
+    void removeCacheEntry(int32_t slot) override { mMemoryCache.erase(slot); }
+
+    std::tuple<V1_0::ErrorStatus, hardware::hidl_vec<V1_2::OutputShape>, V1_2::Timing> execute(
+            const V1_0::Request& request, const std::vector<int32_t>& slots,
+            V1_2::MeasureTiming measure) override {
+        // convert slots to pools
+        hardware::hidl_vec<hardware::hidl_memory> pools(slots.size());
+        std::transform(slots.begin(), slots.end(), pools.begin(),
+                       [this](int32_t slot) { return mMemoryCache[slot]; });
+
+        // create full request
+        V1_0::Request fullRequest = request;
+        fullRequest.pools = std::move(pools);
+
+        // setup execution
+        V1_0::ErrorStatus returnedStatus = V1_0::ErrorStatus::GENERAL_FAILURE;
+        hardware::hidl_vec<V1_2::OutputShape> returnedOutputShapes;
+        V1_2::Timing returnedTiming;
+        auto cb = [&returnedStatus, &returnedOutputShapes, &returnedTiming](
+                          V1_0::ErrorStatus status,
+                          const hardware::hidl_vec<V1_2::OutputShape>& outputShapes,
+                          const V1_2::Timing& timing) {
+            returnedStatus = status;
+            returnedOutputShapes = outputShapes;
+            returnedTiming = timing;
+        };
+
+        // execute
+        const hardware::Return<void> ret =
+                mpPreparedModel->executeSynchronously(fullRequest, measure, cb);
+        if (!ret.isOk() || returnedStatus != V1_0::ErrorStatus::NONE) {
+            LOG(ERROR) << "IPreparedModelAdapter::execute -- Error executing";
+            return {returnedStatus, std::move(returnedOutputShapes), kNoTiming};
+        }
+
+        return std::make_tuple(returnedStatus, std::move(returnedOutputShapes), returnedTiming);
+    }
+
+  private:
+    V1_2::IPreparedModel* const mpPreparedModel;
+    std::map<int32_t, hardware::hidl_memory> mMemoryCache;
+};
+
+}  // anonymous namespace
+
+// ExecutionBurstServer methods
+
+sp<ExecutionBurstServer> ExecutionBurstServer::create(
+        const sp<IBurstCallback>& callback, const MQDescriptorSync<FmqRequestDatum>& requestChannel,
+        const MQDescriptorSync<FmqResultDatum>& resultChannel,
+        std::shared_ptr<IBurstExecutorWithCache> executorWithCache,
+        std::chrono::microseconds pollingTimeWindow) {
+    // check inputs
+    if (callback == nullptr || executorWithCache == nullptr) {
+        LOG(ERROR) << "ExecutionBurstServer::create passed a nullptr";
+        return nullptr;
+    }
+
+    // create FMQ objects
+    std::unique_ptr<RequestChannelReceiver> requestChannelReceiver =
+            RequestChannelReceiver::create(requestChannel, pollingTimeWindow);
+    std::unique_ptr<ResultChannelSender> resultChannelSender =
+            ResultChannelSender::create(resultChannel);
+
+    // check FMQ objects
+    if (!requestChannelReceiver || !resultChannelSender) {
+        LOG(ERROR) << "ExecutionBurstServer::create failed to create FastMessageQueue";
+        return nullptr;
+    }
+
+    // make and return context
+    return new ExecutionBurstServer(callback, std::move(requestChannelReceiver),
+                                    std::move(resultChannelSender), std::move(executorWithCache));
+}
+
+sp<ExecutionBurstServer> ExecutionBurstServer::create(
+        const sp<IBurstCallback>& callback, const MQDescriptorSync<FmqRequestDatum>& requestChannel,
+        const MQDescriptorSync<FmqResultDatum>& resultChannel, V1_2::IPreparedModel* preparedModel,
+        std::chrono::microseconds pollingTimeWindow) {
+    // check relevant input
+    if (preparedModel == nullptr) {
+        LOG(ERROR) << "ExecutionBurstServer::create passed a nullptr";
+        return nullptr;
+    }
+
+    // adapt IPreparedModel to have caching
+    const std::shared_ptr<DefaultBurstExecutorWithCache> preparedModelAdapter =
+            std::make_shared<DefaultBurstExecutorWithCache>(preparedModel);
+
+    // make and return context
+    return ExecutionBurstServer::create(callback, requestChannel, resultChannel,
+                                        preparedModelAdapter, pollingTimeWindow);
+}
+
+ExecutionBurstServer::ExecutionBurstServer(
+        const sp<IBurstCallback>& callback, std::unique_ptr<RequestChannelReceiver> requestChannel,
+        std::unique_ptr<ResultChannelSender> resultChannel,
+        std::shared_ptr<IBurstExecutorWithCache> executorWithCache)
+    : mCallback(callback),
+      mRequestChannelReceiver(std::move(requestChannel)),
+      mResultChannelSender(std::move(resultChannel)),
+      mExecutorWithCache(std::move(executorWithCache)) {
+    // TODO: highly document the threading behavior of this class
+    mWorker = std::thread([this] { task(); });
+}
+
+ExecutionBurstServer::~ExecutionBurstServer() {
+    // set teardown flag
+    mTeardown = true;
+    mRequestChannelReceiver->invalidate();
+
+    // wait for task thread to end
+    mWorker.join();
+}
+
+hardware::Return<void> ExecutionBurstServer::freeMemory(int32_t slot) {
+    std::lock_guard<std::mutex> hold(mMutex);
+    mExecutorWithCache->removeCacheEntry(slot);
+    return hardware::Void();
+}
+
+void ExecutionBurstServer::ensureCacheEntriesArePresentLocked(const std::vector<int32_t>& slots) {
+    const auto slotIsKnown = [this](int32_t slot) {
+        return mExecutorWithCache->isCacheEntryPresent(slot);
+    };
+
+    // find unique unknown slots
+    std::vector<int32_t> unknownSlots = slots;
+    auto unknownSlotsEnd = unknownSlots.end();
+    std::sort(unknownSlots.begin(), unknownSlotsEnd);
+    unknownSlotsEnd = std::unique(unknownSlots.begin(), unknownSlotsEnd);
+    unknownSlotsEnd = std::remove_if(unknownSlots.begin(), unknownSlotsEnd, slotIsKnown);
+    unknownSlots.erase(unknownSlotsEnd, unknownSlots.end());
+
+    // quick-exit if all slots are known
+    if (unknownSlots.empty()) {
+        return;
+    }
+
+    V1_0::ErrorStatus errorStatus = V1_0::ErrorStatus::GENERAL_FAILURE;
+    std::vector<hardware::hidl_memory> returnedMemories;
+    auto cb = [&errorStatus, &returnedMemories](
+                      V1_0::ErrorStatus status,
+                      const hardware::hidl_vec<hardware::hidl_memory>& memories) {
+        errorStatus = status;
+        returnedMemories = memories;
+    };
+
+    const hardware::Return<void> ret = mCallback->getMemories(unknownSlots, cb);
+
+    if (!ret.isOk() || errorStatus != V1_0::ErrorStatus::NONE ||
+        returnedMemories.size() != unknownSlots.size()) {
+        LOG(ERROR) << "Error retrieving memories";
+        return;
+    }
+
+    // add memories to unknown slots
+    for (size_t i = 0; i < unknownSlots.size(); ++i) {
+        mExecutorWithCache->addCacheEntry(returnedMemories[i], unknownSlots[i]);
+    }
+}
+
+void ExecutionBurstServer::task() {
+    // loop until the burst object is being destroyed
+    while (!mTeardown) {
+        // receive request
+        auto arguments = mRequestChannelReceiver->getBlocking();
+
+        // if the request packet was not properly received, return a generic
+        // error and skip the execution
+        //
+        // if the burst is being torn down, skip the execution so the "task"
+        // function can end
+        if (!arguments) {
+            if (!mTeardown) {
+                mResultChannelSender->send(V1_0::ErrorStatus::GENERAL_FAILURE, {}, kNoTiming);
+            }
+            continue;
+        }
+
+        // otherwise begin tracing execution
+        NNTRACE_FULL(NNTRACE_LAYER_IPC, NNTRACE_PHASE_EXECUTION,
+                     "ExecutionBurstServer getting memory, executing, and returning results");
+
+        // unpack the arguments; types are Request, std::vector<int32_t>, and
+        // MeasureTiming, respectively
+        const auto [requestWithoutPools, slotsOfPools, measure] = std::move(*arguments);
+
+        // ensure executor with cache has required memory
+        std::lock_guard<std::mutex> hold(mMutex);
+        ensureCacheEntriesArePresentLocked(slotsOfPools);
+
+        // perform computation; types are ErrorStatus, hidl_vec<OutputShape>,
+        // and Timing, respectively
+        const auto [errorStatus, outputShapes, returnedTiming] =
+                mExecutorWithCache->execute(requestWithoutPools, slotsOfPools, measure);
+
+        // return result
+        mResultChannelSender->send(errorStatus, outputShapes, returnedTiming);
+    }
+}
+
+}  // namespace android::nn
diff --git a/neuralnetworks/1.2/utils/src/ExecutionBurstUtils.cpp b/neuralnetworks/1.2/utils/src/ExecutionBurstUtils.cpp
new file mode 100644
index 0000000..f0275f9
--- /dev/null
+++ b/neuralnetworks/1.2/utils/src/ExecutionBurstUtils.cpp
@@ -0,0 +1,749 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "ExecutionBurstUtils"
+
+#include "ExecutionBurstUtils.h"
+
+#include <android-base/logging.h>
+#include <android/hardware/neuralnetworks/1.0/types.h>
+#include <android/hardware/neuralnetworks/1.1/types.h>
+#include <android/hardware/neuralnetworks/1.2/types.h>
+#include <fmq/MessageQueue.h>
+#include <hidl/MQDescriptor.h>
+
+#include <atomic>
+#include <chrono>
+#include <memory>
+#include <thread>
+#include <tuple>
+#include <utility>
+#include <vector>
+
+namespace android::hardware::neuralnetworks::V1_2::utils {
+namespace {
+
+constexpr V1_2::Timing kNoTiming = {std::numeric_limits<uint64_t>::max(),
+                                    std::numeric_limits<uint64_t>::max()};
+
+}
+
+// serialize a request into a packet
+std::vector<FmqRequestDatum> serialize(const V1_0::Request& request, V1_2::MeasureTiming measure,
+                                       const std::vector<int32_t>& slots) {
+    // count how many elements need to be sent for a request
+    size_t count = 2 + request.inputs.size() + request.outputs.size() + request.pools.size();
+    for (const auto& input : request.inputs) {
+        count += input.dimensions.size();
+    }
+    for (const auto& output : request.outputs) {
+        count += output.dimensions.size();
+    }
+
+    // create buffer to temporarily store elements
+    std::vector<FmqRequestDatum> data;
+    data.reserve(count);
+
+    // package packetInfo
+    {
+        FmqRequestDatum datum;
+        datum.packetInformation(
+                {/*.packetSize=*/static_cast<uint32_t>(count),
+                 /*.numberOfInputOperands=*/static_cast<uint32_t>(request.inputs.size()),
+                 /*.numberOfOutputOperands=*/static_cast<uint32_t>(request.outputs.size()),
+                 /*.numberOfPools=*/static_cast<uint32_t>(request.pools.size())});
+        data.push_back(datum);
+    }
+
+    // package input data
+    for (const auto& input : request.inputs) {
+        // package operand information
+        FmqRequestDatum datum;
+        datum.inputOperandInformation(
+                {/*.hasNoValue=*/input.hasNoValue,
+                 /*.location=*/input.location,
+                 /*.numberOfDimensions=*/static_cast<uint32_t>(input.dimensions.size())});
+        data.push_back(datum);
+
+        // package operand dimensions
+        for (uint32_t dimension : input.dimensions) {
+            FmqRequestDatum datum;
+            datum.inputOperandDimensionValue(dimension);
+            data.push_back(datum);
+        }
+    }
+
+    // package output data
+    for (const auto& output : request.outputs) {
+        // package operand information
+        FmqRequestDatum datum;
+        datum.outputOperandInformation(
+                {/*.hasNoValue=*/output.hasNoValue,
+                 /*.location=*/output.location,
+                 /*.numberOfDimensions=*/static_cast<uint32_t>(output.dimensions.size())});
+        data.push_back(datum);
+
+        // package operand dimensions
+        for (uint32_t dimension : output.dimensions) {
+            FmqRequestDatum datum;
+            datum.outputOperandDimensionValue(dimension);
+            data.push_back(datum);
+        }
+    }
+
+    // package pool identifier
+    for (int32_t slot : slots) {
+        FmqRequestDatum datum;
+        datum.poolIdentifier(slot);
+        data.push_back(datum);
+    }
+
+    // package measureTiming
+    {
+        FmqRequestDatum datum;
+        datum.measureTiming(measure);
+        data.push_back(datum);
+    }
+
+    // return packet
+    return data;
+}
+
+// serialize result
+std::vector<FmqResultDatum> serialize(V1_0::ErrorStatus errorStatus,
+                                      const std::vector<V1_2::OutputShape>& outputShapes,
+                                      V1_2::Timing timing) {
+    // count how many elements need to be sent for a request
+    size_t count = 2 + outputShapes.size();
+    for (const auto& outputShape : outputShapes) {
+        count += outputShape.dimensions.size();
+    }
+
+    // create buffer to temporarily store elements
+    std::vector<FmqResultDatum> data;
+    data.reserve(count);
+
+    // package packetInfo
+    {
+        FmqResultDatum datum;
+        datum.packetInformation({/*.packetSize=*/static_cast<uint32_t>(count),
+                                 /*.errorStatus=*/errorStatus,
+                                 /*.numberOfOperands=*/static_cast<uint32_t>(outputShapes.size())});
+        data.push_back(datum);
+    }
+
+    // package output shape data
+    for (const auto& operand : outputShapes) {
+        // package operand information
+        FmqResultDatum::OperandInformation info{};
+        info.isSufficient = operand.isSufficient;
+        info.numberOfDimensions = static_cast<uint32_t>(operand.dimensions.size());
+
+        FmqResultDatum datum;
+        datum.operandInformation(info);
+        data.push_back(datum);
+
+        // package operand dimensions
+        for (uint32_t dimension : operand.dimensions) {
+            FmqResultDatum datum;
+            datum.operandDimensionValue(dimension);
+            data.push_back(datum);
+        }
+    }
+
+    // package executionTiming
+    {
+        FmqResultDatum datum;
+        datum.executionTiming(timing);
+        data.push_back(datum);
+    }
+
+    // return result
+    return data;
+}
+
+// deserialize request
+std::optional<std::tuple<V1_0::Request, std::vector<int32_t>, V1_2::MeasureTiming>> deserialize(
+        const std::vector<FmqRequestDatum>& data) {
+    using discriminator = FmqRequestDatum::hidl_discriminator;
+
+    size_t index = 0;
+
+    // validate packet information
+    if (data.size() == 0 || data[index].getDiscriminator() != discriminator::packetInformation) {
+        LOG(ERROR) << "FMQ Request packet ill-formed";
+        return std::nullopt;
+    }
+
+    // unpackage packet information
+    const FmqRequestDatum::PacketInformation& packetInfo = data[index].packetInformation();
+    index++;
+    const uint32_t packetSize = packetInfo.packetSize;
+    const uint32_t numberOfInputOperands = packetInfo.numberOfInputOperands;
+    const uint32_t numberOfOutputOperands = packetInfo.numberOfOutputOperands;
+    const uint32_t numberOfPools = packetInfo.numberOfPools;
+
+    // verify packet size
+    if (data.size() != packetSize) {
+        LOG(ERROR) << "FMQ Request packet ill-formed";
+        return std::nullopt;
+    }
+
+    // unpackage input operands
+    std::vector<V1_0::RequestArgument> inputs;
+    inputs.reserve(numberOfInputOperands);
+    for (size_t operand = 0; operand < numberOfInputOperands; ++operand) {
+        // validate input operand information
+        if (data[index].getDiscriminator() != discriminator::inputOperandInformation) {
+            LOG(ERROR) << "FMQ Request packet ill-formed";
+            return std::nullopt;
+        }
+
+        // unpackage operand information
+        const FmqRequestDatum::OperandInformation& operandInfo =
+                data[index].inputOperandInformation();
+        index++;
+        const bool hasNoValue = operandInfo.hasNoValue;
+        const V1_0::DataLocation location = operandInfo.location;
+        const uint32_t numberOfDimensions = operandInfo.numberOfDimensions;
+
+        // unpackage operand dimensions
+        std::vector<uint32_t> dimensions;
+        dimensions.reserve(numberOfDimensions);
+        for (size_t i = 0; i < numberOfDimensions; ++i) {
+            // validate dimension
+            if (data[index].getDiscriminator() != discriminator::inputOperandDimensionValue) {
+                LOG(ERROR) << "FMQ Request packet ill-formed";
+                return std::nullopt;
+            }
+
+            // unpackage dimension
+            const uint32_t dimension = data[index].inputOperandDimensionValue();
+            index++;
+
+            // store result
+            dimensions.push_back(dimension);
+        }
+
+        // store result
+        inputs.push_back(
+                {/*.hasNoValue=*/hasNoValue, /*.location=*/location, /*.dimensions=*/dimensions});
+    }
+
+    // unpackage output operands
+    std::vector<V1_0::RequestArgument> outputs;
+    outputs.reserve(numberOfOutputOperands);
+    for (size_t operand = 0; operand < numberOfOutputOperands; ++operand) {
+        // validate output operand information
+        if (data[index].getDiscriminator() != discriminator::outputOperandInformation) {
+            LOG(ERROR) << "FMQ Request packet ill-formed";
+            return std::nullopt;
+        }
+
+        // unpackage operand information
+        const FmqRequestDatum::OperandInformation& operandInfo =
+                data[index].outputOperandInformation();
+        index++;
+        const bool hasNoValue = operandInfo.hasNoValue;
+        const V1_0::DataLocation location = operandInfo.location;
+        const uint32_t numberOfDimensions = operandInfo.numberOfDimensions;
+
+        // unpackage operand dimensions
+        std::vector<uint32_t> dimensions;
+        dimensions.reserve(numberOfDimensions);
+        for (size_t i = 0; i < numberOfDimensions; ++i) {
+            // validate dimension
+            if (data[index].getDiscriminator() != discriminator::outputOperandDimensionValue) {
+                LOG(ERROR) << "FMQ Request packet ill-formed";
+                return std::nullopt;
+            }
+
+            // unpackage dimension
+            const uint32_t dimension = data[index].outputOperandDimensionValue();
+            index++;
+
+            // store result
+            dimensions.push_back(dimension);
+        }
+
+        // store result
+        outputs.push_back(
+                {/*.hasNoValue=*/hasNoValue, /*.location=*/location, /*.dimensions=*/dimensions});
+    }
+
+    // unpackage pools
+    std::vector<int32_t> slots;
+    slots.reserve(numberOfPools);
+    for (size_t pool = 0; pool < numberOfPools; ++pool) {
+        // validate input operand information
+        if (data[index].getDiscriminator() != discriminator::poolIdentifier) {
+            LOG(ERROR) << "FMQ Request packet ill-formed";
+            return std::nullopt;
+        }
+
+        // unpackage operand information
+        const int32_t poolId = data[index].poolIdentifier();
+        index++;
+
+        // store result
+        slots.push_back(poolId);
+    }
+
+    // validate measureTiming
+    if (data[index].getDiscriminator() != discriminator::measureTiming) {
+        LOG(ERROR) << "FMQ Request packet ill-formed";
+        return std::nullopt;
+    }
+
+    // unpackage measureTiming
+    const V1_2::MeasureTiming measure = data[index].measureTiming();
+    index++;
+
+    // validate packet information
+    if (index != packetSize) {
+        LOG(ERROR) << "FMQ Result packet ill-formed";
+        return std::nullopt;
+    }
+
+    // return request
+    V1_0::Request request = {/*.inputs=*/inputs, /*.outputs=*/outputs, /*.pools=*/{}};
+    return std::make_tuple(std::move(request), std::move(slots), measure);
+}
+
+// deserialize a packet into the result
+std::optional<std::tuple<V1_0::ErrorStatus, std::vector<V1_2::OutputShape>, V1_2::Timing>>
+deserialize(const std::vector<FmqResultDatum>& data) {
+    using discriminator = FmqResultDatum::hidl_discriminator;
+
+    std::vector<V1_2::OutputShape> outputShapes;
+    size_t index = 0;
+
+    // validate packet information
+    if (data.size() == 0 || data[index].getDiscriminator() != discriminator::packetInformation) {
+        LOG(ERROR) << "FMQ Result packet ill-formed";
+        return std::nullopt;
+    }
+
+    // unpackage packet information
+    const FmqResultDatum::PacketInformation& packetInfo = data[index].packetInformation();
+    index++;
+    const uint32_t packetSize = packetInfo.packetSize;
+    const V1_0::ErrorStatus errorStatus = packetInfo.errorStatus;
+    const uint32_t numberOfOperands = packetInfo.numberOfOperands;
+
+    // verify packet size
+    if (data.size() != packetSize) {
+        LOG(ERROR) << "FMQ Result packet ill-formed";
+        return std::nullopt;
+    }
+
+    // unpackage operands
+    for (size_t operand = 0; operand < numberOfOperands; ++operand) {
+        // validate operand information
+        if (data[index].getDiscriminator() != discriminator::operandInformation) {
+            LOG(ERROR) << "FMQ Result packet ill-formed";
+            return std::nullopt;
+        }
+
+        // unpackage operand information
+        const FmqResultDatum::OperandInformation& operandInfo = data[index].operandInformation();
+        index++;
+        const bool isSufficient = operandInfo.isSufficient;
+        const uint32_t numberOfDimensions = operandInfo.numberOfDimensions;
+
+        // unpackage operand dimensions
+        std::vector<uint32_t> dimensions;
+        dimensions.reserve(numberOfDimensions);
+        for (size_t i = 0; i < numberOfDimensions; ++i) {
+            // validate dimension
+            if (data[index].getDiscriminator() != discriminator::operandDimensionValue) {
+                LOG(ERROR) << "FMQ Result packet ill-formed";
+                return std::nullopt;
+            }
+
+            // unpackage dimension
+            const uint32_t dimension = data[index].operandDimensionValue();
+            index++;
+
+            // store result
+            dimensions.push_back(dimension);
+        }
+
+        // store result
+        outputShapes.push_back({/*.dimensions=*/dimensions, /*.isSufficient=*/isSufficient});
+    }
+
+    // validate execution timing
+    if (data[index].getDiscriminator() != discriminator::executionTiming) {
+        LOG(ERROR) << "FMQ Result packet ill-formed";
+        return std::nullopt;
+    }
+
+    // unpackage execution timing
+    const V1_2::Timing timing = data[index].executionTiming();
+    index++;
+
+    // validate packet information
+    if (index != packetSize) {
+        LOG(ERROR) << "FMQ Result packet ill-formed";
+        return std::nullopt;
+    }
+
+    // return result
+    return std::make_tuple(errorStatus, std::move(outputShapes), timing);
+}
+
+V1_0::ErrorStatus legacyConvertResultCodeToErrorStatus(int resultCode) {
+    return convertToV1_0(convertResultCodeToErrorStatus(resultCode));
+}
+
+// RequestChannelSender methods
+
+std::pair<std::unique_ptr<RequestChannelSender>, const FmqRequestDescriptor*>
+RequestChannelSender::create(size_t channelLength) {
+    std::unique_ptr<FmqRequestChannel> fmqRequestChannel =
+            std::make_unique<FmqRequestChannel>(channelLength, /*confEventFlag=*/true);
+    if (!fmqRequestChannel->isValid()) {
+        LOG(ERROR) << "Unable to create RequestChannelSender";
+        return {nullptr, nullptr};
+    }
+
+    const FmqRequestDescriptor* descriptor = fmqRequestChannel->getDesc();
+    return std::make_pair(std::make_unique<RequestChannelSender>(std::move(fmqRequestChannel)),
+                          descriptor);
+}
+
+RequestChannelSender::RequestChannelSender(std::unique_ptr<FmqRequestChannel> fmqRequestChannel)
+    : mFmqRequestChannel(std::move(fmqRequestChannel)) {}
+
+bool RequestChannelSender::send(const V1_0::Request& request, V1_2::MeasureTiming measure,
+                                const std::vector<int32_t>& slots) {
+    const std::vector<FmqRequestDatum> serialized = serialize(request, measure, slots);
+    return sendPacket(serialized);
+}
+
+bool RequestChannelSender::sendPacket(const std::vector<FmqRequestDatum>& packet) {
+    if (!mValid) {
+        return false;
+    }
+
+    if (packet.size() > mFmqRequestChannel->availableToWrite()) {
+        LOG(ERROR)
+                << "RequestChannelSender::sendPacket -- packet size exceeds size available in FMQ";
+        return false;
+    }
+
+    // Always send the packet with "blocking" because this signals the futex and
+    // unblocks the consumer if it is waiting on the futex.
+    return mFmqRequestChannel->writeBlocking(packet.data(), packet.size());
+}
+
+void RequestChannelSender::invalidate() {
+    mValid = false;
+}
+
+// RequestChannelReceiver methods
+
+std::unique_ptr<RequestChannelReceiver> RequestChannelReceiver::create(
+        const FmqRequestDescriptor& requestChannel, std::chrono::microseconds pollingTimeWindow) {
+    std::unique_ptr<FmqRequestChannel> fmqRequestChannel =
+            std::make_unique<FmqRequestChannel>(requestChannel);
+
+    if (!fmqRequestChannel->isValid()) {
+        LOG(ERROR) << "Unable to create RequestChannelReceiver";
+        return nullptr;
+    }
+    if (fmqRequestChannel->getEventFlagWord() == nullptr) {
+        LOG(ERROR)
+                << "RequestChannelReceiver::create was passed an MQDescriptor without an EventFlag";
+        return nullptr;
+    }
+
+    return std::make_unique<RequestChannelReceiver>(std::move(fmqRequestChannel),
+                                                    pollingTimeWindow);
+}
+
+RequestChannelReceiver::RequestChannelReceiver(std::unique_ptr<FmqRequestChannel> fmqRequestChannel,
+                                               std::chrono::microseconds pollingTimeWindow)
+    : mFmqRequestChannel(std::move(fmqRequestChannel)), kPollingTimeWindow(pollingTimeWindow) {}
+
+std::optional<std::tuple<V1_0::Request, std::vector<int32_t>, V1_2::MeasureTiming>>
+RequestChannelReceiver::getBlocking() {
+    const auto packet = getPacketBlocking();
+    if (!packet) {
+        return std::nullopt;
+    }
+
+    return deserialize(*packet);
+}
+
+void RequestChannelReceiver::invalidate() {
+    mTeardown = true;
+
+    // force unblock
+    // ExecutionBurstServer is by default waiting on a request packet. If the
+    // client process destroys its burst object, the server may still be waiting
+    // on the futex. This force unblock wakes up any thread waiting on the
+    // futex.
+    // TODO: look for a different/better way to signal/notify the futex to wake
+    // up any thread waiting on it
+    FmqRequestDatum datum;
+    datum.packetInformation({/*.packetSize=*/0, /*.numberOfInputOperands=*/0,
+                             /*.numberOfOutputOperands=*/0, /*.numberOfPools=*/0});
+    mFmqRequestChannel->writeBlocking(&datum, 1);
+}
+
+std::optional<std::vector<FmqRequestDatum>> RequestChannelReceiver::getPacketBlocking() {
+    if (mTeardown) {
+        return std::nullopt;
+    }
+
+    // First spend time polling if results are available in FMQ instead of
+    // waiting on the futex. Polling is more responsive (yielding lower
+    // latencies), but can take up more power, so only poll for a limited period
+    // of time.
+
+    auto& getCurrentTime = std::chrono::high_resolution_clock::now;
+    const auto timeToStopPolling = getCurrentTime() + kPollingTimeWindow;
+
+    while (getCurrentTime() < timeToStopPolling) {
+        // if class is being torn down, immediately return
+        if (mTeardown.load(std::memory_order_relaxed)) {
+            return std::nullopt;
+        }
+
+        // Check if data is available. If it is, immediately retrieve it and
+        // return.
+        const size_t available = mFmqRequestChannel->availableToRead();
+        if (available > 0) {
+            // This is the first point when we know an execution is occurring,
+            // so begin to collect systraces. Note that a similar systrace does
+            // not exist at the corresponding point in
+            // ResultChannelReceiver::getPacketBlocking because the execution is
+            // already in flight.
+            NNTRACE_FULL(NNTRACE_LAYER_IPC, NNTRACE_PHASE_EXECUTION,
+                         "ExecutionBurstServer getting packet");
+            std::vector<FmqRequestDatum> packet(available);
+            const bool success = mFmqRequestChannel->read(packet.data(), available);
+            if (!success) {
+                LOG(ERROR) << "Error receiving packet";
+                return std::nullopt;
+            }
+            return std::make_optional(std::move(packet));
+        }
+    }
+
+    // If we get to this point, we either stopped polling because it was taking
+    // too long or polling was not allowed. Instead, perform a blocking call
+    // which uses a futex to save power.
+
+    // wait for request packet and read first element of request packet
+    FmqRequestDatum datum;
+    bool success = mFmqRequestChannel->readBlocking(&datum, 1);
+
+    // This is the first point when we know an execution is occurring, so begin
+    // to collect systraces. Note that a similar systrace does not exist at the
+    // corresponding point in ResultChannelReceiver::getPacketBlocking because
+    // the execution is already in flight.
+    NNTRACE_FULL(NNTRACE_LAYER_IPC, NNTRACE_PHASE_EXECUTION, "ExecutionBurstServer getting packet");
+
+    // retrieve remaining elements
+    // NOTE: all of the data is already available at this point, so there's no
+    // need to do a blocking wait to wait for more data. This is known because
+    // in FMQ, all writes are published (made available) atomically. Currently,
+    // the producer always publishes the entire packet in one function call, so
+    // if the first element of the packet is available, the remaining elements
+    // are also available.
+    const size_t count = mFmqRequestChannel->availableToRead();
+    std::vector<FmqRequestDatum> packet(count + 1);
+    std::memcpy(&packet.front(), &datum, sizeof(datum));
+    success &= mFmqRequestChannel->read(packet.data() + 1, count);
+
+    // terminate loop
+    if (mTeardown) {
+        return std::nullopt;
+    }
+
+    // ensure packet was successfully received
+    if (!success) {
+        LOG(ERROR) << "Error receiving packet";
+        return std::nullopt;
+    }
+
+    return std::make_optional(std::move(packet));
+}
+
+// ResultChannelSender methods
+
+std::unique_ptr<ResultChannelSender> ResultChannelSender::create(
+        const FmqResultDescriptor& resultChannel) {
+    std::unique_ptr<FmqResultChannel> fmqResultChannel =
+            std::make_unique<FmqResultChannel>(resultChannel);
+
+    if (!fmqResultChannel->isValid()) {
+        LOG(ERROR) << "Unable to create RequestChannelSender";
+        return nullptr;
+    }
+    if (fmqResultChannel->getEventFlagWord() == nullptr) {
+        LOG(ERROR) << "ResultChannelSender::create was passed an MQDescriptor without an EventFlag";
+        return nullptr;
+    }
+
+    return std::make_unique<ResultChannelSender>(std::move(fmqResultChannel));
+}
+
+ResultChannelSender::ResultChannelSender(std::unique_ptr<FmqResultChannel> fmqResultChannel)
+    : mFmqResultChannel(std::move(fmqResultChannel)) {}
+
+bool ResultChannelSender::send(V1_0::ErrorStatus errorStatus,
+                               const std::vector<V1_2::OutputShape>& outputShapes,
+                               V1_2::Timing timing) {
+    const std::vector<FmqResultDatum> serialized = serialize(errorStatus, outputShapes, timing);
+    return sendPacket(serialized);
+}
+
+bool ResultChannelSender::sendPacket(const std::vector<FmqResultDatum>& packet) {
+    if (packet.size() > mFmqResultChannel->availableToWrite()) {
+        LOG(ERROR)
+                << "ResultChannelSender::sendPacket -- packet size exceeds size available in FMQ";
+        const std::vector<FmqResultDatum> errorPacket =
+                serialize(V1_0::ErrorStatus::GENERAL_FAILURE, {}, kNoTiming);
+
+        // Always send the packet with "blocking" because this signals the futex
+        // and unblocks the consumer if it is waiting on the futex.
+        return mFmqResultChannel->writeBlocking(errorPacket.data(), errorPacket.size());
+    }
+
+    // Always send the packet with "blocking" because this signals the futex and
+    // unblocks the consumer if it is waiting on the futex.
+    return mFmqResultChannel->writeBlocking(packet.data(), packet.size());
+}
+
+// ResultChannelReceiver methods
+
+std::pair<std::unique_ptr<ResultChannelReceiver>, const FmqResultDescriptor*>
+ResultChannelReceiver::create(size_t channelLength, std::chrono::microseconds pollingTimeWindow) {
+    std::unique_ptr<FmqResultChannel> fmqResultChannel =
+            std::make_unique<FmqResultChannel>(channelLength, /*confEventFlag=*/true);
+    if (!fmqResultChannel->isValid()) {
+        LOG(ERROR) << "Unable to create ResultChannelReceiver";
+        return {nullptr, nullptr};
+    }
+
+    const FmqResultDescriptor* descriptor = fmqResultChannel->getDesc();
+    return std::make_pair(
+            std::make_unique<ResultChannelReceiver>(std::move(fmqResultChannel), pollingTimeWindow),
+            descriptor);
+}
+
+ResultChannelReceiver::ResultChannelReceiver(std::unique_ptr<FmqResultChannel> fmqResultChannel,
+                                             std::chrono::microseconds pollingTimeWindow)
+    : mFmqResultChannel(std::move(fmqResultChannel)), kPollingTimeWindow(pollingTimeWindow) {}
+
+std::optional<std::tuple<V1_0::ErrorStatus, std::vector<V1_2::OutputShape>, V1_2::Timing>>
+ResultChannelReceiver::getBlocking() {
+    const auto packet = getPacketBlocking();
+    if (!packet) {
+        return std::nullopt;
+    }
+
+    return deserialize(*packet);
+}
+
+void ResultChannelReceiver::invalidate() {
+    mValid = false;
+
+    // force unblock
+    // ExecutionBurstController waits on a result packet after sending a
+    // request. If the driver containing ExecutionBurstServer crashes, the
+    // controller may be waiting on the futex. This force unblock wakes up any
+    // thread waiting on the futex.
+    // TODO: look for a different/better way to signal/notify the futex to
+    // wake up any thread waiting on it
+    FmqResultDatum datum;
+    datum.packetInformation({/*.packetSize=*/0,
+                             /*.errorStatus=*/V1_0::ErrorStatus::GENERAL_FAILURE,
+                             /*.numberOfOperands=*/0});
+    mFmqResultChannel->writeBlocking(&datum, 1);
+}
+
+std::optional<std::vector<FmqResultDatum>> ResultChannelReceiver::getPacketBlocking() {
+    if (!mValid) {
+        return std::nullopt;
+    }
+
+    // First spend time polling if results are available in FMQ instead of
+    // waiting on the futex. Polling is more responsive (yielding lower
+    // latencies), but can take up more power, so only poll for a limited period
+    // of time.
+
+    auto& getCurrentTime = std::chrono::high_resolution_clock::now;
+    const auto timeToStopPolling = getCurrentTime() + kPollingTimeWindow;
+
+    while (getCurrentTime() < timeToStopPolling) {
+        // if class is being torn down, immediately return
+        if (!mValid.load(std::memory_order_relaxed)) {
+            return std::nullopt;
+        }
+
+        // Check if data is available. If it is, immediately retrieve it and
+        // return.
+        const size_t available = mFmqResultChannel->availableToRead();
+        if (available > 0) {
+            std::vector<FmqResultDatum> packet(available);
+            const bool success = mFmqResultChannel->read(packet.data(), available);
+            if (!success) {
+                LOG(ERROR) << "Error receiving packet";
+                return std::nullopt;
+            }
+            return std::make_optional(std::move(packet));
+        }
+    }
+
+    // If we get to this point, we either stopped polling because it was taking
+    // too long or polling was not allowed. Instead, perform a blocking call
+    // which uses a futex to save power.
+
+    // wait for result packet and read first element of result packet
+    FmqResultDatum datum;
+    bool success = mFmqResultChannel->readBlocking(&datum, 1);
+
+    // retrieve remaining elements
+    // NOTE: all of the data is already available at this point, so there's no
+    // need to do a blocking wait to wait for more data. This is known because
+    // in FMQ, all writes are published (made available) atomically. Currently,
+    // the producer always publishes the entire packet in one function call, so
+    // if the first element of the packet is available, the remaining elements
+    // are also available.
+    const size_t count = mFmqResultChannel->availableToRead();
+    std::vector<FmqResultDatum> packet(count + 1);
+    std::memcpy(&packet.front(), &datum, sizeof(datum));
+    success &= mFmqResultChannel->read(packet.data() + 1, count);
+
+    if (!mValid) {
+        return std::nullopt;
+    }
+
+    // ensure packet was successfully received
+    if (!success) {
+        LOG(ERROR) << "Error receiving packet";
+        return std::nullopt;
+    }
+
+    return std::make_optional(std::move(packet));
+}
+
+}  // namespace android::hardware::neuralnetworks::V1_2::utils
diff --git a/neuralnetworks/1.2/utils/src/PreparedModel.cpp b/neuralnetworks/1.2/utils/src/PreparedModel.cpp
index 6d00082..6841c5e 100644
--- a/neuralnetworks/1.2/utils/src/PreparedModel.cpp
+++ b/neuralnetworks/1.2/utils/src/PreparedModel.cpp
@@ -27,6 +27,7 @@
 #include <nnapi/IPreparedModel.h>
 #include <nnapi/Result.h>
 #include <nnapi/Types.h>
+#include <nnapi/hal/1.0/Burst.h>
 #include <nnapi/hal/1.0/Conversions.h>
 #include <nnapi/hal/CommonUtils.h>
 #include <nnapi/hal/HandleError.h>
@@ -117,6 +118,10 @@
            << "IPreparedModel::executeFenced is not supported on 1.2 HAL service";
 }
 
+nn::GeneralResult<nn::SharedBurst> PreparedModel::configureExecutionBurst() const {
+    return V1_0::utils::Burst::create(shared_from_this());
+}
+
 std::any PreparedModel::getUnderlyingResource() const {
     sp<V1_2::IPreparedModel> resource = kPreparedModel;
     return resource;
diff --git a/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Device.h b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Device.h
index 84f606a..f36b6c0 100644
--- a/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Device.h
+++ b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Device.h
@@ -54,6 +54,7 @@
     const std::string& getVersionString() const override;
     nn::Version getFeatureLevel() const override;
     nn::DeviceType getType() const override;
+    bool isUpdatable() const override;
     const std::vector<nn::Extension>& getSupportedExtensions() const override;
     const nn::Capabilities& getCapabilities() const override;
     std::pair<uint32_t, uint32_t> getNumberOfCacheFilesNeeded() const override;
diff --git a/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/PreparedModel.h b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/PreparedModel.h
index 664d87a..690fecc 100644
--- a/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/PreparedModel.h
+++ b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/PreparedModel.h
@@ -35,7 +35,8 @@
 namespace android::hardware::neuralnetworks::V1_3::utils {
 
 // Class that adapts V1_3::IPreparedModel to nn::IPreparedModel.
-class PreparedModel final : public nn::IPreparedModel {
+class PreparedModel final : public nn::IPreparedModel,
+                            public std::enable_shared_from_this<PreparedModel> {
     struct PrivateConstructorTag {};
 
   public:
@@ -56,6 +57,8 @@
             const nn::OptionalDuration& loopTimeoutDuration,
             const nn::OptionalDuration& timeoutDurationAfterFence) const override;
 
+    nn::GeneralResult<nn::SharedBurst> configureExecutionBurst() const override;
+
     std::any getUnderlyingResource() const override;
 
   private:
diff --git a/neuralnetworks/1.3/utils/src/Device.cpp b/neuralnetworks/1.3/utils/src/Device.cpp
index d710b85..87c9f32 100644
--- a/neuralnetworks/1.3/utils/src/Device.cpp
+++ b/neuralnetworks/1.3/utils/src/Device.cpp
@@ -150,6 +150,10 @@
     return kDeviceType;
 }
 
+bool Device::isUpdatable() const {
+    return false;
+}
+
 const std::vector<nn::Extension>& Device::getSupportedExtensions() const {
     return kExtensions;
 }
diff --git a/neuralnetworks/1.3/utils/src/PreparedModel.cpp b/neuralnetworks/1.3/utils/src/PreparedModel.cpp
index 7b4b7ba..725e4f5 100644
--- a/neuralnetworks/1.3/utils/src/PreparedModel.cpp
+++ b/neuralnetworks/1.3/utils/src/PreparedModel.cpp
@@ -29,6 +29,7 @@
 #include <nnapi/Result.h>
 #include <nnapi/TypeUtils.h>
 #include <nnapi/Types.h>
+#include <nnapi/hal/1.0/Burst.h>
 #include <nnapi/hal/1.2/Conversions.h>
 #include <nnapi/hal/CommonUtils.h>
 #include <nnapi/hal/HandleError.h>
@@ -197,6 +198,10 @@
     return std::make_pair(std::move(syncFence), std::move(callback));
 }
 
+nn::GeneralResult<nn::SharedBurst> PreparedModel::configureExecutionBurst() const {
+    return V1_0::utils::Burst::create(shared_from_this());
+}
+
 std::any PreparedModel::getUnderlyingResource() const {
     sp<V1_3::IPreparedModel> resource = kPreparedModel;
     return resource;
diff --git a/neuralnetworks/utils/common/include/nnapi/hal/InvalidBurst.h b/neuralnetworks/utils/common/include/nnapi/hal/InvalidBurst.h
new file mode 100644
index 0000000..83e60b6
--- /dev/null
+++ b/neuralnetworks/utils/common/include/nnapi/hal/InvalidBurst.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_INVALID_BURST_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_INVALID_BURST_H
+
+#include <nnapi/IBurst.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+
+#include <memory>
+#include <optional>
+#include <utility>
+
+namespace android::hardware::neuralnetworks::utils {
+
+class InvalidBurst final : public nn::IBurst {
+  public:
+    OptionalCacheHold cacheMemory(const nn::Memory& memory) const override;
+
+    nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> execute(
+            const nn::Request& request, nn::MeasureTiming measure) const override;
+};
+
+}  // namespace android::hardware::neuralnetworks::utils
+
+#endif  // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_INVALID_BURST_H
diff --git a/neuralnetworks/utils/common/include/nnapi/hal/InvalidDevice.h b/neuralnetworks/utils/common/include/nnapi/hal/InvalidDevice.h
index 5e62b9a..d843526 100644
--- a/neuralnetworks/utils/common/include/nnapi/hal/InvalidDevice.h
+++ b/neuralnetworks/utils/common/include/nnapi/hal/InvalidDevice.h
@@ -32,7 +32,7 @@
 class InvalidDevice final : public nn::IDevice {
   public:
     InvalidDevice(std::string name, std::string versionString, nn::Version featureLevel,
-                  nn::DeviceType type, std::vector<nn::Extension> extensions,
+                  nn::DeviceType type, bool isUpdatable, std::vector<nn::Extension> extensions,
                   nn::Capabilities capabilities,
                   std::pair<uint32_t, uint32_t> numberOfCacheFilesNeeded);
 
@@ -40,6 +40,7 @@
     const std::string& getVersionString() const override;
     nn::Version getFeatureLevel() const override;
     nn::DeviceType getType() const override;
+    bool isUpdatable() const override;
     const std::vector<nn::Extension>& getSupportedExtensions() const override;
     const nn::Capabilities& getCapabilities() const override;
     std::pair<uint32_t, uint32_t> getNumberOfCacheFilesNeeded() const override;
@@ -70,6 +71,7 @@
     const std::string kVersionString;
     const nn::Version kFeatureLevel;
     const nn::DeviceType kType;
+    const bool kIsUpdatable;
     const std::vector<nn::Extension> kExtensions;
     const nn::Capabilities kCapabilities;
     const std::pair<uint32_t, uint32_t> kNumberOfCacheFilesNeeded;
diff --git a/neuralnetworks/utils/common/include/nnapi/hal/InvalidPreparedModel.h b/neuralnetworks/utils/common/include/nnapi/hal/InvalidPreparedModel.h
index 985cddb..3e1dca7 100644
--- a/neuralnetworks/utils/common/include/nnapi/hal/InvalidPreparedModel.h
+++ b/neuralnetworks/utils/common/include/nnapi/hal/InvalidPreparedModel.h
@@ -40,6 +40,8 @@
             const nn::OptionalDuration& loopTimeoutDuration,
             const nn::OptionalDuration& timeoutDurationAfterFence) const override;
 
+    nn::GeneralResult<nn::SharedBurst> configureExecutionBurst() const override;
+
     std::any getUnderlyingResource() const override;
 };
 
diff --git a/neuralnetworks/utils/common/include/nnapi/hal/ResilientBurst.h b/neuralnetworks/utils/common/include/nnapi/hal/ResilientBurst.h
new file mode 100644
index 0000000..0df287f
--- /dev/null
+++ b/neuralnetworks/utils/common/include/nnapi/hal/ResilientBurst.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_RESILIENT_BURST_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_RESILIENT_BURST_H
+
+#include <android-base/thread_annotations.h>
+#include <nnapi/IBurst.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+
+#include <functional>
+#include <memory>
+#include <mutex>
+#include <optional>
+#include <utility>
+
+namespace android::hardware::neuralnetworks::utils {
+
+class ResilientBurst final : public nn::IBurst,
+                             public std::enable_shared_from_this<ResilientBurst> {
+    struct PrivateConstructorTag {};
+
+  public:
+    using Factory = std::function<nn::GeneralResult<nn::SharedBurst>()>;
+
+    static nn::GeneralResult<std::shared_ptr<const ResilientBurst>> create(Factory makeBurst);
+
+    ResilientBurst(PrivateConstructorTag tag, Factory makeBurst, nn::SharedBurst burst);
+
+    nn::SharedBurst getBurst() const;
+    nn::GeneralResult<nn::SharedBurst> recover(const nn::IBurst* failingBurst) const;
+
+    OptionalCacheHold cacheMemory(const nn::Memory& memory) const override;
+
+    nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> execute(
+            const nn::Request& request, nn::MeasureTiming measure) const override;
+
+  private:
+    const Factory kMakeBurst;
+    mutable std::mutex mMutex;
+    mutable nn::SharedBurst mBurst GUARDED_BY(mMutex);
+};
+
+}  // namespace android::hardware::neuralnetworks::utils
+
+#endif  // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_RESILIENT_BURST_H
diff --git a/neuralnetworks/utils/common/include/nnapi/hal/ResilientDevice.h b/neuralnetworks/utils/common/include/nnapi/hal/ResilientDevice.h
index 84ae799..8199c52 100644
--- a/neuralnetworks/utils/common/include/nnapi/hal/ResilientDevice.h
+++ b/neuralnetworks/utils/common/include/nnapi/hal/ResilientDevice.h
@@ -53,6 +53,7 @@
     const std::string& getVersionString() const override;
     nn::Version getFeatureLevel() const override;
     nn::DeviceType getType() const override;
+    bool isUpdatable() const override;
     const std::vector<nn::Extension>& getSupportedExtensions() const override;
     const nn::Capabilities& getCapabilities() const override;
     std::pair<uint32_t, uint32_t> getNumberOfCacheFilesNeeded() const override;
diff --git a/neuralnetworks/utils/common/include/nnapi/hal/ResilientPreparedModel.h b/neuralnetworks/utils/common/include/nnapi/hal/ResilientPreparedModel.h
index 9b8d924..a6c1b19 100644
--- a/neuralnetworks/utils/common/include/nnapi/hal/ResilientPreparedModel.h
+++ b/neuralnetworks/utils/common/include/nnapi/hal/ResilientPreparedModel.h
@@ -30,7 +30,8 @@
 
 namespace android::hardware::neuralnetworks::utils {
 
-class ResilientPreparedModel final : public nn::IPreparedModel {
+class ResilientPreparedModel final : public nn::IPreparedModel,
+                                     public std::enable_shared_from_this<ResilientPreparedModel> {
     struct PrivateConstructorTag {};
 
   public:
@@ -57,9 +58,14 @@
             const nn::OptionalDuration& loopTimeoutDuration,
             const nn::OptionalDuration& timeoutDurationAfterFence) const override;
 
+    nn::GeneralResult<nn::SharedBurst> configureExecutionBurst() const override;
+
     std::any getUnderlyingResource() const override;
 
   private:
+    bool isValidInternal() const EXCLUDES(mMutex);
+    nn::GeneralResult<nn::SharedBurst> configureExecutionBurstInternal() const;
+
     const Factory kMakePreparedModel;
     mutable std::mutex mMutex;
     mutable nn::SharedPreparedModel mPreparedModel GUARDED_BY(mMutex);
diff --git a/neuralnetworks/utils/common/src/InvalidBurst.cpp b/neuralnetworks/utils/common/src/InvalidBurst.cpp
new file mode 100644
index 0000000..4ca6603
--- /dev/null
+++ b/neuralnetworks/utils/common/src/InvalidBurst.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "InvalidBurst.h"
+
+#include <nnapi/IBurst.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+
+#include <memory>
+#include <optional>
+#include <utility>
+
+namespace android::hardware::neuralnetworks::utils {
+
+InvalidBurst::OptionalCacheHold InvalidBurst::cacheMemory(const nn::Memory& /*memory*/) const {
+    return nullptr;
+}
+
+nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> InvalidBurst::execute(
+        const nn::Request& /*request*/, nn::MeasureTiming /*measure*/) const {
+    return NN_ERROR() << "InvalidBurst";
+}
+
+}  // namespace android::hardware::neuralnetworks::utils
diff --git a/neuralnetworks/utils/common/src/InvalidDevice.cpp b/neuralnetworks/utils/common/src/InvalidDevice.cpp
index 535ccb4..81bca7f 100644
--- a/neuralnetworks/utils/common/src/InvalidDevice.cpp
+++ b/neuralnetworks/utils/common/src/InvalidDevice.cpp
@@ -32,13 +32,14 @@
 namespace android::hardware::neuralnetworks::utils {
 
 InvalidDevice::InvalidDevice(std::string name, std::string versionString, nn::Version featureLevel,
-                             nn::DeviceType type, std::vector<nn::Extension> extensions,
-                             nn::Capabilities capabilities,
+                             nn::DeviceType type, bool isUpdatable,
+                             std::vector<nn::Extension> extensions, nn::Capabilities capabilities,
                              std::pair<uint32_t, uint32_t> numberOfCacheFilesNeeded)
     : kName(std::move(name)),
       kVersionString(std::move(versionString)),
       kFeatureLevel(featureLevel),
       kType(type),
+      kIsUpdatable(isUpdatable),
       kExtensions(std::move(extensions)),
       kCapabilities(std::move(capabilities)),
       kNumberOfCacheFilesNeeded(numberOfCacheFilesNeeded) {}
@@ -59,6 +60,10 @@
     return kType;
 }
 
+bool InvalidDevice::isUpdatable() const {
+    return kIsUpdatable;
+}
+
 const std::vector<nn::Extension>& InvalidDevice::getSupportedExtensions() const {
     return kExtensions;
 }
diff --git a/neuralnetworks/utils/common/src/InvalidPreparedModel.cpp b/neuralnetworks/utils/common/src/InvalidPreparedModel.cpp
index a46f4ac..9081e1f 100644
--- a/neuralnetworks/utils/common/src/InvalidPreparedModel.cpp
+++ b/neuralnetworks/utils/common/src/InvalidPreparedModel.cpp
@@ -42,6 +42,10 @@
     return NN_ERROR() << "InvalidPreparedModel";
 }
 
+nn::GeneralResult<nn::SharedBurst> InvalidPreparedModel::configureExecutionBurst() const {
+    return NN_ERROR() << "InvalidPreparedModel";
+}
+
 std::any InvalidPreparedModel::getUnderlyingResource() const {
     return {};
 }
diff --git a/neuralnetworks/utils/common/src/ResilientBurst.cpp b/neuralnetworks/utils/common/src/ResilientBurst.cpp
new file mode 100644
index 0000000..0d3cb33
--- /dev/null
+++ b/neuralnetworks/utils/common/src/ResilientBurst.cpp
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ResilientBurst.h"
+
+#include <android-base/logging.h>
+#include <android-base/thread_annotations.h>
+#include <nnapi/IBurst.h>
+#include <nnapi/Result.h>
+#include <nnapi/TypeUtils.h>
+#include <nnapi/Types.h>
+
+#include <functional>
+#include <memory>
+#include <mutex>
+#include <optional>
+#include <utility>
+
+namespace android::hardware::neuralnetworks::utils {
+namespace {
+
+template <typename FnType>
+auto protect(const ResilientBurst& resilientBurst, const FnType& fn)
+        -> decltype(fn(*resilientBurst.getBurst())) {
+    auto burst = resilientBurst.getBurst();
+    auto result = fn(*burst);
+
+    // Immediately return if burst is not dead.
+    if (result.has_value() || result.error().code != nn::ErrorStatus::DEAD_OBJECT) {
+        return result;
+    }
+
+    // Attempt recovery and return if it fails.
+    auto maybeBurst = resilientBurst.recover(burst.get());
+    if (!maybeBurst.has_value()) {
+        auto [resultErrorMessage, resultErrorCode, resultOutputShapes] = std::move(result).error();
+        const auto& [recoveryErrorMessage, recoveryErrorCode] = maybeBurst.error();
+        return nn::error(resultErrorCode, std::move(resultOutputShapes))
+               << resultErrorMessage << ", and failed to recover dead burst object with error "
+               << recoveryErrorCode << ": " << recoveryErrorMessage;
+    }
+    burst = std::move(maybeBurst).value();
+
+    return fn(*burst);
+}
+
+}  // namespace
+
+nn::GeneralResult<std::shared_ptr<const ResilientBurst>> ResilientBurst::create(Factory makeBurst) {
+    if (makeBurst == nullptr) {
+        return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
+               << "utils::ResilientBurst::create must have non-empty makeBurst";
+    }
+    auto burst = NN_TRY(makeBurst());
+    CHECK(burst != nullptr);
+    return std::make_shared<ResilientBurst>(PrivateConstructorTag{}, std::move(makeBurst),
+                                            std::move(burst));
+}
+
+ResilientBurst::ResilientBurst(PrivateConstructorTag /*tag*/, Factory makeBurst,
+                               nn::SharedBurst burst)
+    : kMakeBurst(std::move(makeBurst)), mBurst(std::move(burst)) {
+    CHECK(kMakeBurst != nullptr);
+    CHECK(mBurst != nullptr);
+}
+
+nn::SharedBurst ResilientBurst::getBurst() const {
+    std::lock_guard guard(mMutex);
+    return mBurst;
+}
+
+nn::GeneralResult<nn::SharedBurst> ResilientBurst::recover(const nn::IBurst* failingBurst) const {
+    std::lock_guard guard(mMutex);
+
+    // Another caller updated the failing burst.
+    if (mBurst.get() != failingBurst) {
+        return mBurst;
+    }
+
+    mBurst = NN_TRY(kMakeBurst());
+    return mBurst;
+}
+
+ResilientBurst::OptionalCacheHold ResilientBurst::cacheMemory(const nn::Memory& memory) const {
+    return getBurst()->cacheMemory(memory);
+}
+
+nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> ResilientBurst::execute(
+        const nn::Request& request, nn::MeasureTiming measure) const {
+    const auto fn = [&request, measure](const nn::IBurst& burst) {
+        return burst.execute(request, measure);
+    };
+    return protect(*this, fn);
+}
+
+}  // namespace android::hardware::neuralnetworks::utils
diff --git a/neuralnetworks/utils/common/src/ResilientDevice.cpp b/neuralnetworks/utils/common/src/ResilientDevice.cpp
index 2023c9a..13965af 100644
--- a/neuralnetworks/utils/common/src/ResilientDevice.cpp
+++ b/neuralnetworks/utils/common/src/ResilientDevice.cpp
@@ -122,12 +122,14 @@
     };
     if (compare(&IDevice::getName) || compare(&IDevice::getVersionString) ||
         compare(&IDevice::getFeatureLevel) || compare(&IDevice::getType) ||
-        compare(&IDevice::getSupportedExtensions) || compare(&IDevice::getCapabilities)) {
+        compare(&IDevice::isUpdatable) || compare(&IDevice::getSupportedExtensions) ||
+        compare(&IDevice::getCapabilities)) {
         LOG(ERROR) << "Recovered device has different metadata than what is cached. Marking "
                       "IDevice object as invalid.";
         device = std::make_shared<const InvalidDevice>(
-                kName, kVersionString, mDevice->getFeatureLevel(), mDevice->getType(), kExtensions,
-                kCapabilities, mDevice->getNumberOfCacheFilesNeeded());
+                kName, kVersionString, mDevice->getFeatureLevel(), mDevice->getType(),
+                mDevice->isUpdatable(), kExtensions, kCapabilities,
+                mDevice->getNumberOfCacheFilesNeeded());
         mIsValid = false;
     }
 
@@ -151,6 +153,10 @@
     return getDevice()->getType();
 }
 
+bool ResilientDevice::isUpdatable() const {
+    return getDevice()->isUpdatable();
+}
+
 const std::vector<nn::Extension>& ResilientDevice::getSupportedExtensions() const {
     return kExtensions;
 }
diff --git a/neuralnetworks/utils/common/src/ResilientPreparedModel.cpp b/neuralnetworks/utils/common/src/ResilientPreparedModel.cpp
index 667df2b..5dd5f99 100644
--- a/neuralnetworks/utils/common/src/ResilientPreparedModel.cpp
+++ b/neuralnetworks/utils/common/src/ResilientPreparedModel.cpp
@@ -16,6 +16,9 @@
 
 #include "ResilientPreparedModel.h"
 
+#include "InvalidBurst.h"
+#include "ResilientBurst.h"
+
 #include <android-base/logging.h>
 #include <android-base/thread_annotations.h>
 #include <nnapi/IPreparedModel.h>
@@ -124,8 +127,35 @@
     return protect(*this, fn);
 }
 
+nn::GeneralResult<nn::SharedBurst> ResilientPreparedModel::configureExecutionBurst() const {
+#if 0
+    auto self = shared_from_this();
+    ResilientBurst::Factory makeBurst =
+            [preparedModel = std::move(self)]() -> nn::GeneralResult<nn::SharedBurst> {
+        return preparedModel->configureExecutionBurst();
+    };
+    return ResilientBurst::create(std::move(makeBurst));
+#else
+    return configureExecutionBurstInternal();
+#endif
+}
+
 std::any ResilientPreparedModel::getUnderlyingResource() const {
     return getPreparedModel()->getUnderlyingResource();
 }
 
+bool ResilientPreparedModel::isValidInternal() const {
+    return true;
+}
+
+nn::GeneralResult<nn::SharedBurst> ResilientPreparedModel::configureExecutionBurstInternal() const {
+    if (!isValidInternal()) {
+        return std::make_shared<const InvalidBurst>();
+    }
+    const auto fn = [](const nn::IPreparedModel& preparedModel) {
+        return preparedModel.configureExecutionBurst();
+    };
+    return protect(*this, fn);
+}
+
 }  // namespace android::hardware::neuralnetworks::utils
diff --git a/neuralnetworks/utils/common/test/MockDevice.h b/neuralnetworks/utils/common/test/MockDevice.h
index 08cd5c5..5566968 100644
--- a/neuralnetworks/utils/common/test/MockDevice.h
+++ b/neuralnetworks/utils/common/test/MockDevice.h
@@ -29,6 +29,7 @@
     MOCK_METHOD(const std::string&, getVersionString, (), (const, override));
     MOCK_METHOD(Version, getFeatureLevel, (), (const, override));
     MOCK_METHOD(DeviceType, getType, (), (const, override));
+    MOCK_METHOD(bool, isUpdatable, (), (const, override));
     MOCK_METHOD(const std::vector<Extension>&, getSupportedExtensions, (), (const, override));
     MOCK_METHOD(const Capabilities&, getCapabilities, (), (const, override));
     MOCK_METHOD((std::pair<uint32_t, uint32_t>), getNumberOfCacheFilesNeeded, (),
diff --git a/neuralnetworks/utils/common/test/MockPreparedModel.h b/neuralnetworks/utils/common/test/MockPreparedModel.h
index 928508e..418af61 100644
--- a/neuralnetworks/utils/common/test/MockPreparedModel.h
+++ b/neuralnetworks/utils/common/test/MockPreparedModel.h
@@ -35,6 +35,7 @@
                  const OptionalDuration& loopTimeoutDuration,
                  const OptionalDuration& timeoutDurationAfterFence),
                 (const, override));
+    MOCK_METHOD(GeneralResult<SharedBurst>, configureExecutionBurst, (), (const, override));
     MOCK_METHOD(std::any, getUnderlyingResource, (), (const, override));
 };
 
diff --git a/oemlock/aidl/Android.bp b/oemlock/aidl/Android.bp
new file mode 100644
index 0000000..bfc99e7
--- /dev/null
+++ b/oemlock/aidl/Android.bp
@@ -0,0 +1,16 @@
+aidl_interface {
+    name: "android.hardware.oemlock",
+    vendor_available: true,
+    srcs: ["android/hardware/oemlock/*.aidl"],
+    stability: "vintf",
+    backend: {
+        java: {
+            platform_apis: true,
+        },
+        ndk: {
+            vndk: {
+                enabled: true,
+            },
+        },
+    },
+}
diff --git a/oemlock/aidl/aidl_api/android.hardware.oemlock/current/android/hardware/oemlock/IOemLock.aidl b/oemlock/aidl/aidl_api/android.hardware.oemlock/current/android/hardware/oemlock/IOemLock.aidl
new file mode 100644
index 0000000..e3c974d
--- /dev/null
+++ b/oemlock/aidl/aidl_api/android.hardware.oemlock/current/android/hardware/oemlock/IOemLock.aidl
@@ -0,0 +1,27 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.oemlock;
+@VintfStability
+interface IOemLock {
+  String getName();
+  boolean isOemUnlockAllowedByCarrier();
+  boolean isOemUnlockAllowedByDevice();
+  android.hardware.oemlock.OemLockSecureStatus setOemUnlockAllowedByCarrier(in boolean allowed, in byte[] signature);
+  void setOemUnlockAllowedByDevice(in boolean allowed);
+}
diff --git a/oemlock/aidl/aidl_api/android.hardware.oemlock/current/android/hardware/oemlock/OemLockSecureStatus.aidl b/oemlock/aidl/aidl_api/android.hardware.oemlock/current/android/hardware/oemlock/OemLockSecureStatus.aidl
new file mode 100644
index 0000000..9d1327d
--- /dev/null
+++ b/oemlock/aidl/aidl_api/android.hardware.oemlock/current/android/hardware/oemlock/OemLockSecureStatus.aidl
@@ -0,0 +1,25 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.oemlock;
+@Backing(type="int") @VintfStability
+enum OemLockSecureStatus {
+  OK = 0,
+  FAILED = 1,
+  INVALID_SIGNATURE = 2,
+}
diff --git a/oemlock/aidl/android/hardware/oemlock/IOemLock.aidl b/oemlock/aidl/android/hardware/oemlock/IOemLock.aidl
new file mode 100644
index 0000000..674ff85
--- /dev/null
+++ b/oemlock/aidl/android/hardware/oemlock/IOemLock.aidl
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.oemlock;
+
+import android.hardware.oemlock.OemLockSecureStatus;
+
+/*
+ * The OEM lock prevents the bootloader from allowing the device to be flashed.
+ *
+ * Both the carrier and the device itself have a say as to whether OEM unlock is
+ * allowed and both must agree that is allowed in order for unlock to be
+ * possible.
+ */
+@VintfStability
+interface IOemLock {
+    /**
+     * Returns a vendor specific identifier of the HAL.
+     *
+     * The name returned must not be interpreted by the framework but must be
+     * passed to vendor code which may use it to identify the security protocol
+     * used by setOemUnlockAllowedByCarrier. This allows the vendor to identify
+     * the protocol without having to maintain a device-to-protocol mapping.
+     *
+     * @return name of the implementation and STATUS_OK if get name successfully
+     */
+    String getName();
+
+    /**
+     * Returns whether OEM unlock is allowed by the carrier.
+     *
+     * @return the current state(allowed/not allowed) of the flag
+     * and STATUS_OK if the flag was successfully read.
+     */
+    boolean isOemUnlockAllowedByCarrier();
+
+    /**
+     * Returns whether OEM unlock ia allowed by the device.
+     *
+     * @return the current state(allowed/not allowed) of the flag
+     * and STATUS_OK if the flag was successfully read.
+     */
+    boolean isOemUnlockAllowedByDevice();
+
+    /**
+     * Updates whether OEM unlock is allowed by the carrier.
+     *
+     * The implementation may require a vendor defined signature to prove the
+     * validity of this request in order to harden its security.
+     *
+     * @param allowed is the new value of the flag.
+     * @param signature to prove validity of this request or empty if not
+     *        required.
+     * @return OK if the flag was successfully updated,
+     *         INVALID_SIGNATURE if a signature is required but the wrong one
+     *         was provided
+     *         FAILED if the update was otherwise unsuccessful.
+     */
+    OemLockSecureStatus setOemUnlockAllowedByCarrier(in boolean allowed, in byte[] signature);
+
+    /**
+     * Updates whether OEM unlock is allowed by the device.
+     *
+     * @param allowed the new value of the flag.
+     * @return STATUS_OK if the flag was successfully updated.
+     */
+    void setOemUnlockAllowedByDevice(in boolean allowed);
+}
diff --git a/oemlock/aidl/android/hardware/oemlock/OemLockSecureStatus.aidl b/oemlock/aidl/android/hardware/oemlock/OemLockSecureStatus.aidl
new file mode 100644
index 0000000..3c11377
--- /dev/null
+++ b/oemlock/aidl/android/hardware/oemlock/OemLockSecureStatus.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.oemlock;
+
+@VintfStability
+@Backing(type="int")
+enum OemLockSecureStatus {
+    /**
+     * The operation completed successfully.
+     */
+    OK,
+    /**
+     * The operation encountered a problem.
+     */
+    FAILED,
+    /**
+     * An invalid signature was provided so the operation was not performed.
+     */
+    INVALID_SIGNATURE,
+}
diff --git a/oemlock/aidl/default/Android.bp b/oemlock/aidl/default/Android.bp
new file mode 100644
index 0000000..b9872d7
--- /dev/null
+++ b/oemlock/aidl/default/Android.bp
@@ -0,0 +1,32 @@
+//
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_binary {
+    name: "android.hardware.oemlock-service.example",
+    relative_install_path: "hw",
+    init_rc: ["android.hardware.oemlock-service.example.rc"],
+    vintf_fragments: ["android.hardware.oemlock-service.example.xml"],
+    vendor: true,
+    srcs: [
+        "service.cpp",
+        "OemLock.cpp",
+    ],
+    shared_libs: [
+        "android.hardware.oemlock-ndk_platform",
+        "libbase",
+        "libbinder_ndk",
+    ],
+}
diff --git a/oemlock/aidl/default/OemLock.cpp b/oemlock/aidl/default/OemLock.cpp
new file mode 100644
index 0000000..646b532
--- /dev/null
+++ b/oemlock/aidl/default/OemLock.cpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "OemLock.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace oemlock {
+
+// Methods from ::android::hardware::oemlock::IOemLock follow.
+
+::ndk::ScopedAStatus OemLock::getName(std::string *out_name) {
+    (void)out_name;
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus OemLock::setOemUnlockAllowedByCarrier(bool in_allowed, const std::vector<uint8_t> &in_signature, OemLockSecureStatus *_aidl_return) {
+    (void)in_allowed;
+    (void)in_signature;
+    (void)_aidl_return;
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus OemLock::isOemUnlockAllowedByCarrier(bool *out_allowed) {
+    (void)out_allowed;
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus OemLock::setOemUnlockAllowedByDevice(bool in_allowed) {
+    (void)in_allowed;
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus OemLock::isOemUnlockAllowedByDevice(bool *out_allowed) {
+    (void)out_allowed;
+    return ::ndk::ScopedAStatus::ok();
+}
+
+} // namespace oemlock
+} // namespace hardware
+} // namespace android
+} // aidl
diff --git a/oemlock/aidl/default/OemLock.h b/oemlock/aidl/default/OemLock.h
new file mode 100644
index 0000000..b0df414
--- /dev/null
+++ b/oemlock/aidl/default/OemLock.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/oemlock/BnOemLock.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace oemlock {
+
+using ::aidl::android::hardware::oemlock::IOemLock;
+using ::aidl::android::hardware::oemlock::OemLockSecureStatus;
+
+struct OemLock : public BnOemLock {
+public:
+    OemLock() = default;
+
+    // Methods from ::android::hardware::oemlock::IOemLock follow.
+    ::ndk::ScopedAStatus getName(std::string* out_name) override;
+    ::ndk::ScopedAStatus isOemUnlockAllowedByCarrier(bool* out_allowed) override;
+    ::ndk::ScopedAStatus isOemUnlockAllowedByDevice(bool* out_allowed) override;
+    ::ndk::ScopedAStatus setOemUnlockAllowedByCarrier(bool in_allowed, const std::vector<uint8_t>& in_signature, OemLockSecureStatus* _aidl_return) override;
+    ::ndk::ScopedAStatus setOemUnlockAllowedByDevice(bool in_allowed) override;
+};
+
+} // namespace oemlock
+} // namespace hardware
+} // namespace android
+} // aidl
diff --git a/oemlock/aidl/default/android.hardware.oemlock-service.example.rc b/oemlock/aidl/default/android.hardware.oemlock-service.example.rc
new file mode 100644
index 0000000..57b79d3
--- /dev/null
+++ b/oemlock/aidl/default/android.hardware.oemlock-service.example.rc
@@ -0,0 +1,4 @@
+service vendor.oemlock_default /vendor/bin/hw/android.hardware.oemlock-service.example
+    class hal
+    user hsm
+    group hsm
diff --git a/oemlock/aidl/default/android.hardware.oemlock-service.example.xml b/oemlock/aidl/default/android.hardware.oemlock-service.example.xml
new file mode 100644
index 0000000..b9f137f
--- /dev/null
+++ b/oemlock/aidl/default/android.hardware.oemlock-service.example.xml
@@ -0,0 +1,9 @@
+<manifest version="1.0" type="device">
+    <hal format="aidl">
+        <name>android.hardware.oemlock</name>
+        <interface>
+            <name>IOemLock</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+</manifest>
diff --git a/oemlock/aidl/default/service.cpp b/oemlock/aidl/default/service.cpp
new file mode 100644
index 0000000..af828a0
--- /dev/null
+++ b/oemlock/aidl/default/service.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+#include "OemLock.h"
+
+using ::aidl::android::hardware::oemlock::OemLock;
+
+int main() {
+    ABinderProcess_setThreadPoolMaxThreadCount(0);
+    std::shared_ptr<OemLock> oemlock = ndk::SharedRefBase::make<OemLock>();
+
+    const std::string instance = std::string() + OemLock::descriptor + "/default";
+    binder_status_t status = AServiceManager_addService(oemlock->asBinder().get(), instance.c_str());
+    CHECK(status == STATUS_OK);
+
+    ABinderProcess_joinThreadPool();
+    return -1; // Should never be reached
+}
diff --git a/oemlock/aidl/vts/Android.bp b/oemlock/aidl/vts/Android.bp
new file mode 100644
index 0000000..a13dbe2
--- /dev/null
+++ b/oemlock/aidl/vts/Android.bp
@@ -0,0 +1,33 @@
+//
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_test {
+    name: "VtsHalOemLockTargetTest",
+    defaults: [
+        "VtsHalTargetTestDefaults",
+        "use_libaidlvintf_gtest_helper_static",
+    ],
+    srcs: ["VtsHalOemLockTargetTest.cpp"],
+    shared_libs: [
+        "libbinder_ndk",
+        "libbase",
+    ],
+    static_libs: ["android.hardware.oemlock-ndk_platform"],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
+}
diff --git a/oemlock/aidl/vts/VtsHalOemLockTargetTest.cpp b/oemlock/aidl/vts/VtsHalOemLockTargetTest.cpp
new file mode 100644
index 0000000..6bf6298
--- /dev/null
+++ b/oemlock/aidl/vts/VtsHalOemLockTargetTest.cpp
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+
+#include <aidl/android/hardware/oemlock/IOemLock.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+using ::aidl::android::hardware::oemlock::IOemLock;
+using ::aidl::android::hardware::oemlock::OemLockSecureStatus;
+
+using ndk::SpAIBinder;
+
+struct OemLockAidlTest : public ::testing::TestWithParam<std::string> {
+    virtual void SetUp() override {
+        oemlock = IOemLock::fromBinder(
+            SpAIBinder(AServiceManager_waitForService(GetParam().c_str())));
+        ASSERT_NE(oemlock, nullptr);
+    }
+
+    virtual void TearDown() override {}
+
+    std::shared_ptr<IOemLock> oemlock;
+};
+
+/*
+ * Check the name can be retrieved
+ */
+TEST_P(OemLockAidlTest, GetName) {
+    std::string name;
+
+    const auto ret = oemlock->getName(&name);
+
+    ASSERT_TRUE(ret.isOk());
+    // Any value acceptable
+};
+
+/*
+ * Check the unlock allowed by device state can be queried
+ */
+TEST_P(OemLockAidlTest, QueryUnlockAllowedByDevice) {
+    bool allowed;
+
+    const auto ret = oemlock->isOemUnlockAllowedByDevice(&allowed);
+
+    ASSERT_TRUE(ret.isOk());
+    // Any value acceptable
+}
+
+/*
+ * Check unlock allowed by device state can be toggled
+ */
+TEST_P(OemLockAidlTest, AllowedByDeviceCanBeToggled) {
+    bool allowed;
+
+    // Get the original state so it can be restored
+    const auto get_ret = oemlock->isOemUnlockAllowedByDevice(&allowed);
+    ASSERT_TRUE(get_ret.isOk());
+    const bool originallyAllowed = allowed;
+
+    // Toggle the state
+    const auto set_ret = oemlock->setOemUnlockAllowedByDevice(!originallyAllowed);
+    ASSERT_TRUE(set_ret.isOk());
+
+    const auto check_set_ret = oemlock->isOemUnlockAllowedByDevice(&allowed);
+    ASSERT_TRUE(check_set_ret.isOk());
+    ASSERT_EQ(allowed, !originallyAllowed);
+
+    // Restore the state
+    const auto restore_ret = oemlock->setOemUnlockAllowedByDevice(originallyAllowed);
+    ASSERT_TRUE(restore_ret.isOk());
+
+    const auto check_restore_ret = oemlock->isOemUnlockAllowedByDevice(&allowed);
+    ASSERT_TRUE(check_restore_ret.isOk());
+    ASSERT_EQ(allowed, originallyAllowed);
+}
+
+/*
+ * Check the unlock allowed by device state can be queried
+ */
+TEST_P(OemLockAidlTest, QueryUnlockAllowedByCarrier) {
+    bool allowed;
+
+    const auto ret = oemlock->isOemUnlockAllowedByCarrier(&allowed);
+
+    ASSERT_TRUE(ret.isOk());
+    // Any value acceptable
+}
+
+/*
+ * Attempt to check unlock allowed by carrier can be toggled
+ *
+ * The implementation may involve a signature which cannot be tested here. That
+ * is a valid implementation so the test will pass. If there is no signature
+ * required, the test will toggle the value.
+ */
+TEST_P(OemLockAidlTest, CarrierUnlock) {
+    const std::vector<uint8_t> noSignature = {};
+    bool allowed;
+    OemLockSecureStatus secure_status;
+
+    // Get the original state so it can be restored
+    const auto get_ret = oemlock->isOemUnlockAllowedByCarrier(&allowed);
+    ASSERT_TRUE(get_ret.isOk());
+    const bool originallyAllowed = allowed;
+
+    if (originallyAllowed) {
+       // Only applied to locked devices
+       return;
+    }
+
+    // Toggle the state
+    const auto set_ret = oemlock->setOemUnlockAllowedByCarrier(!originallyAllowed, noSignature, &secure_status);
+    ASSERT_TRUE(set_ret.isOk());
+    ASSERT_NE(secure_status, OemLockSecureStatus::FAILED);
+    const auto set_status = secure_status;
+
+    const auto check_set_ret = oemlock->isOemUnlockAllowedByCarrier(&allowed);
+    ASSERT_TRUE(check_set_ret.isOk());
+
+    if (set_status == OemLockSecureStatus::INVALID_SIGNATURE) {
+       // Signature is required so we cannot toggle the value in the test, but this is allowed
+       ASSERT_EQ(allowed, originallyAllowed);
+       return;
+    }
+
+    ASSERT_EQ(set_status, OemLockSecureStatus::OK);
+    ASSERT_EQ(allowed, !originallyAllowed);
+
+    // Restore the state
+    const auto restore_ret = oemlock->setOemUnlockAllowedByCarrier(originallyAllowed, noSignature, &secure_status);
+    ASSERT_TRUE(restore_ret.isOk());
+    ASSERT_EQ(secure_status, OemLockSecureStatus::OK);
+
+    const auto check_restore_ret = oemlock->isOemUnlockAllowedByCarrier(&allowed);
+    ASSERT_TRUE(check_restore_ret.isOk());
+    ASSERT_EQ(allowed, originallyAllowed);
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(OemLockAidlTest);
+INSTANTIATE_TEST_SUITE_P(
+        PerInstance, OemLockAidlTest,
+        testing::ValuesIn(android::getAidlHalInstanceNames(IOemLock::descriptor)),
+        android::PrintInstanceNameToString);
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    ABinderProcess_setThreadPoolMaxThreadCount(1);
+    ABinderProcess_startThreadPool();
+    return RUN_ALL_TESTS();
+}
diff --git a/radio/1.0/vts/functional/vts_test_util.h b/radio/1.0/vts/functional/vts_test_util.h
index 846148f..218e823 100644
--- a/radio/1.0/vts/functional/vts_test_util.h
+++ b/radio/1.0/vts/functional/vts_test_util.h
@@ -37,6 +37,10 @@
 
 static constexpr const char* FEATURE_TELEPHONY = "android.hardware.telephony";
 
+static constexpr const char* FEATURE_TELEPHONY_GSM = "android.hardware.telephony.gsm";
+
+static constexpr const char* FEATURE_TELEPHONY_CDMA = "android.hardware.telephony.cdma";
+
 /*
  * Generate random serial number for radio test
  */
diff --git a/radio/1.4/vts/functional/radio_hidl_hal_api.cpp b/radio/1.4/vts/functional/radio_hidl_hal_api.cpp
index 4dcf1f3..b0b984c 100644
--- a/radio/1.4/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.4/vts/functional/radio_hidl_hal_api.cpp
@@ -34,8 +34,9 @@
     if (!deviceSupportsFeature(FEATURE_VOICE_CALL)) {
         ALOGI("Skipping emergencyDial because voice call is not supported in device");
         return;
-    } else if (!deviceSupportsFeature(FEATURE_TELEPHONY)) {
-        ALOGI("Skipping emergencyDial because telephony radio is not supported in device");
+    } else if (!deviceSupportsFeature(FEATURE_TELEPHONY_GSM) &&
+               !deviceSupportsFeature(FEATURE_TELEPHONY_CDMA)) {
+        ALOGI("Skipping emergencyDial because gsm/cdma radio is not supported in device");
         return;
     } else {
         ALOGI("Running emergencyDial because voice call is supported in device");
@@ -89,8 +90,9 @@
     if (!deviceSupportsFeature(FEATURE_VOICE_CALL)) {
         ALOGI("Skipping emergencyDial because voice call is not supported in device");
         return;
-    } else if (!deviceSupportsFeature(FEATURE_TELEPHONY)) {
-        ALOGI("Skipping emergencyDial because telephony radio is not supported in device");
+    } else if (!deviceSupportsFeature(FEATURE_TELEPHONY_GSM) &&
+               !deviceSupportsFeature(FEATURE_TELEPHONY_CDMA)) {
+        ALOGI("Skipping emergencyDial because gsm/cdma radio is not supported in device");
         return;
     } else {
         ALOGI("Running emergencyDial because voice call is supported in device");
@@ -144,8 +146,9 @@
     if (!deviceSupportsFeature(FEATURE_VOICE_CALL)) {
         ALOGI("Skipping emergencyDial because voice call is not supported in device");
         return;
-    } else if (!deviceSupportsFeature(FEATURE_TELEPHONY)) {
-        ALOGI("Skipping emergencyDial because telephony radio is not supported in device");
+    } else if (!deviceSupportsFeature(FEATURE_TELEPHONY_GSM) &&
+               !deviceSupportsFeature(FEATURE_TELEPHONY_CDMA)) {
+        ALOGI("Skipping emergencyDial because gsm/cdma radio is not supported in device");
         return;
     } else {
         ALOGI("Running emergencyDial because voice call is supported in device");
diff --git a/radio/1.6/IRadioIndication.hal b/radio/1.6/IRadioIndication.hal
index 1b56d40..a53d7c1 100644
--- a/radio/1.6/IRadioIndication.hal
+++ b/radio/1.6/IRadioIndication.hal
@@ -23,6 +23,7 @@
 import @1.6::NetworkScanResult;
 import @1.6::SignalStrength;
 import @1.6::SetupDataCallResult;
+import @1.6::PhysicalChannelConfig;
 
 /**
  * Interface declaring unsolicited radio indications.
@@ -101,4 +102,15 @@
      * CellInfo.
      */
     oneway networkScanResult_1_6(RadioIndicationType type, NetworkScanResult result);
+
+    /**
+     * Indicates physical channel configurations.
+     *
+     * An empty configs list indicates that the radio is in idle mode.
+     *
+     * @param type Type of radio indication
+     * @param configs Vector of PhysicalChannelConfigs
+     */
+    oneway currentPhysicalChannelConfigs_1_6(RadioIndicationType type,
+            vec<PhysicalChannelConfig> configs);
 };
diff --git a/radio/1.6/types.hal b/radio/1.6/types.hal
index 550e079..d475ed3 100644
--- a/radio/1.6/types.hal
+++ b/radio/1.6/types.hal
@@ -23,7 +23,10 @@
 import @1.0::RadioError;
 import @1.0::RadioResponseType;
 import @1.0::RegState;
+import @1.1::EutranBands;
+import @1.1::GeranBands;
 import @1.1::ScanStatus;
+import @1.1::UtranBands;
 import @1.2::Call;
 import @1.2::CellInfoCdma;
 import @1.2::CellConnectionStatus;
@@ -41,6 +44,7 @@
 import @1.5::CellInfoWcdma;
 import @1.5::CellInfoTdscdma;
 import @1.5::LinkAddress;
+import @1.5::NgranBands;
 import @1.5::RegStateResult.AccessTechnologySpecificInfo.Cdma2000RegistrationInfo;
 import @1.5::RegStateResult.AccessTechnologySpecificInfo.EutranRegistrationInfo;
 import @1.5::RegistrationFailCause;
@@ -281,7 +285,7 @@
      * suggestion. 0 indicates retry should be performed immediately. 0x7fffffffffffffff indicates
      * the device should not retry data setup anymore.
      */
-    uint64_t suggestedRetryTime;
+    int64_t suggestedRetryTime;
 
     /** Context ID, uniquely identifies this data connection. */
     int32_t cid;
@@ -347,7 +351,7 @@
 
     /**
      * The allocated pdu session id for this data call.
-     * A value of -1 means no pdu session id was attached to this call.
+     * A value of 0 means no pdu session id was attached to this call.
      *
      * Reference: 3GPP TS 24.007 section 11.2.3.1b
      */
@@ -818,3 +822,70 @@
      */
     SLICE_REJECTED = 0x8CC,
 };
+
+struct PhysicalChannelConfig {
+    /** Connection status for cell. Valid values are PRIMARY_SERVING and SECONDARY_SERVING */
+    CellConnectionStatus status;
+
+    /** The radio technology for this physical channel */
+    RadioTechnology rat;
+
+    /** Downlink Absolute Radio Frequency Channel Number */
+    int32_t downlinkChannelNumber;
+
+    /** Uplink Absolute Radio Frequency Channel Number */
+    int32_t uplinkChannelNumber;
+
+    /** Downlink cell bandwidth, in kHz */
+    int32_t cellBandwidthDownlink;
+
+    /** Uplink cell bandwidth, in kHz */
+    int32_t cellBandwidthUplink;
+
+    /**
+     * A list of data calls mapped to this physical channel. The context id must match the cid of
+     * @1.5::SetupDataCallResult. An empty list means the physical channel has no data call mapped
+     * to it.
+     */
+    vec<int32_t> contextIds;
+
+    /**
+     * The physical cell identifier for this cell.
+     *
+     * In UTRAN, this value is primary scrambling code. The range is [0, 511].
+     * Reference: 3GPP TS 25.213 section 5.2.2.
+     *
+     * In EUTRAN, this value is physical layer cell identity. The range is [0, 503].
+     * Reference: 3GPP TS 36.211 section 6.11.
+     *
+     * In 5G RAN, this value is physical layer cell identity. The range is [0, 1007].
+     * Reference: 3GPP TS 38.211 section 7.4.2.1.
+     */
+    uint32_t physicalCellId;
+
+    /**
+     * The frequency band to scan.
+     */
+    safe_union Band {
+        /** Valid only if radioAccessNetwork = GERAN. */
+        GeranBands geranBand;
+        /** Valid only if radioAccessNetwork = UTRAN. */
+        UtranBands utranBand;
+        /** Valid only if radioAccessNetwork = EUTRAN. */
+        EutranBands eutranBand;
+        /** Valid only if radioAccessNetwork = NGRAN. */
+        NgranBands ngranBand;
+    } band;
+};
+
+/**
+ * Extended from @1.5 NgranBands
+ * IRadio 1.6 supports NGRAN bands up to V16.5.0
+ */
+enum NgranBands  : @1.5::NgranBands {
+    /** 3GPP TS 38.101-1, Table 5.2-1: FR1 bands */
+    BAND_26 = 26,
+    BAND_46 = 46,
+    BAND_53 = 53,
+    BAND_96 = 96,
+};
diff --git a/radio/1.6/vts/functional/radio_hidl_hal_utils_v1_6.h b/radio/1.6/vts/functional/radio_hidl_hal_utils_v1_6.h
index fbcd7a9..5fcfa3b 100644
--- a/radio/1.6/vts/functional/radio_hidl_hal_utils_v1_6.h
+++ b/radio/1.6/vts/functional/radio_hidl_hal_utils_v1_6.h
@@ -857,6 +857,11 @@
             const ::android::hardware::hidl_vec<::android::hardware::radio::V1_6::CellInfo>&
                     records);
 
+    Return<void> currentPhysicalChannelConfigs_1_6(
+            RadioIndicationType type,
+            const ::android::hardware::hidl_vec<
+                    ::android::hardware::radio::V1_6::PhysicalChannelConfig>& configs);
+
     /* 1.5 Api */
     Return<void> uiccApplicationsEnablementChanged(RadioIndicationType type, bool enabled);
 
diff --git a/radio/1.6/vts/functional/radio_indication.cpp b/radio/1.6/vts/functional/radio_indication.cpp
index bfc54c0..e7a9680 100644
--- a/radio/1.6/vts/functional/radio_indication.cpp
+++ b/radio/1.6/vts/functional/radio_indication.cpp
@@ -30,6 +30,13 @@
     return Void();
 }
 
+Return<void> RadioIndication_v1_6::currentPhysicalChannelConfigs_1_6(
+        RadioIndicationType /*type*/,
+        const ::android::hardware::hidl_vec<
+                ::android::hardware::radio::V1_6::PhysicalChannelConfig>& /*configs*/) {
+    return Void();
+}
+
 /* 1.5 Apis */
 Return<void> RadioIndication_v1_6::uiccApplicationsEnablementChanged(RadioIndicationType /*type*/,
                                                                      bool /*enabled*/) {
diff --git a/radio/config/1.3/types.hal b/radio/config/1.3/types.hal
index bedb709..ba964bf 100644
--- a/radio/config/1.3/types.hal
+++ b/radio/config/1.3/types.hal
@@ -19,4 +19,10 @@
 /**
  * Contains the device capabilities with respect to the Radio HAL.
  */
-struct HalDeviceCapabilities {};
+struct HalDeviceCapabilities {
+  /**
+   * True indicates that the modem is missing features within the current
+   * version of the Radio HAL.
+   */
+  bool modemReducedFeatureSet1;
+};
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 46e0ae0..a6c3e65 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
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
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 ed96485..84395af 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
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
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 dddc9d8..e914823 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
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/ByteArray.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/ByteArray.aidl
index 3d18a26..cef8eca 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/ByteArray.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/ByteArray.aidl
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
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 9e0f8dc..2277831 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
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
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 8fc4d42..2e583ce 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
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
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 7c3f2f3..b372822 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
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
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 8694b32..aa8c071 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
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
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 9ea24f5..0d43d8d 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
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
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 aef5ee0..9ab00c1 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
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
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 3d08cfe..07c2844 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
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
@@ -21,9 +22,9 @@
   android.hardware.security.keymint.KeyMintHardwareInfo getHardwareInfo();
   android.hardware.security.keymint.VerificationToken verifyAuthorization(in long challenge, in android.hardware.security.keymint.HardwareAuthToken token);
   void addRngEntropy(in byte[] data);
-  void generateKey(in android.hardware.security.keymint.KeyParameter[] keyParams, out android.hardware.security.keymint.ByteArray generatedKeyBlob, out android.hardware.security.keymint.KeyCharacteristics generatedKeyCharacteristics, out android.hardware.security.keymint.Certificate[] outCertChain);
-  void importKey(in android.hardware.security.keymint.KeyParameter[] inKeyParams, in android.hardware.security.keymint.KeyFormat inKeyFormat, in byte[] inKeyData, out android.hardware.security.keymint.ByteArray outImportedKeyBlob, out android.hardware.security.keymint.KeyCharacteristics outImportedKeyCharacteristics, out android.hardware.security.keymint.Certificate[] outCertChain);
-  void importWrappedKey(in byte[] inWrappedKeyData, in byte[] inWrappingKeyBlob, in byte[] inMaskingKey, in android.hardware.security.keymint.KeyParameter[] inUnwrappingParams, in long inPasswordSid, in long inBiometricSid, out android.hardware.security.keymint.ByteArray outImportedKeyBlob, out android.hardware.security.keymint.KeyCharacteristics outImportedKeyCharacteristics);
+  android.hardware.security.keymint.KeyCreationResult generateKey(in android.hardware.security.keymint.KeyParameter[] keyParams);
+  android.hardware.security.keymint.KeyCreationResult importKey(in android.hardware.security.keymint.KeyParameter[] keyParams, in android.hardware.security.keymint.KeyFormat keyFormat, in byte[] keyData);
+  android.hardware.security.keymint.KeyCreationResult importWrappedKey(in byte[] wrappedKeyData, in byte[] wrappingKeyBlob, in byte[] maskingKey, in android.hardware.security.keymint.KeyParameter[] unwrappingParams, in long passwordSid, in long biometricSid);
   byte[] upgradeKey(in byte[] inKeyBlobToUpgrade, in android.hardware.security.keymint.KeyParameter[] inUpgradeParams);
   void deleteKey(in byte[] inKeyBlob);
   void deleteAllKeys();
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 8e3b0fc..08aa00a 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
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
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 fb4214c..49ea8af 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
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
@@ -18,6 +19,6 @@
 package android.hardware.security.keymint;
 @VintfStability
 parcelable KeyCharacteristics {
-  android.hardware.security.keymint.KeyParameter[] softwareEnforced;
-  android.hardware.security.keymint.KeyParameter[] hardwareEnforced;
+  android.hardware.security.keymint.SecurityLevel securityLevel;
+  android.hardware.security.keymint.KeyParameter[] authorizations;
 }
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
new file mode 100644
index 0000000..4b9ac79
--- /dev/null
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyCreationResult.aidl
@@ -0,0 +1,25 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.security.keymint;
+@VintfStability
+parcelable KeyCreationResult {
+  byte[] keyBlob;
+  android.hardware.security.keymint.KeyCharacteristics[] keyCharacteristics;
+  android.hardware.security.keymint.Certificate[] certificateChain;
+}
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 f701c80..4eb5a78 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
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
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 5e9f7ae..0390ec9 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
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
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 9728bf9..e84cf74 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
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
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 4985768..6829a2b 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
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyParameterArray.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyParameterArray.aidl
index 2c3b768..882ca89 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyParameterArray.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyParameterArray.aidl
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
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 ecf20ad..6c11a92 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
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
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 a6fd8c3..ff8d85a 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
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
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 2ecfa1e..6c61312 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
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
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 601693f..c4812ed 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
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
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 814405c..ce12fed 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
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
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 bb2766c..41c8832 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
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Timestamp.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Timestamp.aidl
index 4d5b659..963e66e 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Timestamp.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Timestamp.aidl
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/VerificationToken.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/VerificationToken.aidl
index 5c76816..7dc556c 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/VerificationToken.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/VerificationToken.aidl
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/security/keymint/aidl/android/hardware/security/keymint/Certificate.aidl b/security/keymint/aidl/android/hardware/security/keymint/Certificate.aidl
index a953859..0e5d898 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/Certificate.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/Certificate.aidl
@@ -17,9 +17,8 @@
 package android.hardware.security.keymint;
 
 /**
- * This encodes the IKeyMintDevice attestation generated certificate.
+ * This encodes an IKeyMintDevice certificate, generated for a KeyMint asymmetric public key.
  */
-
 @VintfStability
 parcelable Certificate {
     /**
diff --git a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
index 4944acb..820e135 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
@@ -18,10 +18,9 @@
 
 import android.hardware.security.keymint.BeginResult;
 import android.hardware.security.keymint.ByteArray;
-import android.hardware.security.keymint.Certificate;
 import android.hardware.security.keymint.HardwareAuthToken;
 import android.hardware.security.keymint.IKeyMintOperation;
-import android.hardware.security.keymint.KeyCharacteristics;
+import android.hardware.security.keymint.KeyCreationResult;
 import android.hardware.security.keymint.KeyFormat;
 import android.hardware.security.keymint.KeyParameter;
 import android.hardware.security.keymint.KeyMintHardwareInfo;
@@ -126,16 +125,22 @@
  * attacker can use them at will (though they're more secure than keys which can be
  * exfiltrated).  Therefore, IKeyMintDevice must enforce access controls.
  *
- * Access controls are defined as an "authorization list" of tag/value pairs.  Authorization tags
- * are 32-bit integers from the Tag enum, and the values are a variety of types, defined in the
- * TagType enum.  Some tags may be repeated to specify multiple values.  Whether a tag may be
- * repeated is specified in the documentation for the tag and in the TagType.  When a key is
- * created or imported, the caller specifies an authorization list.  The IKeyMintDevice must divide
- * the caller-provided authorizations into two lists, those it enforces in tee secure zone and
- * those enforced in the strongBox hardware.  These two lists are returned as the "teeEnforced"
- * and "strongboxEnforced" elements of the KeyCharacteristics struct. Note that software enforced
- * authorization list entries are not returned because they are not enforced by keymint.  The
- * IKeyMintDevice must also add the following authorizations to the appropriate list:
+ * Access controls are defined as "authorization lists" of tag/value pairs.  Authorization tags are
+ * 32-bit integers from the Tag enum, and the values are a variety of types, defined in the TagType
+ * enum.  Some tags may be repeated to specify multiple values.  Whether a tag may be repeated is
+ * specified in the documentation for the tag and in the TagType.  When a key is created or
+ * imported, the caller specifies a `key_description` authorization list.  The IKeyMintDevice must
+ * determine which tags it can and cannot enforce, and at what SecurityLevel, and return an array of
+ * `KeyCharacteristics` structures that contains everything it will enforce, associated with the
+ * appropriate security level, which is one of SOFTWARE, TRUSTED_ENVIRONMENT and STRONGBOX.
+ * Typically, implementations will only return a single KeyCharacteristics structure, because
+ * everything they enforce is enforced at the same security level.  There may be cases, however, for
+ * which multiple security levels are relevant. One example is that of a StrongBox IKeyMintDevice
+ * that relies on a TEE to enforce biometric user authentication.  In that case, the generate/import
+ * methods must return two KeyCharacteristics structs, one with SecurityLevel::TRUSTED_ENVIRONMENT
+ * and the biometric authentication-related tags, and another with SecurityLevel::STRONGBOX and
+ * everything else.  The IKeyMintDevice must also add the following authorizations to the
+ * appropriate list:
  *
  * o    Tag::OS_VERSION
  * o    Tag::OS_PATCHLEVEL
@@ -148,26 +153,27 @@
  * The caller must always provide the current date time in the keyParameter CREATION_DATETIME
  * tags.
  *
- * All authorization tags and their values, both teeEnforced and strongboxEnforced, including
- * unknown tags, must be cryptographically bound to the private/secret key material such that any
- * modification of the portion of the key blob that contains the authorization list makes it
- * impossible for the secure environment to obtain the private/secret key material.  The
- * recommended approach to meet this requirement is to use the full set of authorization tags
- * associated with a key as input to a secure key derivation function used to derive a key that
- * is used to encrypt the private/secret key material.
+ * All authorization tags and their values enforced by an IKeyMintDevice must be cryptographically
+ * bound to the private/secret key material such that any modification of the portion of the key
+ * blob that contains the authorization list makes it impossible for the secure environment to
+ * obtain the private/secret key material.  The recommended approach to meet this requirement is to
+ * use the full set of authorization tags associated with a key as input to a secure key derivation
+ * function used to derive a key (the KEK) that is used to encrypt the private/secret key material.
+ * Note that it is NOT acceptable to use a static KEK to encrypt the private/secret key material
+ * with an AEAD cipher mode, using the enforced authorization tags as AAD.  This is because
+ * Tag::APPLICATION_DATA must not be included in the authorization tags stored in the key blob, but
+ * must be provided by the caller for every use.  Assuming the Tag::APPLICATION_DATA value has
+ * sufficient entropy, this provides a cryptographic guarantee that an attacker cannot use a key
+ * without knowing the Tag::APPLICATION_DATA value, even if they compromise the IKeyMintDevice.
  *
- * IKeyMintDevice implementations ignore any tags they cannot enforce and do not return them
- * in KeyCharacteristics.  For example, Tag::ORIGINATION_EXPIRE_DATETIME provides the date and
- * time after which a key may not be used to encrypt or sign new messages.  Unless the
- * IKeyMintDevice has access to a secure source of current date/time information, it is not
- * possible for the IKeyMintDevice to enforce this tag.  An IKeyMintDevice implementation will
- * not rely on the non-secure world's notion of time, because it could be controlled by an
- * attacker. Similarly, it cannot rely on GPSr time, even if it has exclusive control of the
- * GPSr, because that might be spoofed by attacker RF signals.
- *
- * IKeyMintDevices do not use or enforce any tags they place in the softwareEnforced
- * list.  The IKeyMintDevice caller must enforce them, and it is unnecessary to enforce them
- * twice.
+ * IKeyMintDevice implementations must ignore any tags they cannot enforce and must not return them
+ * in KeyCharacteristics.  For example, Tag::ORIGINATION_EXPIRE_DATETIME provides the date and time
+ * after which a key may not be used to encrypt or sign new messages.  Unless the IKeyMintDevice has
+ * access to a secure source of current date/time information, it is not possible for the
+ * IKeyMintDevice to enforce this tag.  An IKeyMintDevice implementation will not rely on the
+ * non-secure world's notion of time, because it could be controlled by an attacker. Similarly, it
+ * cannot rely on GPSr time, even if it has exclusive control of the GPSr, because that might be
+ * spoofed by attacker RF signals.
  *
  * Some tags must be enforced by the IKeyMintDevice.  See the detailed documentation on each Tag
  * in Tag.aidl.
@@ -337,38 +343,9 @@
      *        provided in params.  See above for detailed specifications of which tags are required
      *        for which types of keys.
      *
-     * @return generatedKeyBlob Opaque descriptor of the generated key.  The recommended
-     *         implementation strategy is to include an encrypted copy of the key material, wrapped
-     *         in a key unavailable outside secure hardware.
-     *
-     * @return generatedKeyCharacteristics Description of the generated key, divided into two sets:
-     *         hardware-enforced and software-enforced.  The description here applies equally
-     *         to the key characteristics lists returned by generateKey, importKey and
-     *         importWrappedKey.  The characteristics returned by this parameter completely
-     *         describe the type and usage of the specified key.
-     *
-     *         The rule that IKeyMintDevice implementations must use for deciding whether a
-     *         given tag belongs in the hardware-enforced or software-enforced list is that if
-     *         the meaning of the tag is fully assured by secure hardware, it is hardware
-     *         enforced.  Otherwise, it's software enforced.
-     *
-     * @return outCertChain If the key is an asymmetric key, and proper keyparameters for
-     *         attestation (such as challenge) is provided, then this parameter will return the
-     *         attestation certificate.  If the signing of the attestation certificate is from a
-     *         factory key, additional certificates back to the root attestation certificate will
-     *         also be provided. Clients will need to check root certificate against a known-good
-     *         value. The certificates must be DER-encoded.  Caller needs to provide
-     *         CREATION_DATETIME as one of the attestation parameters, otherwise the attestation
-     *         certificate will not contain the creation datetime.  The first certificate in the
-     *         vector is the attestation for the generated key itself, the next certificate is
-     *         the key that signs the first certificate, and so forth.  The last certificate in
-     *         the chain is the root certificate.  If the key is a symmetric key, then no
-     *         certificate will be returned and this variable will return empty. TODO: change
-     *         certificate return to a single certificate and make it nullable b/163604282.
+     * @return The result of key creation.  See KeyCreationResult.aidl.
      */
-    void generateKey(in KeyParameter[] keyParams, out ByteArray generatedKeyBlob,
-                     out KeyCharacteristics generatedKeyCharacteristics,
-                     out Certificate[] outCertChain);
+    KeyCreationResult generateKey(in KeyParameter[] keyParams);
 
     /**
      * Imports key material into an IKeyMintDevice.  Key definition parameters and return values
@@ -396,29 +373,10 @@
      *
      * @param inKeyData The key material to import, in the format specified in keyFormat.
      *
-     * @return outImportedKeyBlob descriptor of the imported key.  The format of the keyblob will
-     *         be the google specified keyblob format.
-     *
-     * @return outImportedKeyCharacteristics Description of the generated key.  See the
-     *         keyCharacteristics description in generateKey.
-     *
-     * @return outCertChain If the key is an asymmetric key, and proper keyparameters for
-     *         attestation (such as challenge) is provided, then this parameter will return the
-     *         attestation certificate.  If the signing of the attestation certificate is from a
-     *         factory key, additional certificates back to the root attestation certificate will
-     *         also be provided. Clients will need to check root certificate against a known-good
-     *         value. The certificates must be DER-encoded.  Caller needs to provide
-     *         CREATION_DATETIME as one of the attestation parameters, otherwise the attestation
-     *         certificate will not contain the creation datetime.  The first certificate in the
-     *         vector is the attestation for the generated key itself, the next certificate is
-     *         the key that signs the first certificate, and so forth.  The last certificate in
-     *         the chain is the root certificate.  If the key is a symmetric key, then no
-     *         certificate will be returned and this variable will return empty.
+     * @return The result of key creation.  See KeyCreationResult.aidl.
      */
-    void importKey(in KeyParameter[] inKeyParams, in KeyFormat inKeyFormat,
-                   in byte[] inKeyData, out ByteArray outImportedKeyBlob,
-                   out KeyCharacteristics outImportedKeyCharacteristics,
-                   out Certificate[] outCertChain);
+    KeyCreationResult importKey(in KeyParameter[] keyParams, in KeyFormat keyFormat,
+                                in byte[] keyData);
 
     /**
      * Securely imports a key, or key pair, returning a key blob and a description of the imported
@@ -474,45 +432,38 @@
      *     5. Perform the equivalent of calling importKey(keyParams, keyFormat, keyData), except
      *        that the origin tag should be set to SECURELY_IMPORTED.
      *
-     * @param inWrappingKeyBlob The opaque key descriptor returned by generateKey() or importKey().
+     * @param wrappingKeyBlob The opaque key descriptor returned by generateKey() or importKey().
      *        This key must have been created with Purpose::WRAP_KEY.
      *
-     * @param inMaskingKey The 32-byte value XOR'd with the transport key in the SecureWrappedKey
+     * @param maskingKey The 32-byte value XOR'd with the transport key in the SecureWrappedKey
      *        structure.
      *
-     * @param inUnwrappingParams must contain any parameters needed to perform the unwrapping
-     *        operation.  For example, if the wrapping key is an AES key the block and padding
-     *        modes must be specified in this argument.
+     * @param unwrappingParams must contain any parameters needed to perform the unwrapping
+     *        operation.  For example, if the wrapping key is an AES key the block and padding modes
+     *        must be specified in this argument.
      *
-     * @param inPasswordSid specifies the password secure ID (SID) of the user that owns the key
-     *        being installed.  If the authorization list in wrappedKeyData contains a
-     *        Tag::USER_SECURE_IDwith a value that has the HardwareAuthenticatorType::PASSWORD
-     *        bit set, the constructed key must be bound to the SID value provided by this
-     *        argument.  If the wrappedKeyData does not contain such a tag and value, this argument
-     *        must be ignored.
+     * @param passwordSid specifies the password secure ID (SID) of the user that owns the key being
+     *        installed.  If the authorization list in wrappedKeyData contains a
+     *        Tag::USER_SECURE_IDwith a value that has the HardwareAuthenticatorType::PASSWORD bit
+     *        set, the constructed key must be bound to the SID value provided by this argument.  If
+     *        the wrappedKeyData does not contain such a tag and value, this argument must be
+     *        ignored.
      *
-     * @param inBiometricSid specifies the biometric secure ID (SID) of the user that owns the key
+     * @param biometricSid specifies the biometric secure ID (SID) of the user that owns the key
      *        being installed.  If the authorization list in wrappedKeyData contains a
      *        Tag::USER_SECURE_ID with a value that has the HardwareAuthenticatorType::FINGERPRINT
      *        bit set, the constructed key must be bound to the SID value provided by this argument.
      *        If the wrappedKeyData does not contain such a tag and value, this argument must be
      *        ignored.
      *
-     * @return outImportedKeyBlob Opaque descriptor of the imported key.  It is recommended that
-     *         the keyBlob contain a copy of the key material, wrapped in a key unavailable outside
-     *         secure hardware.
-     *
-     * @return outImportedKeyCharacteristics Description of the generated key.  See the description
-     *         of keyCharacteristics parameter in generateKey.
+     * @return The result of key creation.  See KeyCreationResult.aidl.
      */
-    void importWrappedKey(in byte[] inWrappedKeyData,
-                          in byte[] inWrappingKeyBlob,
-                          in byte[] inMaskingKey,
-                          in KeyParameter[] inUnwrappingParams,
-                          in long inPasswordSid,
-                          in long inBiometricSid,
-                          out ByteArray outImportedKeyBlob,
-                          out KeyCharacteristics outImportedKeyCharacteristics);
+     KeyCreationResult importWrappedKey(in byte[] wrappedKeyData,
+                                        in byte[] wrappingKeyBlob,
+                                        in byte[] maskingKey,
+                                        in KeyParameter[] unwrappingParams,
+                                        in long passwordSid,
+                                        in long biometricSid);
 
     /**
      * Upgrades an old key blob.  Keys can become "old" in two ways: IKeyMintDevice can be
diff --git a/security/keymint/aidl/android/hardware/security/keymint/KeyCharacteristics.aidl b/security/keymint/aidl/android/hardware/security/keymint/KeyCharacteristics.aidl
index 0801868..edd4d8f 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/KeyCharacteristics.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/KeyCharacteristics.aidl
@@ -17,25 +17,20 @@
 package android.hardware.security.keymint;
 
 import android.hardware.security.keymint.KeyParameter;
+import android.hardware.security.keymint.SecurityLevel;
 
 /**
- * KeyCharacteristics defines the attributes of a key, including cryptographic parameters, and usage
- * restrictions.  It consits of two vectors of KeyParameters, one for "softwareEnforced" attributes
- * and one for "hardwareEnforced" attributes.
+ * KeyCharacteristics defines the attributes of a key that are enforced by KeyMint, and the security
+ * level (see SecurityLevel.aidl) of that enforcement.
  *
- * KeyCharacteristics objects are returned by generateKey, importKey, importWrappedKey and
- * getKeyCharacteristics.  The IKeyMintDevice secure environment is responsible for allocating the
- * parameters, all of which are Tags with associated values, to the correct vector.  The
- * hardwareEnforced vector must contain only those attributes which are enforced by secure hardware.
- * All others should be in the softwareEnforced vector.  See the definitions of individual Tag enums
- * for specification of which must be hardware-enforced, which may be software-enforced and which
- * must never appear in KeyCharacteristics.
+ * The `generateKey` `importKey` and `importWrappedKey` methods each return an array of
+ * KeyCharacteristics, specifying the security levels of enforcement and the authorizations
+ * 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.
  */
 @VintfStability
 parcelable KeyCharacteristics {
-    /* TODO(seleneh) get rid of the software enforced in keymint.  replace hardware enforced with
-     * tee enforced and strongbox enforced.
-     */
-    KeyParameter[] softwareEnforced;
-    KeyParameter[] hardwareEnforced;
+    SecurityLevel securityLevel;
+    KeyParameter[] authorizations;
 }
diff --git a/security/keymint/aidl/android/hardware/security/keymint/KeyCreationResult.aidl b/security/keymint/aidl/android/hardware/security/keymint/KeyCreationResult.aidl
new file mode 100644
index 0000000..b149ac9
--- /dev/null
+++ b/security/keymint/aidl/android/hardware/security/keymint/KeyCreationResult.aidl
@@ -0,0 +1,62 @@
+/*
+ * 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.security.keymint;
+
+import android.hardware.security.keymint.Certificate;
+import android.hardware.security.keymint.KeyCharacteristics;
+
+/**
+ * This structure is returned when a new key is created with generateKey(), importKey() or
+ * importWrappedKey().
+ */
+@VintfStability
+parcelable KeyCreationResult {
+    /**
+     * `keyBlob` is an descriptor of the generated/imported key key.
+     */
+    byte[] keyBlob;
+
+    /**
+     * `keyCharacteristics` is a description of the generated key in the form of authorization lists
+     * associated with security levels.  The rules that IKeyMintDevice implementations must use for
+     * deciding whether a given tag from `keyParams` argument to the generation/import method should
+     * be returned in `keyCharacteristics` are:
+     *
+     * - If the IKeyMintDevice cannot fully enforce the semantics of the tag, it should be omitted.
+     * - If the semantics of the tag are fully enforced by the IKeyMintDevice, without any
+     *   assistance from components running at other security levels, it should be included in an
+     *   entry with the SecurityLevel of the IKeyMintDevice.
+     * - If the semantics of the tag are fully enforced, but with the assistance of components
+     *   running at another SecurityLevel, it should be included in an entry with the minimum
+     *   SecurityLevel of the involved components.  For example if a StrongBox IKeyMintDevice relies
+     *   on a TEE to validate biometric authentication, biometric authentication tags go in an entry
+     *   with SecurityLevel::TRUSTED_ENVIRONMENT.
+     */
+    KeyCharacteristics[] keyCharacteristics;
+
+    /**
+     * If the generated/imported key is an asymmetric key, `certificateChain` will contain a chain
+     * of one or more certificates.  If the key parameters provided to the generate/import method
+     * contains Tag::ATTESTATION_CHALLENGE the first certificate will contain an attestation
+     * extension, and will be signed by a factory-installed attestation key and followed by a chain
+     * of certificates leading to an authoritative root.  If there is no attestation challenge, only
+     * one certificate will be returned, and it will be self-signed or contain a fake signature,
+     * depending on whether the key has KeyPurpose::SIGN.  If the generated key is symmetric,
+     * certificateChain will be empty.
+     */
+    Certificate[] certificateChain;
+}
diff --git a/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl b/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl
index 9f41b4e..f92bf00 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl
@@ -512,10 +512,10 @@
 
     /**
      * Tag::APPLICATION_DATA.  When provided to generateKey or importKey, this tag specifies data
-     * that is necessary during all uses of the key.  In particular, calls to exportKey() and
-     * getKeyCharacteristics() must provide the same value to the appData parameter, and calls to
-     * begin must provide this tag and the same associated data as part of the inParams set.  If
-     * the correct data is not provided, the method must return ErrorCode::INVALID_KEY_BLOB.
+     * that is necessary during all uses of the key.  In particular, calls to begin() and
+     * exportKey() must provide the same value to the appData parameter, and calls to begin must
+     * provide this tag and the same associated data as part of the inParams set.  If the correct
+     * data is not provided, the method must return ErrorCode::INVALID_KEY_BLOB.
      *
      * The content of this tag msut be bound to the key cryptographically, meaning it must not be
      * possible for an adversary who has access to all of the secure world secrets but does not have
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
index 94bc199..93a216f 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
@@ -17,6 +17,7 @@
 #include "KeyMintAidlTestBase.h"
 
 #include <chrono>
+#include <unordered_set>
 #include <vector>
 
 #include <android-base/logging.h>
@@ -43,6 +44,34 @@
 
 namespace test {
 
+namespace {
+
+// Predicate for testing basic characteristics validity in generation or import.
+bool KeyCharacteristicsBasicallyValid(SecurityLevel secLevel,
+                                      const vector<KeyCharacteristics>& key_characteristics) {
+    if (key_characteristics.empty()) return false;
+
+    std::unordered_set<SecurityLevel> levels_seen;
+    for (auto& entry : key_characteristics) {
+        if (entry.authorizations.empty()) return false;
+
+        if (levels_seen.find(entry.securityLevel) != levels_seen.end()) return false;
+        levels_seen.insert(entry.securityLevel);
+
+        // Generally, we should only have one entry, at the same security level as the KM
+        // instance.  There is an exception: StrongBox KM can have some authorizations that are
+        // enforced by the TEE.
+        bool isExpectedSecurityLevel = secLevel == entry.securityLevel ||
+                                       (secLevel == SecurityLevel::STRONGBOX &&
+                                        entry.securityLevel == SecurityLevel::TRUSTED_ENVIRONMENT);
+
+        if (!isExpectedSecurityLevel) return false;
+    }
+    return true;
+}
+
+}  // namespace
+
 ErrorCode KeyMintAidlTestBase::GetReturnErrorCode(const Status& result) {
     if (result.isOk()) return ErrorCode::OK;
 
@@ -78,35 +107,30 @@
 }
 
 ErrorCode KeyMintAidlTestBase::GenerateKey(const AuthorizationSet& key_desc,
-                                           vector<uint8_t>* keyBlob, KeyCharacteristics* keyChar) {
-    EXPECT_NE(keyBlob, nullptr) << "Key blob pointer must not be null.  Test bug";
-    EXPECT_NE(keyChar, nullptr)
+                                           vector<uint8_t>* key_blob,
+                                           vector<KeyCharacteristics>* key_characteristics) {
+    EXPECT_NE(key_blob, nullptr) << "Key blob pointer must not be null.  Test bug";
+    EXPECT_NE(key_characteristics, nullptr)
             << "Previous characteristics not deleted before generating key.  Test bug.";
 
     // Aidl does not clear these output parameters if the function returns
     // error.  This is different from hal where output parameter is always
     // cleared due to hal returning void.  So now we need to do our own clearing
     // of the output variables prior to calling keyMint aidl libraries.
-    keyBlob->clear();
-    keyChar->softwareEnforced.clear();
-    keyChar->hardwareEnforced.clear();
-    certChain_.clear();
+    key_blob->clear();
+    key_characteristics->clear();
+    cert_chain_.clear();
 
-    Status result;
-    ByteArray blob;
+    KeyCreationResult creationResult;
+    Status result = keymint_->generateKey(key_desc.vector_data(), &creationResult);
 
-    result = keymint_->generateKey(key_desc.vector_data(), &blob, keyChar, &certChain_);
-
-    // On result, blob & characteristics should be empty.
     if (result.isOk()) {
-        if (SecLevel() != SecurityLevel::SOFTWARE) {
-            EXPECT_GT(keyChar->hardwareEnforced.size(), 0);
-        }
-        EXPECT_GT(keyChar->softwareEnforced.size(), 0);
-        // TODO(seleneh) in a later version where we return @nullable
-        // single Certificate, check non-null single certificate is always
-        // non-empty.
-        *keyBlob = blob.data;
+        EXPECT_PRED2(KeyCharacteristicsBasicallyValid, SecLevel(),
+                     creationResult.keyCharacteristics);
+        EXPECT_GT(creationResult.keyBlob.size(), 0);
+        *key_blob = std::move(creationResult.keyBlob);
+        *key_characteristics = std::move(creationResult.keyCharacteristics);
+        cert_chain_ = std::move(creationResult.certificateChain);
     }
 
     return GetReturnErrorCode(result);
@@ -118,25 +142,26 @@
 
 ErrorCode KeyMintAidlTestBase::ImportKey(const AuthorizationSet& key_desc, KeyFormat format,
                                          const string& key_material, vector<uint8_t>* key_blob,
-                                         KeyCharacteristics* key_characteristics) {
+                                         vector<KeyCharacteristics>* key_characteristics) {
     Status result;
 
-    certChain_.clear();
-    key_characteristics->softwareEnforced.clear();
-    key_characteristics->hardwareEnforced.clear();
+    cert_chain_.clear();
+    key_characteristics->clear();
     key_blob->clear();
 
-    ByteArray blob;
+    KeyCreationResult creationResult;
     result = keymint_->importKey(key_desc.vector_data(), format,
-                                 vector<uint8_t>(key_material.begin(), key_material.end()), &blob,
-                                 key_characteristics, &certChain_);
+                                 vector<uint8_t>(key_material.begin(), key_material.end()),
+                                 &creationResult);
 
     if (result.isOk()) {
-        if (SecLevel() != SecurityLevel::SOFTWARE) {
-            EXPECT_GT(key_characteristics->hardwareEnforced.size(), 0);
-        }
-        EXPECT_GT(key_characteristics->softwareEnforced.size(), 0);
-        *key_blob = blob.data;
+        EXPECT_PRED2(KeyCharacteristicsBasicallyValid, SecLevel(),
+                     creationResult.keyCharacteristics);
+        EXPECT_GT(creationResult.keyBlob.size(), 0);
+
+        *key_blob = std::move(creationResult.keyBlob);
+        *key_characteristics = std::move(creationResult.keyCharacteristics);
+        cert_chain_ = std::move(creationResult.certificateChain);
     }
 
     return GetReturnErrorCode(result);
@@ -151,25 +176,25 @@
                                                 const AuthorizationSet& wrapping_key_desc,
                                                 string masking_key,
                                                 const AuthorizationSet& unwrapping_params) {
-    Status result;
     EXPECT_EQ(ErrorCode::OK, ImportKey(wrapping_key_desc, KeyFormat::PKCS8, wrapping_key));
 
-    ByteArray outBlob;
-    key_characteristics_.softwareEnforced.clear();
-    key_characteristics_.hardwareEnforced.clear();
+    key_characteristics_.clear();
 
-    result = keymint_->importWrappedKey(vector<uint8_t>(wrapped_key.begin(), wrapped_key.end()),
-                                        key_blob_,
-                                        vector<uint8_t>(masking_key.begin(), masking_key.end()),
-                                        unwrapping_params.vector_data(), 0 /* passwordSid */,
-                                        0 /* biometricSid */, &outBlob, &key_characteristics_);
+    KeyCreationResult creationResult;
+    Status result = keymint_->importWrappedKey(
+            vector<uint8_t>(wrapped_key.begin(), wrapped_key.end()), key_blob_,
+            vector<uint8_t>(masking_key.begin(), masking_key.end()),
+            unwrapping_params.vector_data(), 0 /* passwordSid */, 0 /* biometricSid */,
+            &creationResult);
 
     if (result.isOk()) {
-        key_blob_ = outBlob.data;
-        if (SecLevel() != SecurityLevel::SOFTWARE) {
-            EXPECT_GT(key_characteristics_.hardwareEnforced.size(), 0);
-        }
-        EXPECT_GT(key_characteristics_.softwareEnforced.size(), 0);
+        EXPECT_PRED2(KeyCharacteristicsBasicallyValid, SecLevel(),
+                     creationResult.keyCharacteristics);
+        EXPECT_GT(creationResult.keyBlob.size(), 0);
+
+        key_blob_ = std::move(creationResult.keyBlob);
+        key_characteristics_ = std::move(creationResult.keyCharacteristics);
+        cert_chain_ = std::move(creationResult.certificateChain);
     }
 
     return GetReturnErrorCode(result);
@@ -754,6 +779,15 @@
     return {};
 }
 
+static const vector<KeyParameter> kEmptyAuthList{};
+
+const vector<KeyParameter>& KeyMintAidlTestBase::SecLevelAuthorizations(
+        const vector<KeyCharacteristics>& key_characteristics) {
+    auto found = std::find_if(key_characteristics.begin(), key_characteristics.end(),
+                              [this](auto& entry) { return entry.securityLevel == SecLevel(); });
+    return (found == key_characteristics.end()) ? kEmptyAuthList : found->authorizations;
+}
+
 }  // namespace test
 
 }  // namespace aidl::android::hardware::security::keymint
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
index f73c26d..f36c397 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
@@ -56,13 +56,13 @@
 
     ErrorCode GetReturnErrorCode(const Status& result);
     ErrorCode GenerateKey(const AuthorizationSet& key_desc, vector<uint8_t>* key_blob,
-                          KeyCharacteristics* key_characteristics);
+                          vector<KeyCharacteristics>* key_characteristics);
 
     ErrorCode GenerateKey(const AuthorizationSet& key_desc);
 
     ErrorCode ImportKey(const AuthorizationSet& key_desc, KeyFormat format,
                         const string& key_material, vector<uint8_t>* key_blob,
-                        KeyCharacteristics* key_characteristics);
+                        vector<KeyCharacteristics>* key_characteristics);
     ErrorCode ImportKey(const AuthorizationSet& key_desc, KeyFormat format,
                         const string& key_material);
 
@@ -147,8 +147,8 @@
 
     std::pair<ErrorCode, vector<uint8_t>> UpgradeKey(const vector<uint8_t>& key_blob);
 
-    bool IsSecure() { return securityLevel_ != SecurityLevel::SOFTWARE; }
-    SecurityLevel SecLevel() { return securityLevel_; }
+    bool IsSecure() const { return securityLevel_ != SecurityLevel::SOFTWARE; }
+    SecurityLevel SecLevel() const { return securityLevel_; }
 
     vector<uint32_t> ValidKeySizes(Algorithm algorithm);
     vector<uint32_t> InvalidKeySizes(Algorithm algorithm);
@@ -164,9 +164,15 @@
     }
 
     std::shared_ptr<IKeyMintOperation> op_;
-    vector<Certificate> certChain_;
+    vector<Certificate> cert_chain_;
     vector<uint8_t> key_blob_;
-    KeyCharacteristics key_characteristics_;
+    vector<KeyCharacteristics> key_characteristics_;
+
+    const vector<KeyParameter>& SecLevelAuthorizations(
+            const vector<KeyCharacteristics>& key_characteristics);
+    inline const vector<KeyParameter>& SecLevelAuthorizations() {
+        return SecLevelAuthorizations(key_characteristics_);
+    }
 
   private:
     std::shared_ptr<IKeyMintDevice> keymint_;
diff --git a/security/keymint/aidl/vts/functional/KeyMintTest.cpp b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
index eeb7491..bd36b8e 100644
--- a/security/keymint/aidl/vts/functional/KeyMintTest.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
@@ -56,18 +56,16 @@
 template <>
 struct std::equal_to<KeyCharacteristics> {
     bool operator()(const KeyCharacteristics& a, const KeyCharacteristics& b) const {
-        // This isn't very efficient. Oh, well.
-        AuthorizationSet a_sw(a.softwareEnforced);
-        AuthorizationSet b_sw(b.softwareEnforced);
-        AuthorizationSet a_tee(b.hardwareEnforced);
-        AuthorizationSet b_tee(b.hardwareEnforced);
+        if (a.securityLevel != b.securityLevel) return false;
 
-        a_sw.Sort();
-        b_sw.Sort();
-        a_tee.Sort();
-        b_tee.Sort();
+        // this isn't very efficient. Oh, well.
+        AuthorizationSet a_auths(a.authorizations);
+        AuthorizationSet b_auths(b.authorizations);
 
-        return ((a_sw == b_sw) && (a_tee == b_tee));
+        a_auths.Sort();
+        b_auths.Sort();
+
+        return a_auths == b_auths;
     }
 };
 
@@ -229,19 +227,20 @@
 
 class NewKeyGenerationTest : public KeyMintAidlTestBase {
   protected:
-    void CheckBaseParams(const KeyCharacteristics& keyCharacteristics) {
+    void CheckBaseParams(const vector<KeyCharacteristics>& keyCharacteristics) {
         // TODO(swillden): Distinguish which params should be in which auth list.
 
-        AuthorizationSet auths(keyCharacteristics.hardwareEnforced);
-        auths.push_back(AuthorizationSet(keyCharacteristics.softwareEnforced));
+        AuthorizationSet auths;
+        for (auto& entry : keyCharacteristics) {
+            auths.push_back(AuthorizationSet(entry.authorizations));
+        }
 
         EXPECT_TRUE(auths.Contains(TAG_ORIGIN, KeyOrigin::GENERATED));
         EXPECT_TRUE(auths.Contains(TAG_PURPOSE, KeyPurpose::SIGN));
         EXPECT_TRUE(auths.Contains(TAG_PURPOSE, KeyPurpose::VERIFY));
 
-        // Verify that App ID, App data and ROT are NOT included.
+        // Verify that App data and ROT are NOT included.
         EXPECT_FALSE(auths.Contains(TAG_ROOT_OF_TRUST));
-        EXPECT_FALSE(auths.Contains(TAG_APPLICATION_ID));
         EXPECT_FALSE(auths.Contains(TAG_APPLICATION_DATA));
 
         // Check that some unexpected tags/values are NOT present.
@@ -249,15 +248,13 @@
         EXPECT_FALSE(auths.Contains(TAG_PURPOSE, KeyPurpose::DECRYPT));
         EXPECT_FALSE(auths.Contains(TAG_AUTH_TIMEOUT, 301U));
 
-        // Now check that unspecified, defaulted tags are correct.
-        EXPECT_TRUE(auths.Contains(TAG_CREATION_DATETIME));
+        auto os_ver = auths.GetTagValue(TAG_OS_VERSION);
+        ASSERT_TRUE(os_ver);
+        EXPECT_EQ(*os_ver, os_version());
 
-        EXPECT_TRUE(auths.Contains(TAG_OS_VERSION, os_version()))
-                << "OS version is " << os_version() << " key reported "
-                << auths.GetTagValue(TAG_OS_VERSION)->get();
-        EXPECT_TRUE(auths.Contains(TAG_OS_PATCHLEVEL, os_patch_level()))
-                << "OS patch level is " << os_patch_level() << " key reported "
-                << auths.GetTagValue(TAG_OS_PATCHLEVEL)->get();
+        auto os_pl = auths.GetTagValue(TAG_OS_PATCHLEVEL);
+        ASSERT_TRUE(os_pl);
+        EXPECT_EQ(*os_pl, os_patch_level());
     }
 };
 
@@ -270,7 +267,7 @@
 TEST_P(NewKeyGenerationTest, Rsa) {
     for (auto key_size : ValidKeySizes(Algorithm::RSA)) {
         vector<uint8_t> key_blob;
-        KeyCharacteristics key_characteristics;
+        vector<KeyCharacteristics> key_characteristics;
         ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
                                                      .RsaSigningKey(key_size, 65537)
                                                      .Digest(Digest::NONE)
@@ -280,12 +277,7 @@
         ASSERT_GT(key_blob.size(), 0U);
         CheckBaseParams(key_characteristics);
 
-        AuthorizationSet crypto_params;
-        if (IsSecure()) {
-            crypto_params = key_characteristics.hardwareEnforced;
-        } else {
-            crypto_params = key_characteristics.softwareEnforced;
-        }
+        AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
 
         EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::RSA));
         EXPECT_TRUE(crypto_params.Contains(TAG_KEY_SIZE, key_size))
@@ -304,7 +296,7 @@
 TEST_P(NewKeyGenerationTest, NoInvalidRsaSizes) {
     for (auto key_size : InvalidKeySizes(Algorithm::RSA)) {
         vector<uint8_t> key_blob;
-        KeyCharacteristics key_characteristics;
+        vector<KeyCharacteristics> key_characteristics;
         ASSERT_EQ(ErrorCode::UNSUPPORTED_KEY_SIZE,
                   GenerateKey(AuthorizationSetBuilder()
                                       .RsaSigningKey(key_size, 65537)
@@ -337,7 +329,7 @@
 TEST_P(NewKeyGenerationTest, Ecdsa) {
     for (auto key_size : ValidKeySizes(Algorithm::EC)) {
         vector<uint8_t> key_blob;
-        KeyCharacteristics key_characteristics;
+        vector<KeyCharacteristics> key_characteristics;
         ASSERT_EQ(ErrorCode::OK,
                   GenerateKey(
                           AuthorizationSetBuilder().EcdsaSigningKey(key_size).Digest(Digest::NONE),
@@ -345,12 +337,7 @@
         ASSERT_GT(key_blob.size(), 0U);
         CheckBaseParams(key_characteristics);
 
-        AuthorizationSet crypto_params;
-        if (IsSecure()) {
-            crypto_params = key_characteristics.hardwareEnforced;
-        } else {
-            crypto_params = key_characteristics.softwareEnforced;
-        }
+        AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
 
         EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::EC));
         EXPECT_TRUE(crypto_params.Contains(TAG_KEY_SIZE, key_size))
@@ -383,7 +370,7 @@
 TEST_P(NewKeyGenerationTest, EcdsaInvalidSize) {
     for (auto key_size : InvalidKeySizes(Algorithm::EC)) {
         vector<uint8_t> key_blob;
-        KeyCharacteristics key_characteristics;
+        vector<KeyCharacteristics> key_characteristics;
         ASSERT_EQ(ErrorCode::UNSUPPORTED_KEY_SIZE,
                   GenerateKey(
                           AuthorizationSetBuilder().EcdsaSigningKey(key_size).Digest(Digest::NONE),
@@ -454,7 +441,7 @@
 TEST_P(NewKeyGenerationTest, Hmac) {
     for (auto digest : ValidDigests(false /* withNone */, true /* withMD5 */)) {
         vector<uint8_t> key_blob;
-        KeyCharacteristics key_characteristics;
+        vector<KeyCharacteristics> key_characteristics;
         constexpr size_t key_size = 128;
         ASSERT_EQ(ErrorCode::OK,
                   GenerateKey(
@@ -465,17 +452,10 @@
         ASSERT_GT(key_blob.size(), 0U);
         CheckBaseParams(key_characteristics);
 
-        AuthorizationSet hardwareEnforced = key_characteristics.hardwareEnforced;
-        AuthorizationSet softwareEnforced = key_characteristics.softwareEnforced;
-        if (IsSecure()) {
-            EXPECT_TRUE(hardwareEnforced.Contains(TAG_ALGORITHM, Algorithm::HMAC));
-            EXPECT_TRUE(hardwareEnforced.Contains(TAG_KEY_SIZE, key_size))
-                    << "Key size " << key_size << "missing";
-        } else {
-            EXPECT_TRUE(softwareEnforced.Contains(TAG_ALGORITHM, Algorithm::HMAC));
-            EXPECT_TRUE(softwareEnforced.Contains(TAG_KEY_SIZE, key_size))
-                    << "Key size " << key_size << "missing";
-        }
+        AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
+        EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::HMAC));
+        EXPECT_TRUE(crypto_params.Contains(TAG_KEY_SIZE, key_size))
+                << "Key size " << key_size << "missing";
 
         CheckedDeleteKey(&key_blob);
     }
@@ -600,7 +580,7 @@
 /*
  * SigningOperationsTest.RsaUseRequiresCorrectAppIdAppData
  *
- * Verifies that using an RSA key requires the correct app ID/data.
+ * Verifies that using an RSA key requires the correct app data.
  */
 TEST_P(SigningOperationsTest, RsaUseRequiresCorrectAppIdAppData) {
     ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
@@ -1412,7 +1392,7 @@
     string key_material = "HelloThisIsAKey";
 
     vector<uint8_t> signing_key, verification_key;
-    KeyCharacteristics signing_key_chars, verification_key_chars;
+    vector<KeyCharacteristics> signing_key_chars, verification_key_chars;
     EXPECT_EQ(ErrorCode::OK,
               ImportKey(AuthorizationSetBuilder()
                                 .Authorization(TAG_NO_AUTH_REQUIRED)
@@ -1466,28 +1446,22 @@
     template <TagType tag_type, Tag tag, typename ValueT>
     void CheckCryptoParam(TypedTag<tag_type, tag> ttag, ValueT expected) {
         SCOPED_TRACE("CheckCryptoParam");
-        if (IsSecure()) {
-            EXPECT_TRUE(contains(key_characteristics_.hardwareEnforced, ttag, expected))
-                    << "Tag " << tag << " with value " << expected << " not found";
-            EXPECT_FALSE(contains(key_characteristics_.softwareEnforced, ttag))
-                    << "Tag " << tag << " found";
-        } else {
-            EXPECT_TRUE(contains(key_characteristics_.softwareEnforced, ttag, expected))
-                    << "Tag " << tag << " with value " << expected << " not found";
-            EXPECT_FALSE(contains(key_characteristics_.hardwareEnforced, ttag))
-                    << "Tag " << tag << " found";
+        for (auto& entry : key_characteristics_) {
+            if (entry.securityLevel == SecLevel()) {
+                EXPECT_TRUE(contains(entry.authorizations, ttag, expected))
+                        << "Tag " << tag << " with value " << expected
+                        << " not found at security level" << entry.securityLevel;
+            } else {
+                EXPECT_FALSE(contains(entry.authorizations, ttag, expected))
+                        << "Tag " << tag << " found at security level " << entry.securityLevel;
+            }
         }
     }
 
     void CheckOrigin() {
         SCOPED_TRACE("CheckOrigin");
-        if (IsSecure()) {
-            EXPECT_TRUE(contains(key_characteristics_.hardwareEnforced, TAG_ORIGIN,
-                                 KeyOrigin::IMPORTED));
-        } else {
-            EXPECT_TRUE(contains(key_characteristics_.softwareEnforced, TAG_ORIGIN,
-                                 KeyOrigin::IMPORTED));
-        }
+        // Origin isn't a crypto param, but it always lives with them.
+        return CheckCryptoParam(TAG_ORIGIN, KeyOrigin::IMPORTED);
     }
 };
 
@@ -3950,7 +3924,7 @@
 
     // Delete must work if rollback protection is implemented
     if (error == ErrorCode::OK) {
-        AuthorizationSet hardwareEnforced(key_characteristics_.hardwareEnforced);
+        AuthorizationSet hardwareEnforced(SecLevelAuthorizations());
         ASSERT_TRUE(hardwareEnforced.Contains(TAG_ROLLBACK_RESISTANCE));
 
         ASSERT_EQ(ErrorCode::OK, DeleteKey(true /* keep key blob */));
@@ -3983,8 +3957,8 @@
 
     // Delete must work if rollback protection is implemented
     if (error == ErrorCode::OK) {
-        AuthorizationSet hardwareEnforced(key_characteristics_.hardwareEnforced);
-        ASSERT_TRUE(hardwareEnforced.Contains(TAG_ROLLBACK_RESISTANCE));
+        AuthorizationSet enforced(SecLevelAuthorizations());
+        ASSERT_TRUE(enforced.Contains(TAG_ROLLBACK_RESISTANCE));
 
         // Delete the key we don't care about the result at this point.
         DeleteKey();
@@ -4019,7 +3993,7 @@
 
     // Delete must work if rollback protection is implemented
     if (error == ErrorCode::OK) {
-        AuthorizationSet hardwareEnforced(key_characteristics_.hardwareEnforced);
+        AuthorizationSet hardwareEnforced(SecLevelAuthorizations());
         ASSERT_TRUE(hardwareEnforced.Contains(TAG_ROLLBACK_RESISTANCE));
 
         ASSERT_EQ(ErrorCode::OK, DeleteAllKeys());
diff --git a/security/keymint/support/include/keymint_support/key_param_output.h b/security/keymint/support/include/keymint_support/key_param_output.h
index 5f004fe..c2b0029 100644
--- a/security/keymint/support/include/keymint_support/key_param_output.h
+++ b/security/keymint/support/include/keymint_support/key_param_output.h
@@ -84,8 +84,10 @@
 ::std::ostream& operator<<(::std::ostream& os, const KeyParameter& param);
 
 inline ::std::ostream& operator<<(::std::ostream& os, const KeyCharacteristics& value) {
-    return os << "SW: " << value.softwareEnforced << ::std::endl
-              << "HW: " << value.hardwareEnforced << ::std::endl;
+    for (auto& entry : value.authorizations) {
+        os << value.securityLevel << ": " << entry;
+    }
+    return os;
 }
 
 inline ::std::ostream& operator<<(::std::ostream& os, KeyPurpose value) {
diff --git a/security/secureclock/aidl/Android.bp b/security/secureclock/aidl/Android.bp
new file mode 100644
index 0000000..7d26a9b
--- /dev/null
+++ b/security/secureclock/aidl/Android.bp
@@ -0,0 +1,24 @@
+aidl_interface {
+    name: "android.hardware.security.secureclock",
+    vendor_available: true,
+    srcs: [
+        "android/hardware/security/secureclock/*.aidl",
+    ],
+    stability: "vintf",
+    imports: [
+        "android.hardware.security.keymint",
+    ],
+    backend: {
+        java: {
+            sdk_version: "module_current",
+        },
+        ndk: {
+            vndk: {
+                enabled: true,
+            },
+        },
+        rust: {
+            enabled: true,
+        },
+    },
+}
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
new file mode 100644
index 0000000..c16b312
--- /dev/null
+++ b/security/secureclock/aidl/aidl_api/android.hardware.security.secureclock/current/android/hardware/security/secureclock/ISecureClock.aidl
@@ -0,0 +1,24 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.security.secureclock;
+@VintfStability
+interface ISecureClock {
+  android.hardware.security.secureclock.TimeStampToken generateTimeStamp(in long challenge);
+  const String TIME_STAMP_MAC_LABEL = "Time Verification";
+}
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
new file mode 100644
index 0000000..c23ddca
--- /dev/null
+++ b/security/secureclock/aidl/aidl_api/android.hardware.security.secureclock/current/android/hardware/security/secureclock/TimeStampToken.aidl
@@ -0,0 +1,26 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.security.secureclock;
+@VintfStability
+parcelable TimeStampToken {
+  long challenge;
+  android.hardware.security.keymint.Timestamp timestamp;
+  android.hardware.security.keymint.SecurityLevel securityLevel;
+  byte[] mac;
+}
diff --git a/security/secureclock/aidl/android/hardware/security/secureclock/ISecureClock.aidl b/security/secureclock/aidl/android/hardware/security/secureclock/ISecureClock.aidl
new file mode 100644
index 0000000..7d416dd
--- /dev/null
+++ b/security/secureclock/aidl/android/hardware/security/secureclock/ISecureClock.aidl
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * limitations under the License.
+ */
+
+package android.hardware.security.secureclock;
+import android.hardware.security.secureclock.TimeStampToken;
+
+/**
+ * Secure Clock definition.
+ *
+ * An ISecureClock provides a keymint service to generate secure timestamp using a secure platform.
+ * The secure time stamp contains time in milliseconds. This time stamp also contains a 256-bit MAC
+ * which provides integrity protection. The MAC is generated using HMAC-SHA-256 and a shared
+ * 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.
+ */
+
+@VintfStability
+interface ISecureClock {
+    /**
+     * String used as context in the HMAC computation signing the generated time stamp.
+     * See TimeStampToken.mac for details.
+     */
+    const String TIME_STAMP_MAC_LABEL = "Time Verification";
+
+    /**
+     * Generates an authenticated timestamp.
+     *
+     * @param A challenge value provided by the relying party. It will be included in the generated
+     *        TimeStampToken to ensure freshness. The relying service must ensure that the
+     *        challenge cannot be specified or predicted by an attacker.
+     *
+     * @return the TimeStampToken, see the definition for details.
+     */
+    TimeStampToken generateTimeStamp(in long challenge);
+}
diff --git a/security/secureclock/aidl/android/hardware/security/secureclock/TimeStampToken.aidl b/security/secureclock/aidl/android/hardware/security/secureclock/TimeStampToken.aidl
new file mode 100644
index 0000000..76a2d28
--- /dev/null
+++ b/security/secureclock/aidl/android/hardware/security/secureclock/TimeStampToken.aidl
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.security.secureclock;
+
+import android.hardware.security.keymint.SecurityLevel;
+import android.hardware.security.keymint.Timestamp;
+
+/**
+ * TimeStampToken instances are used for secure environments that requires secure time information.
+ */
+
+@VintfStability
+parcelable TimeStampToken {
+    /**
+     * The challenge that was provided as argument to ISecureClock.generateTimeStamp by the client.
+     */
+    long challenge;
+
+    /**
+     * The current time of the secure environment that generates the TimeStampToken.
+     */
+    Timestamp timestamp;
+
+    /**
+     * SecurityLevel of the secure environment that generated the token.
+     */
+    SecurityLevel securityLevel;
+
+    /**
+     * 32-byte HMAC-SHA256 of the above values, computed as:
+     *
+     *    HMAC(H,
+     *         ISecureClock.TIME_STAMP_MAC_LABEL || challenge || timestamp)
+     *
+     * where:
+     *
+     *   ``ISecureClock.TIME_STAMP_MAC_LABEL'' is a sting constant defined in ISecureClock.aidl.
+     *
+     *   ``H'' is the shared HMAC key (see computeSharedHmac() in ISharedHmacSecret).
+     *
+     *   ``||'' represents concatenation
+     *
+     * The representation of challenge and timestamp is as 64-bit unsigned integers in big-endian
+     * order.  securityLevel is represented as a 32-bit unsigned integer in big-endian order.
+     */
+    byte[] mac;
+}
diff --git a/security/sharedsecret/aidl/Android.bp b/security/sharedsecret/aidl/Android.bp
new file mode 100644
index 0000000..ab44110
--- /dev/null
+++ b/security/sharedsecret/aidl/Android.bp
@@ -0,0 +1,21 @@
+aidl_interface {
+    name: "android.hardware.security.sharedsecret",
+    vendor_available: true,
+    srcs: [
+        "android/hardware/security/sharedsecret/*.aidl",
+    ],
+    stability: "vintf",
+    backend: {
+        java: {
+            sdk_version: "module_current",
+        },
+        ndk: {
+            vndk: {
+                enabled: true,
+            },
+        },
+        rust: {
+            enabled: 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
new file mode 100644
index 0000000..2509936
--- /dev/null
+++ b/security/sharedsecret/aidl/aidl_api/android.hardware.security.sharedsecret/current/android/hardware/security/sharedsecret/ISharedSecret.aidl
@@ -0,0 +1,26 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.security.sharedsecret;
+@VintfStability
+interface ISharedSecret {
+  android.hardware.security.sharedsecret.SharedSecretParameters getSharedSecretParameters();
+  byte[] computeSharedSecret(in android.hardware.security.sharedsecret.SharedSecretParameters[] params);
+  const String KEY_AGREEMENT_LABEL = "KeymasterSharedMac";
+  const String KEY_CHECK_LABEL = "Keymaster HMAC Verification";
+}
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
new file mode 100644
index 0000000..9b65046
--- /dev/null
+++ b/security/sharedsecret/aidl/aidl_api/android.hardware.security.sharedsecret/current/android/hardware/security/sharedsecret/SharedSecretParameters.aidl
@@ -0,0 +1,24 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.security.sharedsecret;
+@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
new file mode 100644
index 0000000..906303f
--- /dev/null
+++ b/security/sharedsecret/aidl/android/hardware/security/sharedsecret/ISharedSecret.aidl
@@ -0,0 +1,114 @@
+/*
+ * 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.
+ */
+
+package android.hardware.security.sharedsecret;
+import android.hardware.security.sharedsecret.SharedSecretParameters;
+
+/**
+ * Shared Secret definition.
+ *
+ * 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:
+ *
+ * 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
+ * below.
+ * Step 2: The system lexicographically sorts the shared secret parameters received from each
+ * service and then sends these sorted parameter list to each service in a computeSharedSecret
+ * method defined below. The services individually computes the shared secret and returns back
+ * the 32 byte sharing check hash value generated by using the computed shared secret.
+ * 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.
+ */
+
+@VintfStability
+interface ISharedSecret {
+    /**
+     * String used as label in the shared key derivation. See computeSharedSecret below.
+     */
+    const String KEY_AGREEMENT_LABEL = "KeymasterSharedMac";
+
+    /**
+     * String used as context in the computation of the sharingCheck. See computeSharedSecret
+     * below.
+     */
+    const String KEY_CHECK_LABEL = "Keymaster HMAC Verification";
+
+    /**
+     * This method is the first 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 HAL instances and collects the
+     * results in preparation for the second step.
+     *
+     * @return The SharedSecretParameters to use.  As specified in the SharedSecretParameters
+     *         documentation, the seed must contain the same value in every invocation
+     *         of the method on a given device, and the nonce must return the same value for every
+     *         invocation during a boot session.
+     */
+    SharedSecretParameters getSharedSecretParameters();
+
+    /**
+     * 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.
+     *
+     * 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):
+     *
+     *     H = CKDF(key = K,
+     *              context = P1 || P2 || ... || Pn,
+     *              label = KEY_AGREEMENT_LABEL)
+     *
+     * where:
+     *
+     *     ``CKDF'' is the standard AES-CMAC KDF from NIST SP 800-108 in counter mode (see Section
+     *           5.1 of the referenced publication).  ``key'', ``context'', and ``label'' are
+     *           defined in the standard.  The counter is prefixed and length L appended, as shown
+     *           in the construction on page 12 of the standard.  The label string is UTF-8 encoded.
+     *
+     *     ``K'' is a pre-established shared secret, set up during factory reset.  The mechanism for
+     *           establishing this shared secret is implementation-defined.Any method of securely
+     *           establishing K that ensures that an attacker cannot obtain or derive its value is
+     *           acceptable.
+     *
+     *           CRITICAL SECURITY REQUIREMENT: All keys created by a IKeymintDevice instance must
+     *           be cryptographically bound to the value of K, such that establishing a new K
+     *           permanently destroys them.
+     *
+     *     ``||'' represents concatenation.
+     *
+     *     ``Pi'' is the i'th SharedSecretParameters value in the params vector. Encoding of an
+     *           SharedSecretParameters is the concatenation of its two fields, i.e. seed || nonce.
+     *
+     * 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
+     * was called.
+     *
+     * @return sharingCheck A 32-byte value used to verify that all the keymint services 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
+     *         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
new file mode 100644
index 0000000..691b3f1
--- /dev/null
+++ b/security/sharedsecret/aidl/android/hardware/security/sharedsecret/SharedSecretParameters.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.security.sharedsecret;
+
+/**
+ * SharedSecretParameters holds the data used in the process of establishing a shared secret i.e.
+ * 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.
+ */
+
+@VintfStability
+parcelable SharedSecretParameters {
+    /**
+     * Either empty or contains a non zero persistent value that is associated with the pre-shared
+     * HMAC agreement key.  It is either empty or 32 bytes in length.
+     */
+    byte[] seed;
+
+    /**
+     * A 32-byte value which is guaranteed to be different each time
+     * getSharedSecretParameters() is called.  Probabilistic uniqueness (i.e. random) is acceptable,
+     * though a stronger uniqueness guarantee (e.g. counter) is recommended where possible.
+     */
+    byte[] nonce;
+}
diff --git a/tv/input/1.0/default/TvInput.cpp b/tv/input/1.0/default/TvInput.cpp
index 4ea1dec..7583a67 100644
--- a/tv/input/1.0/default/TvInput.cpp
+++ b/tv/input/1.0/default/TvInput.cpp
@@ -142,7 +142,7 @@
 
 // static
 void TvInput::notify(struct tv_input_device* __unused, tv_input_event_t* event,
-        void* __unused) {
+                     void* optionalStatus) {
     if (mCallback != nullptr && event != nullptr) {
         // Capturing is no longer supported.
         if (event->type >= TV_INPUT_EVENT_CAPTURE_SUCCEEDED) {
@@ -154,7 +154,17 @@
         tvInputEvent.deviceInfo.type = static_cast<TvInputType>(
                 event->device_info.type);
         tvInputEvent.deviceInfo.portId = event->device_info.hdmi.port_id;
-        tvInputEvent.deviceInfo.cableConnectionStatus = CableConnectionStatus::UNKNOWN;
+        CableConnectionStatus connectionStatus = CableConnectionStatus::UNKNOWN;
+        if (optionalStatus != nullptr &&
+            ((event->type == TV_INPUT_EVENT_STREAM_CONFIGURATIONS_CHANGED) ||
+             (event->type == TV_INPUT_EVENT_DEVICE_AVAILABLE))) {
+            int newStatus = *reinterpret_cast<int*>(optionalStatus);
+            if (newStatus <= static_cast<int>(CableConnectionStatus::DISCONNECTED) &&
+                newStatus >= static_cast<int>(CableConnectionStatus::UNKNOWN)) {
+                connectionStatus = static_cast<CableConnectionStatus>(newStatus);
+            }
+        }
+        tvInputEvent.deviceInfo.cableConnectionStatus = connectionStatus;
         // TODO: Ensure the legacy audio type code is the same once audio HAL default
         // implementation is ready.
         tvInputEvent.deviceInfo.audioType = static_cast<AudioDevice>(
diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/CompositePrimitive.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/CompositePrimitive.aidl
index 6ab7ac5..3071dce3 100644
--- a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/CompositePrimitive.aidl
+++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/CompositePrimitive.aidl
@@ -26,4 +26,5 @@
   SLOW_RISE = 5,
   QUICK_FALL = 6,
   LIGHT_TICK = 7,
+  LOW_TICK = 8,
 }
diff --git a/vibrator/aidl/android/hardware/vibrator/CompositePrimitive.aidl b/vibrator/aidl/android/hardware/vibrator/CompositePrimitive.aidl
index 8e82db0..5314898 100644
--- a/vibrator/aidl/android/hardware/vibrator/CompositePrimitive.aidl
+++ b/vibrator/aidl/android/hardware/vibrator/CompositePrimitive.aidl
@@ -70,4 +70,11 @@
      * Support is required.
      */
     LIGHT_TICK,
+    /**
+     * This very short low frequency effect should produce a light crisp sensation intended
+     * to be used repetitively for dynamic feedback.
+     *
+     * Support is required.
+     */
+    LOW_TICK,
 }
diff --git a/vibrator/aidl/default/Vibrator.cpp b/vibrator/aidl/default/Vibrator.cpp
index c446afd..1021e62 100644
--- a/vibrator/aidl/default/Vibrator.cpp
+++ b/vibrator/aidl/default/Vibrator.cpp
@@ -119,6 +119,7 @@
             CompositePrimitive::THUD,       CompositePrimitive::SPIN,
             CompositePrimitive::QUICK_RISE, CompositePrimitive::SLOW_RISE,
             CompositePrimitive::QUICK_FALL, CompositePrimitive::LIGHT_TICK,
+            CompositePrimitive::LOW_TICK,
     };
     return ndk::ScopedAStatus::ok();
 }
diff --git a/vibrator/aidl/default/vibrator-default.xml b/vibrator/aidl/default/vibrator-default.xml
index 137a811..b5bd3dd 100644
--- a/vibrator/aidl/default/vibrator-default.xml
+++ b/vibrator/aidl/default/vibrator-default.xml
@@ -1,6 +1,7 @@
 <manifest version="1.0" type="device">
     <hal format="aidl">
         <name>android.hardware.vibrator</name>
+        <version>2</version>
         <fqname>IVibrator/default</fqname>
     </hal>
     <hal format="aidl">
diff --git a/wifi/1.5/IWifiChip.hal b/wifi/1.5/IWifiChip.hal
index 80f2ca4..b2960cf 100644
--- a/wifi/1.5/IWifiChip.hal
+++ b/wifi/1.5/IWifiChip.hal
@@ -216,4 +216,22 @@
     setCoexUnsafeChannels(
         vec<CoexUnsafeChannel> unsafeChannels, bitfield<CoexRestriction> restrictions)
             generates (WifiStatus status);
+
+    /**
+     * Set country code for this Wifi chip.
+     *
+     * Country code is global setting across the Wifi chip and not Wifi
+     * interface (STA or AP) specific. Legacy HAL API's for country code in
+     * @1.0::ISupplicantStaIface::setCountryCode &
+     * @1.0::IWifiApIface:setCountryCode are deprecated in favor of this
+     * chip level API.
+     *
+     * @param code 2 byte country code (as defined in ISO 3166) to set.
+     * @return status Status of the operation.
+     *         Possible status codes:
+     *         |WifiStatusCode.SUCCESS|,
+     *         |WifiStatusCode.FAILURE_UNKNOWN|,
+     *         |WifiStatusCode.FAILURE_IFACE_INVALID|
+     */
+    setCountryCode(int8_t[2] code) generates (WifiStatus status);
 };
diff --git a/wifi/1.5/default/wifi_chip.cpp b/wifi/1.5/default/wifi_chip.cpp
index 80a48f5..fbb4a52 100644
--- a/wifi/1.5/default/wifi_chip.cpp
+++ b/wifi/1.5/default/wifi_chip.cpp
@@ -731,6 +731,13 @@
                            hidl_status_cb, unsafeChannels, restrictions);
 }
 
+Return<void> WifiChip::setCountryCode(const hidl_array<int8_t, 2>& code,
+                                      setCountryCode_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiChip::setCountryCodeInternal, hidl_status_cb,
+                           code);
+}
+
 void WifiChip::invalidateAndRemoveAllIfaces() {
     invalidateAndClearBridgedApAll();
     invalidateAndClearAll(ap_ifaces_);
@@ -1478,6 +1485,12 @@
     return createWifiStatusFromLegacyError(legacy_status);
 }
 
+WifiStatus WifiChip::setCountryCodeInternal(const std::array<int8_t, 2>& code) {
+    auto legacy_status =
+        legacy_hal_.lock()->setCountryCode(getFirstActiveWlanIfaceName(), code);
+    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 95c122d..7d7a9b5 100644
--- a/wifi/1.5/default/wifi_chip.h
+++ b/wifi/1.5/default/wifi_chip.h
@@ -178,6 +178,8 @@
         const hidl_vec<CoexUnsafeChannel>& unsafe_channels,
         hidl_bitfield<IfaceType> restrictions,
         setCoexUnsafeChannels_cb hidl_status_cb) override;
+    Return<void> setCountryCode(const hidl_array<int8_t, 2>& code,
+                                setCountryCode_cb _hidl_cb) override;
 
    private:
     void invalidateAndRemoveAllIfaces();
@@ -258,7 +260,7 @@
     WifiStatus setMultiStaUseCaseInternal(MultiStaUseCase use_case);
     WifiStatus setCoexUnsafeChannelsInternal(
         std::vector<CoexUnsafeChannel> unsafe_channels, uint32_t restrictions);
-
+    WifiStatus setCountryCodeInternal(const std::array<int8_t, 2>& code);
     WifiStatus handleChipConfiguration(
         std::unique_lock<std::recursive_mutex>* lock, ChipModeId mode_id);
     WifiStatus registerDebugRingBufferCallback();
diff --git a/wifi/1.5/default/wifi_legacy_hal.cpp b/wifi/1.5/default/wifi_legacy_hal.cpp
index e1a5a8c..3e65ee0 100644
--- a/wifi/1.5/default/wifi_legacy_hal.cpp
+++ b/wifi/1.5/default/wifi_legacy_hal.cpp
@@ -1630,6 +1630,12 @@
                                                    configId);
 }
 
+wifi_error WifiLegacyHal::setDtimConfig(const std::string& iface_name,
+                                        uint32_t multiplier) {
+    return global_func_table_.wifi_set_dtim_config(getIfaceHandle(iface_name),
+                                                   multiplier);
+}
+
 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 610a332..0cc1cff 100644
--- a/wifi/1.5/default/wifi_legacy_hal.h
+++ b/wifi/1.5/default/wifi_legacy_hal.h
@@ -690,6 +690,9 @@
 
     wifi_error twtClearStats(const std::string& iface_name, uint8_t configId);
 
+    wifi_error setDtimConfig(const std::string& iface_name,
+                             uint32_t multiplier);
+
    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 4b005d6..7ba5d9b 100644
--- a/wifi/1.5/default/wifi_legacy_hal_stubs.cpp
+++ b/wifi/1.5/default/wifi_legacy_hal_stubs.cpp
@@ -158,6 +158,7 @@
     populateStubFor(&hal_fn->wifi_twt_info_frame_request);
     populateStubFor(&hal_fn->wifi_twt_get_stats);
     populateStubFor(&hal_fn->wifi_twt_clear_stats);
+    populateStubFor(&hal_fn->wifi_set_dtim_config);
     return true;
 }
 }  // namespace legacy_hal
diff --git a/wifi/1.5/vts/functional/Android.bp b/wifi/1.5/vts/functional/Android.bp
index 2d8b412..118822a 100644
--- a/wifi/1.5/vts/functional/Android.bp
+++ b/wifi/1.5/vts/functional/Android.bp
@@ -14,6 +14,27 @@
 // limitations under the License.
 //
 
+cc_library_static {
+    name: "VtsHalWifiV1_5TargetTestUtil",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: [
+        "wifi_hidl_test_utils_1_5.cpp",
+    ],
+    export_include_dirs: [
+        ".",
+    ],
+    shared_libs: [
+        "libnativehelper",
+    ],
+    static_libs: [
+        "VtsHalWifiV1_0TargetTestUtil",
+        "android.hardware.wifi@1.0",
+        "android.hardware.wifi@1.3",
+        "android.hardware.wifi@1.5",
+        "libwifi-system-iface",
+    ],
+}
+
 cc_test {
     name: "VtsHalWifiV1_5TargetTest",
     defaults: ["VtsHalTargetTestDefaults"],
@@ -67,9 +88,11 @@
     defaults: ["VtsHalTargetTestDefaults"],
     srcs: [
         "wifi_chip_hidl_ap_test.cpp",
+        "wifi_ap_iface_hidl_test.cpp",
     ],
     static_libs: [
         "VtsHalWifiV1_0TargetTestUtil",
+        "VtsHalWifiV1_5TargetTestUtil",
         "android.hardware.wifi@1.0",
         "android.hardware.wifi@1.1",
         "android.hardware.wifi@1.2",
diff --git a/wifi/1.5/vts/functional/wifi_ap_iface_hidl_test.cpp b/wifi/1.5/vts/functional/wifi_ap_iface_hidl_test.cpp
new file mode 100644
index 0000000..e47b14d
--- /dev/null
+++ b/wifi/1.5/vts/functional/wifi_ap_iface_hidl_test.cpp
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <VtsCoreUtil.h>
+#include <VtsHalHidlTargetCallbackBase.h>
+#include <android-base/logging.h>
+
+#undef NAN  // NAN is defined in bionic/libc/include/math.h:38
+
+#include <android/hardware/wifi/1.4/IWifiChipEventCallback.h>
+#include <android/hardware/wifi/1.5/IWifi.h>
+#include <android/hardware/wifi/1.5/IWifiApIface.h>
+#include <android/hardware/wifi/1.5/IWifiChip.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
+
+#include "wifi_hidl_call_util.h"
+#include "wifi_hidl_test_utils.h"
+#include "wifi_hidl_test_utils_1_5.h"
+
+using ::android::sp;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::wifi::V1_0::ChipModeId;
+using ::android::hardware::wifi::V1_0::IfaceType;
+using ::android::hardware::wifi::V1_0::IWifiIface;
+using ::android::hardware::wifi::V1_0::WifiDebugRingBufferStatus;
+using ::android::hardware::wifi::V1_0::WifiStatus;
+using ::android::hardware::wifi::V1_0::WifiStatusCode;
+using ::android::hardware::wifi::V1_4::IWifiChipEventCallback;
+using ::android::hardware::wifi::V1_5::IWifiApIface;
+using ::android::hardware::wifi::V1_5::IWifiChip;
+
+/**
+ * Fixture for IWifiChip tests that are conditioned on SoftAP support.
+ */
+class WifiApIfaceHidlTest : public ::testing::TestWithParam<std::string> {
+   public:
+    virtual void SetUp() override {
+        isBridgedSupport_ = testing::checkSubstringInCommandOutput(
+            "/system/bin/cmd wifi get-softap-supported-features",
+            "wifi_softap_bridged_ap_supported");
+        // Make sure to start with a clean state
+        stopWifi(GetInstanceName());
+    }
+
+    virtual void TearDown() override { stopWifi(GetInstanceName()); }
+
+   protected:
+    bool isBridgedSupport_ = false;
+    std::string GetInstanceName() { return GetParam(); }
+};
+
+/*
+ * resetToFactoryMacAddress
+ */
+TEST_P(WifiApIfaceHidlTest, resetToFactoryMacAddressInBridgedModeTest) {
+    if (!isBridgedSupport_) GTEST_SKIP() << "Missing Bridged AP support";
+    sp<IWifiApIface> wifi_ap_iface =
+        getBridgedWifiApIface_1_5(GetInstanceName());
+    ASSERT_NE(nullptr, wifi_ap_iface.get());
+    const auto& status = HIDL_INVOKE(wifi_ap_iface, resetToFactoryMacAddress);
+    EXPECT_EQ(WifiStatusCode::SUCCESS, status.code);
+}
+
+/*
+ * resetToFactoryMacAddress
+ */
+TEST_P(WifiApIfaceHidlTest, resetToFactoryMacAddressTest) {
+    sp<IWifiApIface> wifi_ap_iface = getWifiApIface_1_5(GetInstanceName());
+    ASSERT_NE(nullptr, wifi_ap_iface.get());
+    const auto& status = HIDL_INVOKE(wifi_ap_iface, resetToFactoryMacAddress);
+    EXPECT_EQ(WifiStatusCode::SUCCESS, status.code);
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WifiApIfaceHidlTest);
+INSTANTIATE_TEST_SUITE_P(
+    PerInstance, WifiApIfaceHidlTest,
+    testing::ValuesIn(android::hardware::getAllHalInstanceNames(
+        ::android::hardware::wifi::V1_5::IWifi::descriptor)),
+    android::hardware::PrintInstanceNameToString);
diff --git a/wifi/1.5/vts/functional/wifi_chip_hidl_ap_test.cpp b/wifi/1.5/vts/functional/wifi_chip_hidl_ap_test.cpp
index 395d317..922c9a7 100644
--- a/wifi/1.5/vts/functional/wifi_chip_hidl_ap_test.cpp
+++ b/wifi/1.5/vts/functional/wifi_chip_hidl_ap_test.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <VtsCoreUtil.h>
 #include <VtsHalHidlTargetCallbackBase.h>
 #include <android-base/logging.h>
 
@@ -51,6 +52,9 @@
 class WifiChipHidlTest : public ::testing::TestWithParam<std::string> {
    public:
     virtual void SetUp() override {
+        isBridgedSupport_ = testing::checkSubstringInCommandOutput(
+            "/system/bin/cmd wifi get-softap-supported-features",
+            "wifi_softap_bridged_ap_supported");
         // Make sure to start with a clean state
         stopWifi(GetInstanceName());
 
@@ -61,6 +65,7 @@
     virtual void TearDown() override { stopWifi(GetInstanceName()); }
 
    protected:
+    bool isBridgedSupport_ = false;
     // Helper function to configure the Chip in one of the supported modes.
     // Most of the non-mode-configuration-related methods require chip
     // to be first configured.
@@ -71,19 +76,12 @@
         return mode_id;
     }
 
-    WifiStatusCode createApIface(sp<IWifiApIface>* ap_iface) {
-        configureChipForIfaceType(IfaceType::AP, true);
-        const auto& status_and_iface = HIDL_INVOKE(wifi_chip_, createApIface);
-        *ap_iface = IWifiApIface::castFrom(status_and_iface.second);
-        return status_and_iface.first.code;
-    }
-
-    WifiStatusCode createBridgedApIface(sp<IWifiApIface>* ap_iface) {
+    void createBridgedApIface(sp<IWifiApIface>* ap_iface) {
         configureChipForIfaceType(IfaceType::AP, true);
         const auto& status_and_iface =
             HIDL_INVOKE(wifi_chip_, createBridgedApIface);
         *ap_iface = status_and_iface.second;
-        return status_and_iface.first.code;
+        EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_iface.first.code);
     }
 
     sp<IWifiChip> wifi_chip_;
@@ -92,19 +90,25 @@
     std::string GetInstanceName() { return GetParam(); }
 };
 
-// TODO: b/173999527. Add test for bridged API.
-
-/*
- * resetToFactoryMacAddress
+/**
+ * createBridgedApIface & removeIfaceInstanceFromBridgedApIface
  */
-TEST_P(WifiChipHidlTest, resetToFactoryMacAddressTest) {
+TEST_P(WifiChipHidlTest,
+       createBridgedApIfaceAndremoveIfaceInstanceFromBridgedApIfaceTest) {
+    if (!isBridgedSupport_) GTEST_SKIP() << "Missing Bridged AP support";
     sp<IWifiApIface> wifi_ap_iface;
-    const auto& status_code = createApIface(&wifi_ap_iface);
-    if (status_code != WifiStatusCode::SUCCESS) {
-        EXPECT_EQ(WifiStatusCode::ERROR_NOT_SUPPORTED, status_code);
-    }
-    const auto& status = HIDL_INVOKE(wifi_ap_iface, resetToFactoryMacAddress);
-    EXPECT_EQ(WifiStatusCode::SUCCESS, status.code);
+    createBridgedApIface(&wifi_ap_iface);
+    ASSERT_NE(nullptr, wifi_ap_iface.get());
+    const auto& status_and_name = HIDL_INVOKE(wifi_ap_iface, getName);
+    EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_name.first.code);
+    // TODO: b/173999527, add API to get instance name to replace it.
+    std::string br_name = status_and_name.second;  // ap_br_ is the pre-fix
+    std::string instance_name =
+        br_name.substr(6, br_name.length());  // remove the pre-fex
+    const auto& status_code =
+        HIDL_INVOKE(wifi_chip_, removeIfaceInstanceFromBridgedApIface, br_name,
+                    instance_name);
+    EXPECT_EQ(WifiStatusCode::SUCCESS, status_code.code);
 }
 
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WifiChipHidlTest);
diff --git a/wifi/1.5/vts/functional/wifi_chip_hidl_test.cpp b/wifi/1.5/vts/functional/wifi_chip_hidl_test.cpp
index a065721..36a8448 100644
--- a/wifi/1.5/vts/functional/wifi_chip_hidl_test.cpp
+++ b/wifi/1.5/vts/functional/wifi_chip_hidl_test.cpp
@@ -173,6 +173,20 @@
     }
 }
 
+/*
+ * SetCountryCode:
+ * Ensures that a call to set the country code will return with a success
+ * status code.
+ */
+TEST_P(WifiChipHidlTest, setCountryCode) {
+    const android::hardware::hidl_array<int8_t, 2> kCountryCode{
+        std::array<int8_t, 2>{{0x55, 0x53}}};
+
+    configureChipForIfaceType(IfaceType::STA, true);
+    EXPECT_EQ(WifiStatusCode::SUCCESS,
+              HIDL_INVOKE(wifi_chip_, setCountryCode, kCountryCode).code);
+}
+
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WifiChipHidlTest);
 INSTANTIATE_TEST_SUITE_P(
     PerInstance, WifiChipHidlTest,
diff --git a/wifi/1.5/vts/functional/wifi_hidl_test_utils_1_5.cpp b/wifi/1.5/vts/functional/wifi_hidl_test_utils_1_5.cpp
new file mode 100644
index 0000000..f1da2ea
--- /dev/null
+++ b/wifi/1.5/vts/functional/wifi_hidl_test_utils_1_5.cpp
@@ -0,0 +1,61 @@
+/*
+ * 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 <VtsHalHidlTargetCallbackBase.h>
+#include <android-base/logging.h>
+
+#undef NAN  // NAN is defined in bionic/libc/include/math.h:38
+
+#include <android/hardware/wifi/1.5/IWifi.h>
+#include <android/hardware/wifi/1.5/IWifiApIface.h>
+#include <android/hardware/wifi/1.5/IWifiChip.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
+
+#include "wifi_hidl_call_util.h"
+#include "wifi_hidl_test_utils.h"
+
+using ::android::sp;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::wifi::V1_0::ChipModeId;
+using ::android::hardware::wifi::V1_0::IfaceType;
+using ::android::hardware::wifi::V1_5::IWifiApIface;
+using ::android::hardware::wifi::V1_5::IWifiChip;
+
+sp<IWifiChip> getWifiChip_1_5(const std::string& instance_name) {
+    return IWifiChip::castFrom(getWifiChip(instance_name));
+}
+
+sp<IWifiApIface> getWifiApIface_1_5(const std::string& instance_name) {
+    ChipModeId mode_id;
+    sp<IWifiChip> wifi_chip_ = getWifiChip_1_5(instance_name);
+    configureChipToSupportIfaceType(wifi_chip_, IfaceType::AP, &mode_id);
+    const auto& status_and_iface = HIDL_INVOKE(wifi_chip_, createApIface);
+    return IWifiApIface::castFrom(status_and_iface.second);
+}
+
+sp<IWifiApIface> getBridgedWifiApIface_1_5(const std::string& instance_name) {
+    ChipModeId mode_id;
+    sp<IWifiChip> wifi_chip_ = getWifiChip_1_5(instance_name);
+    configureChipToSupportIfaceType(wifi_chip_, IfaceType::AP, &mode_id);
+    const auto& status_and_iface =
+        HIDL_INVOKE(wifi_chip_, createBridgedApIface);
+    return IWifiApIface::castFrom(status_and_iface.second);
+}
diff --git a/wifi/1.5/vts/functional/wifi_hidl_test_utils_1_5.h b/wifi/1.5/vts/functional/wifi_hidl_test_utils_1_5.h
new file mode 100644
index 0000000..1b8b737
--- /dev/null
+++ b/wifi/1.5/vts/functional/wifi_hidl_test_utils_1_5.h
@@ -0,0 +1,35 @@
+/*
+ * 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 <android/hardware/wifi/1.5/IWifi.h>
+#include <android/hardware/wifi/1.5/IWifiApIface.h>
+#include <android/hardware/wifi/1.5/IWifiChip.h>
+
+#include <getopt.h>
+
+#include <VtsHalHidlTargetTestEnvBase.h>
+// Helper functions to obtain references to the various HIDL interface objects.
+// Note: We only have a single instance of each of these objects currently.
+// These helper functions should be modified to return vectors if we support
+// multiple instances.
+android::sp<android::hardware::wifi::V1_5::IWifiChip> getWifiChip_1_5(
+    const std::string& instance_name);
+android::sp<android::hardware::wifi::V1_5::IWifiApIface> getWifiApIface_1_5(
+    const std::string& instance_name);
+android::sp<android::hardware::wifi::V1_5::IWifiApIface>
+getBridgedWifiApIface_1_5(const std::string& instance_name);
diff --git a/wifi/hostapd/1.3/vts/functional/Android.bp b/wifi/hostapd/1.3/vts/functional/Android.bp
index 07cebb0..ed18bb6 100644
--- a/wifi/hostapd/1.3/vts/functional/Android.bp
+++ b/wifi/hostapd/1.3/vts/functional/Android.bp
@@ -22,12 +22,18 @@
     ],
     static_libs: [
         "VtsHalWifiV1_0TargetTestUtil",
+        "VtsHalWifiV1_5TargetTestUtil",
         "VtsHalWifiHostapdV1_0TargetTestUtil",
         "android.hardware.wifi.hostapd@1.0",
         "android.hardware.wifi.hostapd@1.1",
         "android.hardware.wifi.hostapd@1.2",
         "android.hardware.wifi.hostapd@1.3",
         "android.hardware.wifi@1.0",
+        "android.hardware.wifi@1.1",
+        "android.hardware.wifi@1.2",
+        "android.hardware.wifi@1.3",
+        "android.hardware.wifi@1.4",
+        "android.hardware.wifi@1.5",
         "libgmock",
         "libwifi-system",
         "libwifi-system-iface",
diff --git a/wifi/hostapd/1.3/vts/functional/hostapd_hidl_test.cpp b/wifi/hostapd/1.3/vts/functional/hostapd_hidl_test.cpp
index a22252c..4e63c56 100644
--- a/wifi/hostapd/1.3/vts/functional/hostapd_hidl_test.cpp
+++ b/wifi/hostapd/1.3/vts/functional/hostapd_hidl_test.cpp
@@ -28,6 +28,7 @@
 
 #include "hostapd_hidl_call_util.h"
 #include "hostapd_hidl_test_utils.h"
+#include "wifi_hidl_test_utils_1_5.h"
 
 using ::android::sp;
 using ::android::hardware::hidl_string;
@@ -38,6 +39,8 @@
 using ::android::hardware::wifi::hostapd::V1_2::Ieee80211ReasonCode;
 using ::android::hardware::wifi::hostapd::V1_3::IHostapd;
 using ::android::hardware::wifi::V1_0::IWifi;
+using ::android::hardware::wifi::V1_0::WifiStatusCode;
+using ::android::hardware::wifi::V1_5::IWifiApIface;
 
 namespace {
 constexpr unsigned char kNwSsid[] = {'t', 'e', 's', 't', '1',
@@ -71,16 +74,39 @@
         isWpa3SaeSupport_ = testing::checkSubstringInCommandOutput(
             "/system/bin/cmd wifi get-softap-supported-features",
             "wifi_softap_wpa3_sae_supported");
+        isBridgedSupport_ = testing::checkSubstringInCommandOutput(
+            "/system/bin/cmd wifi get-softap-supported-features",
+            "wifi_softap_bridged_ap_supported");
     }
 
     virtual void TearDown() override {
         HIDL_INVOKE_VOID_WITHOUT_ARGUMENTS(hostapd_, terminate);
         stopHostapd(wifi_instance_name_);
+        // Wait 3 seconds to allow driver processing load/unload between two
+        // test cases.
+        sleep(3);
     }
 
    protected:
     bool isWpa3SaeSupport_ = false;
     bool isAcsSupport_ = false;
+    bool isBridgedSupport_ = false;
+
+    std::string setupApIfaceAndGetName(bool isBridged) {
+        sp<IWifiApIface> wifi_ap_iface;
+        if (isBridged) {
+            wifi_ap_iface = getBridgedWifiApIface_1_5(wifi_instance_name_);
+        } else {
+            wifi_ap_iface = getWifiApIface_1_5(wifi_instance_name_);
+        }
+        EXPECT_NE(nullptr, wifi_ap_iface.get());
+
+        const auto& status_and_name = HIDL_INVOKE(wifi_ap_iface, getName);
+        EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_name.first.code);
+        return status_and_name.second;
+    }
+
+    // TODO: b/177483254, remove it after fix wlan1 failure case.
     std::string getPrimaryWlanIfaceName() {
         std::array<char, PROPERTY_VALUE_MAX> buffer;
         auto res = property_get("ro.vendor.wifi.sap.interface", buffer.data(),
@@ -90,7 +116,7 @@
         return buffer.data();
     }
 
-    IHostapd::IfaceParams getIfaceParamsWithoutAcs() {
+    IHostapd::IfaceParams getIfaceParamsWithoutAcs(std::string iface_name) {
         ::android::hardware::wifi::hostapd::V1_0::IHostapd::IfaceParams
             iface_params;
         ::android::hardware::wifi::hostapd::V1_1::IHostapd::IfaceParams
@@ -106,7 +132,7 @@
         ::android::hardware::wifi::hostapd::V1_3::IHostapd::ChannelParams
             channelParams_1_3;
 
-        iface_params.ifaceName = getPrimaryWlanIfaceName();
+        iface_params.ifaceName = iface_name;
         iface_params.hwModeParams.enable80211N = true;
         iface_params.hwModeParams.enable80211AC = false;
         iface_params.channelParams.enableAcs = false;
@@ -133,9 +159,41 @@
         return iface_params_1_3;
     }
 
-    IHostapd::IfaceParams getIfaceParamsWithAcs() {
+    IHostapd::IfaceParams getIfaceParamsWithBridgedModeACS(
+        std::string iface_name) {
         // First get the settings for WithoutAcs and then make changes
-        IHostapd::IfaceParams iface_params_1_3 = getIfaceParamsWithoutAcs();
+        IHostapd::IfaceParams iface_params_1_3 =
+            getIfaceParamsWithoutAcs(iface_name);
+        iface_params_1_3.V1_2.V1_1.V1_0.channelParams.enableAcs = true;
+        iface_params_1_3.V1_2.V1_1.V1_0.channelParams.acsShouldExcludeDfs =
+            true;
+
+        std::vector<
+            ::android::hardware::wifi::hostapd::V1_3::IHostapd::ChannelParams>
+            vec_channelParams;
+
+        vec_channelParams.push_back(iface_params_1_3.channelParamsList[0]);
+
+        ::android::hardware::wifi::hostapd::V1_3::IHostapd::ChannelParams
+            second_channelParams_1_3;
+        second_channelParams_1_3.channel = 0;
+        second_channelParams_1_3.enableAcs = true;
+        second_channelParams_1_3.bandMask = 0;
+        second_channelParams_1_3.bandMask |= IHostapd::BandMask::BAND_5_GHZ;
+        second_channelParams_1_3.V1_2 = iface_params_1_3.V1_2.channelParams;
+        second_channelParams_1_3.V1_2.bandMask = 0;
+        second_channelParams_1_3.V1_2.bandMask |=
+            IHostapd::BandMask::BAND_5_GHZ;
+        vec_channelParams.push_back(second_channelParams_1_3);
+
+        iface_params_1_3.channelParamsList = vec_channelParams;
+        return iface_params_1_3;
+    }
+
+    IHostapd::IfaceParams getIfaceParamsWithAcs(std::string iface_name) {
+        // First get the settings for WithoutAcs and then make changes
+        IHostapd::IfaceParams iface_params_1_3 =
+            getIfaceParamsWithoutAcs(iface_name);
         iface_params_1_3.V1_2.V1_1.V1_0.channelParams.enableAcs = true;
         iface_params_1_3.V1_2.V1_1.V1_0.channelParams.acsShouldExcludeDfs =
             true;
@@ -153,8 +211,10 @@
         return iface_params_1_3;
     }
 
-    IHostapd::IfaceParams getIfaceParamsWithAcsAndFreqRange() {
-        IHostapd::IfaceParams iface_params_1_3 = getIfaceParamsWithAcs();
+    IHostapd::IfaceParams getIfaceParamsWithAcsAndFreqRange(
+        std::string iface_name) {
+        IHostapd::IfaceParams iface_params_1_3 =
+            getIfaceParamsWithAcs(iface_name);
         ::android::hardware::wifi::hostapd::V1_2::IHostapd::AcsFrequencyRange
             acsFrequencyRange;
         acsFrequencyRange.start = 2412;
@@ -170,9 +230,10 @@
         return iface_params_1_3;
     }
 
-    IHostapd::IfaceParams getIfaceParamsWithAcsAndInvalidFreqRange() {
+    IHostapd::IfaceParams getIfaceParamsWithAcsAndInvalidFreqRange(
+        std::string iface_name) {
         IHostapd::IfaceParams iface_params_1_3 =
-            getIfaceParamsWithAcsAndFreqRange();
+            getIfaceParamsWithAcsAndFreqRange(iface_name);
         iface_params_1_3.V1_2.channelParams.acsChannelFreqRangesMhz[0].start =
             222;
         iface_params_1_3.V1_2.channelParams.acsChannelFreqRangesMhz[0].end =
@@ -250,8 +311,10 @@
         return nw_params_1_3;
     }
 
-    IHostapd::IfaceParams getIfaceParamsWithInvalidChannel() {
-        IHostapd::IfaceParams iface_params_1_3 = getIfaceParamsWithoutAcs();
+    IHostapd::IfaceParams getIfaceParamsWithInvalidChannel(
+        std::string iface_name) {
+        IHostapd::IfaceParams iface_params_1_3 =
+            getIfaceParamsWithoutAcs(iface_name);
         iface_params_1_3.V1_2.V1_1.V1_0.channelParams.channel =
             kIfaceInvalidChannel;
         iface_params_1_3.channelParamsList[0].channel =
@@ -271,8 +334,11 @@
  */
 TEST_P(HostapdHidlTest, AddPskAccessPointWithAcs) {
     if (!isAcsSupport_) GTEST_SKIP() << "Missing ACS support";
+    // TODO: Use setupApIfaceAndGetName after fixing b/177483254
+    // std::string ifname = setupApIfaceAndGetName(false);
+    std::string ifname = getPrimaryWlanIfaceName();
     auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_3,
-                              getIfaceParamsWithAcs(), getPskNwParams());
+                              getIfaceParamsWithAcs(ifname), getPskNwParams());
     EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
 }
 
@@ -282,9 +348,12 @@
  */
 TEST_P(HostapdHidlTest, AddPskAccessPointWithAcsAndFreqRange) {
     if (!isAcsSupport_) GTEST_SKIP() << "Missing ACS support";
-    auto status =
-        HIDL_INVOKE(hostapd_, addAccessPoint_1_3,
-                    getIfaceParamsWithAcsAndFreqRange(), getPskNwParams());
+    // TODO: Use setupApIfaceAndGetName after fixing b/177483254
+    // std::string ifname = setupApIfaceAndGetName(false);
+    std::string ifname = getPrimaryWlanIfaceName();
+    auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_3,
+                              getIfaceParamsWithAcsAndFreqRange(ifname),
+                              getPskNwParams());
     EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
 }
 
@@ -294,8 +363,11 @@
  */
 TEST_P(HostapdHidlTest, AddPskAccessPointWithAcsAndInvalidFreqRange) {
     if (!isAcsSupport_) GTEST_SKIP() << "Missing ACS support";
+    // TODO: Use setupApIfaceAndGetName after fixing b/177483254
+    // std::string ifname = setupApIfaceAndGetName(false);
+    std::string ifname = getPrimaryWlanIfaceName();
     auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_3,
-                              getIfaceParamsWithAcsAndInvalidFreqRange(),
+                              getIfaceParamsWithAcsAndInvalidFreqRange(ifname),
                               getPskNwParams());
     EXPECT_NE(HostapdStatusCode::SUCCESS, status.code);
 }
@@ -306,8 +378,11 @@
  */
 TEST_P(HostapdHidlTest, AddOpenAccessPointWithAcs) {
     if (!isAcsSupport_) GTEST_SKIP() << "Missing ACS support";
+    // TODO: Use setupApIfaceAndGetName after fixing b/177483254
+    // std::string ifname = setupApIfaceAndGetName(false);
+    std::string ifname = getPrimaryWlanIfaceName();
     auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_3,
-                              getIfaceParamsWithAcs(), getOpenNwParams());
+                              getIfaceParamsWithAcs(ifname), getOpenNwParams());
     EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
 }
 
@@ -316,8 +391,12 @@
  * Access point creation should pass.
  */
 TEST_P(HostapdHidlTest, AddPskAccessPointWithoutAcs) {
-    auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_3,
-                              getIfaceParamsWithoutAcs(), getPskNwParams());
+    // TODO: Use setupApIfaceAndGetName after fixing b/177483254
+    // std::string ifname = setupApIfaceAndGetName(false);
+    std::string ifname = getPrimaryWlanIfaceName();
+    auto status =
+        HIDL_INVOKE(hostapd_, addAccessPoint_1_3,
+                    getIfaceParamsWithoutAcs(ifname), getPskNwParams());
     EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
 }
 
@@ -326,9 +405,12 @@
  * Access point creation should pass.
  */
 TEST_P(HostapdHidlTest, AddPskAccessPointWithoutAcsAndNonMetered) {
-    auto status =
-        HIDL_INVOKE(hostapd_, addAccessPoint_1_3, getIfaceParamsWithoutAcs(),
-                    getPskNwParamsWithNonMetered());
+    // TODO: Use setupApIfaceAndGetName after fixing b/177483254
+    // std::string ifname = setupApIfaceAndGetName(false);
+    std::string ifname = getPrimaryWlanIfaceName();
+    auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_3,
+                              getIfaceParamsWithoutAcs(ifname),
+                              getPskNwParamsWithNonMetered());
     EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
 }
 
@@ -337,8 +419,12 @@
  * Access point creation should pass.
  */
 TEST_P(HostapdHidlTest, AddOpenAccessPointWithoutAcs) {
-    auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_3,
-                              getIfaceParamsWithoutAcs(), getOpenNwParams());
+    // TODO: Use setupApIfaceAndGetName after fixing b/177483254
+    // std::string ifname = setupApIfaceAndGetName(false);
+    std::string ifname = getPrimaryWlanIfaceName();
+    auto status =
+        HIDL_INVOKE(hostapd_, addAccessPoint_1_3,
+                    getIfaceParamsWithoutAcs(ifname), getOpenNwParams());
     EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
 }
 
@@ -348,9 +434,12 @@
  */
 TEST_P(HostapdHidlTest, AddSaeTransitionAccessPointWithoutAcs) {
     if (!isWpa3SaeSupport_) GTEST_SKIP() << "Missing SAE support";
-    auto status =
-        HIDL_INVOKE(hostapd_, addAccessPoint_1_3, getIfaceParamsWithoutAcs(),
-                    getSaeTransitionNwParams());
+    // TODO: Use setupApIfaceAndGetName after fixing b/177483254
+    // std::string ifname = setupApIfaceAndGetName(false);
+    std::string ifname = getPrimaryWlanIfaceName();
+    auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_3,
+                              getIfaceParamsWithoutAcs(ifname),
+                              getSaeTransitionNwParams());
     EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
 }
 
@@ -360,8 +449,12 @@
  */
 TEST_P(HostapdHidlTest, AddSAEAccessPointWithoutAcs) {
     if (!isWpa3SaeSupport_) GTEST_SKIP() << "Missing SAE support";
-    auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_3,
-                              getIfaceParamsWithoutAcs(), getSaeNwParams());
+    // TODO: Use setupApIfaceAndGetName after fixing b/177483254
+    // std::string ifname = setupApIfaceAndGetName(false);
+    std::string ifname = getPrimaryWlanIfaceName();
+    auto status =
+        HIDL_INVOKE(hostapd_, addAccessPoint_1_3,
+                    getIfaceParamsWithoutAcs(ifname), getSaeNwParams());
     EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
 }
 
@@ -371,11 +464,14 @@
  */
 TEST_P(HostapdHidlTest, RemoveAccessPointWithAcs) {
     if (!isAcsSupport_) GTEST_SKIP() << "Missing ACS support";
-    auto status_1_2 = HIDL_INVOKE(hostapd_, addAccessPoint_1_3,
-                                  getIfaceParamsWithAcs(), getPskNwParams());
+    // TODO: Use setupApIfaceAndGetName after fixing b/177483254
+    // std::string ifname = setupApIfaceAndGetName(false);
+    std::string ifname = getPrimaryWlanIfaceName();
+    auto status_1_2 =
+        HIDL_INVOKE(hostapd_, addAccessPoint_1_3, getIfaceParamsWithAcs(ifname),
+                    getPskNwParams());
     EXPECT_EQ(HostapdStatusCode::SUCCESS, status_1_2.code);
-    auto status =
-        HIDL_INVOKE(hostapd_, removeAccessPoint, getPrimaryWlanIfaceName());
+    auto status = HIDL_INVOKE(hostapd_, removeAccessPoint, ifname);
     EXPECT_EQ(
         android::hardware::wifi::hostapd::V1_0::HostapdStatusCode::SUCCESS,
         status.code);
@@ -386,11 +482,14 @@
  * Access point creation & removal should pass.
  */
 TEST_P(HostapdHidlTest, RemoveAccessPointWithoutAcs) {
-    auto status_1_2 = HIDL_INVOKE(hostapd_, addAccessPoint_1_3,
-                                  getIfaceParamsWithoutAcs(), getPskNwParams());
+    // TODO: Use setupApIfaceAndGetName after fixing b/177483254
+    // std::string ifname = setupApIfaceAndGetName(false);
+    std::string ifname = getPrimaryWlanIfaceName();
+    auto status_1_2 =
+        HIDL_INVOKE(hostapd_, addAccessPoint_1_3,
+                    getIfaceParamsWithoutAcs(ifname), getPskNwParams());
     EXPECT_EQ(HostapdStatusCode::SUCCESS, status_1_2.code);
-    auto status =
-        HIDL_INVOKE(hostapd_, removeAccessPoint, getPrimaryWlanIfaceName());
+    auto status = HIDL_INVOKE(hostapd_, removeAccessPoint, ifname);
     EXPECT_EQ(
         android::hardware::wifi::hostapd::V1_0::HostapdStatusCode::SUCCESS,
         status.code);
@@ -401,9 +500,12 @@
  * Access point creation should fail.
  */
 TEST_P(HostapdHidlTest, AddPskAccessPointWithInvalidChannel) {
+    // TODO: Use setupApIfaceAndGetName after fixing b/177483254
+    // std::string ifname = setupApIfaceAndGetName(false);
+    std::string ifname = getPrimaryWlanIfaceName();
     auto status =
         HIDL_INVOKE(hostapd_, addAccessPoint_1_3,
-                    getIfaceParamsWithInvalidChannel(), getPskNwParams());
+                    getIfaceParamsWithInvalidChannel(ifname), getPskNwParams());
     EXPECT_NE(HostapdStatusCode::SUCCESS, status.code);
 }
 
@@ -412,9 +514,12 @@
  * Access point creation should fail.
  */
 TEST_P(HostapdHidlTest, AddInvalidPskAccessPointWithoutAcs) {
+    // TODO: Use setupApIfaceAndGetName after fixing b/177483254
+    // std::string ifname = setupApIfaceAndGetName(false);
+    std::string ifname = getPrimaryWlanIfaceName();
     auto status =
-        HIDL_INVOKE(hostapd_, addAccessPoint_1_3, getIfaceParamsWithoutAcs(),
-                    getInvalidPskNwParams());
+        HIDL_INVOKE(hostapd_, addAccessPoint_1_3,
+                    getIfaceParamsWithoutAcs(ifname), getInvalidPskNwParams());
     EXPECT_NE(HostapdStatusCode::SUCCESS, status.code);
 }
 
@@ -424,9 +529,12 @@
  */
 TEST_P(HostapdHidlTest, AddInvalidSaeTransitionAccessPointWithoutAcs) {
     if (!isWpa3SaeSupport_) GTEST_SKIP() << "Missing SAE support";
-    auto status =
-        HIDL_INVOKE(hostapd_, addAccessPoint_1_3, getIfaceParamsWithoutAcs(),
-                    getInvalidSaeTransitionNwParams());
+    // TODO: Use setupApIfaceAndGetName after fixing b/177483254
+    // std::string ifname = setupApIfaceAndGetName(false);
+    std::string ifname = getPrimaryWlanIfaceName();
+    auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_3,
+                              getIfaceParamsWithoutAcs(ifname),
+                              getInvalidSaeTransitionNwParams());
     EXPECT_NE(HostapdStatusCode::SUCCESS, status.code);
 }
 
@@ -436,9 +544,12 @@
  */
 TEST_P(HostapdHidlTest, AddInvalidSaeAccessPointWithoutAcs) {
     if (!isWpa3SaeSupport_) GTEST_SKIP() << "Missing SAE support";
+    // TODO: Use setupApIfaceAndGetName after fixing b/177483254
+    // std::string ifname = setupApIfaceAndGetName(false);
+    std::string ifname = getPrimaryWlanIfaceName();
     auto status =
-        HIDL_INVOKE(hostapd_, addAccessPoint_1_3, getIfaceParamsWithoutAcs(),
-                    getInvalidSaeNwParams());
+        HIDL_INVOKE(hostapd_, addAccessPoint_1_3,
+                    getIfaceParamsWithoutAcs(ifname), getInvalidSaeNwParams());
     EXPECT_NE(HostapdStatusCode::SUCCESS, status.code);
 }
 
@@ -447,21 +558,30 @@
  * when hotspot interface available.
  */
 TEST_P(HostapdHidlTest, DisconnectClientWhenIfacAvailable) {
+    // TODO: Use setupApIfaceAndGetName after fixing b/177483254
+    // std::string ifname = setupApIfaceAndGetName(false);
+    std::string ifname = getPrimaryWlanIfaceName();
     auto status_1_2 =
-        HIDL_INVOKE(hostapd_, addAccessPoint_1_3, getIfaceParamsWithoutAcs(),
-                    getOpenNwParams());
+        HIDL_INVOKE(hostapd_, addAccessPoint_1_3,
+                    getIfaceParamsWithoutAcs(ifname), getOpenNwParams());
     EXPECT_EQ(HostapdStatusCode::SUCCESS, status_1_2.code);
 
-    status_1_2 =
-        HIDL_INVOKE(hostapd_, forceClientDisconnect, getPrimaryWlanIfaceName(),
-                    kTestZeroMacAddr, kTestDisconnectReasonCode);
+    status_1_2 = HIDL_INVOKE(hostapd_, forceClientDisconnect, ifname,
+                             kTestZeroMacAddr, kTestDisconnectReasonCode);
     EXPECT_EQ(HostapdStatusCode::FAILURE_CLIENT_UNKNOWN, status_1_2.code);
 }
 
 /**
  * AddAccessPointWithDualBandConfig should pass
  */
-// TODO: Add it after VendorHal ready & add feature support check.
+TEST_P(HostapdHidlTest, AddAccessPointWithDualBandConfig) {
+    if (!isBridgedSupport_) GTEST_SKIP() << "Missing Bridged AP support";
+    std::string ifname = setupApIfaceAndGetName(true);
+    auto status_1_2 = HIDL_INVOKE(hostapd_, addAccessPoint_1_3,
+                                  getIfaceParamsWithBridgedModeACS(ifname),
+                                  getOpenNwParams());
+    EXPECT_EQ(HostapdStatusCode::SUCCESS, status_1_2.code);
+}
 
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(HostapdHidlTest);
 INSTANTIATE_TEST_CASE_P(
diff --git a/wifi/supplicant/1.4/ISupplicantStaIfaceCallback.hal b/wifi/supplicant/1.4/ISupplicantStaIfaceCallback.hal
index efcebda..c6f05fb 100644
--- a/wifi/supplicant/1.4/ISupplicantStaIfaceCallback.hal
+++ b/wifi/supplicant/1.4/ISupplicantStaIfaceCallback.hal
@@ -20,7 +20,9 @@
 import @1.0::ISupplicantStaIfaceCallback.Hs20AnqpData;
 import @1.3::ISupplicantStaIfaceCallback;
 import @1.0::ISupplicantStaIfaceCallback.State;
+import @1.0::ISupplicantStaIfaceCallback.StatusCode;
 import @1.0::Bssid;
+import @1.0::Ssid;
 
 /**
  * Callback Interface exposed by the supplicant service
@@ -32,6 +34,19 @@
  */
 interface ISupplicantStaIfaceCallback extends @1.3::ISupplicantStaIfaceCallback {
     /**
+     *  MBO spec v1.2, 4.2.4 Table 14: MBO Association disallowed reason code attribute
+     *  values.
+     */
+    enum MboAssocDisallowedReasonCode : uint8_t {
+        RESERVED = 0,
+        UNSPECIFIED = 1,
+        MAX_NUM_STA_ASSOCIATED = 2,
+        AIR_INTERFACE_OVERLOADED = 3,
+        AUTH_SERVER_OVERLOADED = 4,
+        INSUFFICIENT_RSSI = 5,
+    };
+
+    /**
      * ANQP data for IEEE Std 802.11-2016.
      * The format of the data within these elements follows the IEEE
      * Std 802.11-2016 standard, section 9.4.5.
@@ -49,6 +64,83 @@
     };
 
     /**
+     * OceRssiBasedAssocRejectAttr is extracted from (Re-)Association response
+     * frame from an OCE AP to indicate that the AP has rejected the
+     * (Re-)Association request on the basis of insufficient RSSI.
+     * Refer OCE spec v1.0 section 4.2.2 Table 7.
+     */
+    struct OceRssiBasedAssocRejectAttr {
+        /*
+         * Delta RSSI - The difference in dB between the minimum RSSI at which
+         * the AP would accept a (Re-)Association request from the STA before
+         * Retry Delay expires and the AP's measurement of the RSSI at which the
+         * (Re-)Association request was received.
+         */
+        uint32_t deltaRssi;
+
+        /*
+         * Retry Delay - The time period in seconds for which the AP will not
+         * accept any subsequent (Re-)Association requests from the STA, unless
+         * the received RSSI has improved by Delta RSSI.
+         */
+        uint32_t retryDelayS;
+    };
+
+    /**
+     * Association Rejection related information.
+     */
+    struct AssociationRejectionData {
+        /**
+         * SSID of the AP that rejected the association.
+         */
+        Ssid ssid;
+
+        /**
+         * BSSID of the AP that rejected the association.
+         */
+        Bssid bssid;
+
+        /*
+         * 802.11 code to indicate the reject reason.
+         * Refer to section 8.4.1.9 of IEEE 802.11 spec.
+         */
+        StatusCode statusCode;
+
+        /*
+         * Flag to indicate that failure is due to timeout rather than
+         * explicit rejection response from the AP.
+         */
+        bool timedOut;
+
+        /**
+         * Flag to indicate that MboAssocDisallowedReasonCode is present
+         * in the (Re-)Association response frame.
+         */
+        bool isMboAssocDisallowedReasonCodePresent;
+
+        /**
+         * mboAssocDisallowedReason is extracted from MBO association disallowed attribute
+         * in (Re-)Association response frame to indicate that the AP is not accepting new
+         * associations.
+         * Refer MBO spec v1.2 section 4.2.4 Table 13 for the details of reason code.
+         * The value is undefined if isMboAssocDisallowedReasonCodePresent is false.
+         */
+        MboAssocDisallowedReasonCode mboAssocDisallowedReason;
+
+        /**
+         * Flag to indicate that OceRssiBasedAssocRejectAttr is present
+         * in the (Re-)Association response frame.
+         */
+        bool isOceRssiBasedAssocRejectAttrPresent;
+
+        /*
+         * OCE RSSI-based (Re-)Association rejection attribute.
+         * The contents are undefined if isOceRssiBasedAssocRejectAttrPresent is false.
+         */
+        OceRssiBasedAssocRejectAttr oceRssiBasedAssocRejectData;
+    };
+
+    /**
      * Used to indicate a Hotspot 2.0 terms and conditions acceptance is requested from the user
      * before allowing the device to get internet access.
      *
@@ -68,4 +160,12 @@
      *        All the fields in this struct must be empty if the query failed.
      */
     oneway onAnqpQueryDone_1_4(Bssid bssid, AnqpData data, Hs20AnqpData hs20Data);
+
+    /**
+     * Used to indicate an association rejection received from the AP
+     * to which the connection is being attempted.
+     *
+     * @param assocRejectData Association Rejection related information.
+     */
+    oneway onAssociationRejected_1_4(AssociationRejectionData assocRejectData);
 };
diff --git a/wifi/supplicant/1.4/vts/functional/supplicant_sta_iface_hidl_test.cpp b/wifi/supplicant/1.4/vts/functional/supplicant_sta_iface_hidl_test.cpp
index ccd469d..1794a39 100644
--- a/wifi/supplicant/1.4/vts/functional/supplicant_sta_iface_hidl_test.cpp
+++ b/wifi/supplicant/1.4/vts/functional/supplicant_sta_iface_hidl_test.cpp
@@ -232,6 +232,11 @@
         override {
         return Void();
     }
+    Return<void> onAssociationRejected_1_4(
+        const ISupplicantStaIfaceCallback::AssociationRejectionData& /* data */)
+        override {
+        return Void();
+    }
 };
 
 /*