Merge "Add gralloc tests for locking without CPU usage" into main
diff --git a/Android.bp b/Android.bp
index fc6babe..baf3291 100644
--- a/Android.bp
+++ b/Android.bp
@@ -63,8 +63,8 @@
         "libbase",
         // All the following are dependencies of any HAL definition library.
         "libcutils",
-        "liblog",
         "libhidlbase",
+        "liblog",
         "libutils",
     ],
     cflags: [
diff --git a/audio/aidl/Android.bp b/audio/aidl/Android.bp
index b67b9d2..4902497 100644
--- a/audio/aidl/Android.bp
+++ b/audio/aidl/Android.bp
@@ -44,7 +44,7 @@
         "android/hardware/audio/common/SinkMetadata.aidl",
         "android/hardware/audio/common/SourceMetadata.aidl",
     ],
-    frozen: true,
+    frozen: false,
     backend: {
         cpp: {
             enabled: true,
@@ -89,7 +89,7 @@
 }
 
 // Note: This should always be one version ahead of the last frozen version
-latest_android_hardware_audio_common = "android.hardware.audio.common-V3"
+latest_android_hardware_audio_common = "android.hardware.audio.common-V4"
 
 // Modules that depend on android.hardware.audio.common directly can include
 // the following cc_defaults to avoid explicitly managing dependency versions
@@ -198,11 +198,11 @@
         // IMPORTANT: Update latest_android_hardware_audio_core every time you
         // add the latest frozen version to versions_with_info
     ],
-    frozen: true,
+    frozen: false,
 }
 
 // Note: This should always be one version ahead of the last frozen version
-latest_android_hardware_audio_core = "android.hardware.audio.core-V2"
+latest_android_hardware_audio_core = "android.hardware.audio.core-V3"
 
 // Modules that depend on android.hardware.audio.core directly can include
 // the following cc_defaults to avoid explicitly managing dependency versions
@@ -260,11 +260,11 @@
         // IMPORTANT: Update latest_android_hardware_audio_core_sounddose every time you
         // add the latest frozen version to versions_with_info
     ],
-    frozen: true,
+    frozen: false,
 }
 
 // Note: This should always be one version ahead of the last frozen version
-latest_android_hardware_audio_core_sounddose = "android.hardware.audio.core.sounddose-V2"
+latest_android_hardware_audio_core_sounddose = "android.hardware.audio.core.sounddose-V3"
 
 // Modules that depend on android.hardware.audio.core.sounddose directly can include
 // the following cc_defaults to avoid explicitly managing dependency versions
@@ -368,11 +368,11 @@
         },
 
     ],
-    frozen: true,
+    frozen: false,
 
 }
 
-latest_android_hardware_audio_effect = "android.hardware.audio.effect-V2"
+latest_android_hardware_audio_effect = "android.hardware.audio.effect-V3"
 
 cc_defaults {
     name: "latest_android_hardware_audio_effect_ndk_shared",
diff --git a/audio/aidl/common/include/Utils.h b/audio/aidl/common/include/Utils.h
index b431340..6241f44 100644
--- a/audio/aidl/common/include/Utils.h
+++ b/audio/aidl/common/include/Utils.h
@@ -26,6 +26,7 @@
 #include <aidl/android/media/audio/common/AudioDeviceType.h>
 #include <aidl/android/media/audio/common/AudioFormatDescription.h>
 #include <aidl/android/media/audio/common/AudioInputFlags.h>
+#include <aidl/android/media/audio/common/AudioIoFlags.h>
 #include <aidl/android/media/audio/common/AudioMode.h>
 #include <aidl/android/media/audio/common/AudioOutputFlags.h>
 #include <aidl/android/media/audio/common/PcmType.h>
@@ -191,4 +192,15 @@
     return frameCountFromDurationUs(durationMs * 1000, sampleRateHz);
 }
 
+constexpr bool hasMmapFlag(const ::aidl::android::media::audio::common::AudioIoFlags& flags) {
+    return (flags.getTag() == ::aidl::android::media::audio::common::AudioIoFlags::Tag::input &&
+            isBitPositionFlagSet(
+                    flags.get<::aidl::android::media::audio::common::AudioIoFlags::Tag::input>(),
+                    ::aidl::android::media::audio::common::AudioInputFlags::MMAP_NOIRQ)) ||
+           (flags.getTag() == ::aidl::android::media::audio::common::AudioIoFlags::Tag::output &&
+            isBitPositionFlagSet(
+                    flags.get<::aidl::android::media::audio::common::AudioIoFlags::Tag::output>(),
+                    ::aidl::android::media::audio::common::AudioOutputFlags::MMAP_NOIRQ));
+}
+
 }  // namespace aidl::android::hardware::audio::common
diff --git a/audio/aidl/default/Module.cpp b/audio/aidl/default/Module.cpp
index 0d6151e..543efd1 100644
--- a/audio/aidl/default/Module.cpp
+++ b/audio/aidl/default/Module.cpp
@@ -36,6 +36,7 @@
 
 using aidl::android::hardware::audio::common::frameCountFromDurationMs;
 using aidl::android::hardware::audio::common::getFrameSizeInBytes;
+using aidl::android::hardware::audio::common::hasMmapFlag;
 using aidl::android::hardware::audio::common::isBitPositionFlagSet;
 using aidl::android::hardware::audio::common::isValidAudioMode;
 using aidl::android::hardware::audio::common::SinkMetadata;
@@ -205,35 +206,31 @@
         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
     }
     const auto& flags = portConfigIt->flags.value();
-    if ((flags.getTag() == AudioIoFlags::Tag::input &&
-         !isBitPositionFlagSet(flags.get<AudioIoFlags::Tag::input>(),
-                               AudioInputFlags::MMAP_NOIRQ)) ||
-        (flags.getTag() == AudioIoFlags::Tag::output &&
-         !isBitPositionFlagSet(flags.get<AudioIoFlags::Tag::output>(),
-                               AudioOutputFlags::MMAP_NOIRQ))) {
-        StreamContext::DebugParameters params{mDebug.streamTransientStateDelayMs,
-                                              mVendorDebug.forceTransientBurst,
-                                              mVendorDebug.forceSynchronousDrain};
-        std::shared_ptr<ISoundDose> soundDose;
-        if (!getSoundDose(&soundDose).isOk()) {
-            LOG(ERROR) << __func__ << ": could not create sound dose instance";
-            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
-        }
-        StreamContext temp(
-                std::make_unique<StreamContext::CommandMQ>(1, true /*configureEventFlagWord*/),
-                std::make_unique<StreamContext::ReplyMQ>(1, true /*configureEventFlagWord*/),
-                portConfigIt->format.value(), portConfigIt->channelMask.value(),
-                portConfigIt->sampleRate.value().value, flags, nominalLatencyMs,
-                portConfigIt->ext.get<AudioPortExt::mix>().handle,
-                std::make_unique<StreamContext::DataMQ>(frameSize * in_bufferSizeFrames),
-                asyncCallback, outEventCallback, mSoundDose.getInstance(), params);
-        if (temp.isValid()) {
-            *out_context = std::move(temp);
-        } else {
-            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
-        }
+    StreamContext::DebugParameters params{mDebug.streamTransientStateDelayMs,
+                                          mVendorDebug.forceTransientBurst,
+                                          mVendorDebug.forceSynchronousDrain};
+    std::unique_ptr<StreamContext::DataMQ> dataMQ = nullptr;
+    std::shared_ptr<IStreamCallback> streamAsyncCallback = nullptr;
+    std::shared_ptr<ISoundDose> soundDose;
+    if (!getSoundDose(&soundDose).isOk()) {
+        LOG(ERROR) << __func__ << ": could not create sound dose instance";
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+    }
+    if (!hasMmapFlag(flags)) {
+        dataMQ = std::make_unique<StreamContext::DataMQ>(frameSize * in_bufferSizeFrames);
+        streamAsyncCallback = asyncCallback;
+    }
+    StreamContext temp(
+            std::make_unique<StreamContext::CommandMQ>(1, true /*configureEventFlagWord*/),
+            std::make_unique<StreamContext::ReplyMQ>(1, true /*configureEventFlagWord*/),
+            portConfigIt->format.value(), portConfigIt->channelMask.value(),
+            portConfigIt->sampleRate.value().value, flags, nominalLatencyMs,
+            portConfigIt->ext.get<AudioPortExt::mix>().handle, std::move(dataMQ),
+            streamAsyncCallback, outEventCallback, mSoundDose.getInstance(), params);
+    if (temp.isValid()) {
+        *out_context = std::move(temp);
     } else {
-        // TODO: Implement simulation of MMAP buffer allocation
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
     }
     return ndk::ScopedAStatus::ok();
 }
@@ -373,6 +370,13 @@
     return kLatencyMs;
 }
 
+ndk::ScopedAStatus Module::createMmapBuffer(
+        const ::aidl::android::hardware::audio::core::StreamContext& context __unused,
+        ::aidl::android::hardware::audio::core::StreamDescriptor* desc __unused) {
+    LOG(ERROR) << __func__ << ": " << mType << ": is not implemented";
+    return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
 std::vector<AudioRoute*> Module::getAudioRoutesForAudioPortImpl(int32_t portId) {
     std::vector<AudioRoute*> result;
     auto& routes = getConfig().routes;
@@ -866,6 +870,9 @@
     RETURN_STATUS_IF_ERROR(createStreamContext(in_args.portConfigId, in_args.bufferSizeFrames,
                                                nullptr, nullptr, &context));
     context.fillDescriptor(&_aidl_return->desc);
+    if (hasMmapFlag(context.getFlags())) {
+        RETURN_STATUS_IF_ERROR(createMmapBuffer(context, &_aidl_return->desc));
+    }
     std::shared_ptr<StreamIn> stream;
     RETURN_STATUS_IF_ERROR(createInputStream(std::move(context), in_args.sinkMetadata,
                                              getMicrophoneInfos(), &stream));
@@ -913,6 +920,9 @@
                                                isNonBlocking ? in_args.callback : nullptr,
                                                in_args.eventCallback, &context));
     context.fillDescriptor(&_aidl_return->desc);
+    if (hasMmapFlag(context.getFlags())) {
+        RETURN_STATUS_IF_ERROR(createMmapBuffer(context, &_aidl_return->desc));
+    }
     std::shared_ptr<StreamOut> stream;
     RETURN_STATUS_IF_ERROR(createOutputStream(std::move(context), in_args.sourceMetadata,
                                               in_args.offloadInfo, &stream));
diff --git a/audio/aidl/default/Stream.cpp b/audio/aidl/default/Stream.cpp
index 31b0645..8f5e839 100644
--- a/audio/aidl/default/Stream.cpp
+++ b/audio/aidl/default/Stream.cpp
@@ -30,6 +30,7 @@
 using aidl::android::hardware::audio::common::AudioOffloadMetadata;
 using aidl::android::hardware::audio::common::getChannelCount;
 using aidl::android::hardware::audio::common::getFrameSizeInBytes;
+using aidl::android::hardware::audio::common::hasMmapFlag;
 using aidl::android::hardware::audio::common::isBitPositionFlagSet;
 using aidl::android::hardware::audio::common::SinkMetadata;
 using aidl::android::hardware::audio::common::SourceMetadata;
@@ -84,7 +85,7 @@
         LOG(ERROR) << "frame size is invalid";
         return false;
     }
-    if (mDataMQ && !mDataMQ->isValid()) {
+    if (!hasMmapFlag(mFlags) && mDataMQ && !mDataMQ->isValid()) {
         LOG(ERROR) << "data FMQ is invalid";
         return false;
     }
@@ -116,17 +117,19 @@
 std::string StreamWorkerCommonLogic::init() {
     if (mContext->getCommandMQ() == nullptr) return "Command MQ is null";
     if (mContext->getReplyMQ() == nullptr) return "Reply MQ is null";
-    StreamContext::DataMQ* const dataMQ = mContext->getDataMQ();
-    if (dataMQ == nullptr) return "Data MQ is null";
-    if (sizeof(DataBufferElement) != dataMQ->getQuantumSize()) {
-        return "Unexpected Data MQ quantum size: " + std::to_string(dataMQ->getQuantumSize());
-    }
-    mDataBufferSize = dataMQ->getQuantumCount() * dataMQ->getQuantumSize();
-    mDataBuffer.reset(new (std::nothrow) DataBufferElement[mDataBufferSize]);
-    if (mDataBuffer == nullptr) {
-        return "Failed to allocate data buffer for element count " +
-               std::to_string(dataMQ->getQuantumCount()) +
-               ", size in bytes: " + std::to_string(mDataBufferSize);
+    if (!hasMmapFlag(mContext->getFlags())) {
+        StreamContext::DataMQ* const dataMQ = mContext->getDataMQ();
+        if (dataMQ == nullptr) return "Data MQ is null";
+        if (sizeof(DataBufferElement) != dataMQ->getQuantumSize()) {
+            return "Unexpected Data MQ quantum size: " + std::to_string(dataMQ->getQuantumSize());
+        }
+        mDataBufferSize = dataMQ->getQuantumCount() * dataMQ->getQuantumSize();
+        mDataBuffer.reset(new (std::nothrow) DataBufferElement[mDataBufferSize]);
+        if (mDataBuffer == nullptr) {
+            return "Failed to allocate data buffer for element count " +
+                   std::to_string(dataMQ->getQuantumCount()) +
+                   ", size in bytes: " + std::to_string(mDataBufferSize);
+        }
     }
     if (::android::status_t status = mDriver->init(); status != STATUS_OK) {
         return "Failed to initialize the driver: " + std::to_string(status);
@@ -136,16 +139,26 @@
 
 void StreamWorkerCommonLogic::populateReply(StreamDescriptor::Reply* reply,
                                             bool isConnected) const {
+    static const StreamDescriptor::Position kUnknownPosition = {
+            .frames = StreamDescriptor::Position::UNKNOWN,
+            .timeNs = StreamDescriptor::Position::UNKNOWN};
     reply->status = STATUS_OK;
     if (isConnected) {
         reply->observable.frames = mContext->getFrameCount();
         reply->observable.timeNs = ::android::uptimeNanos();
-        if (auto status = mDriver->refinePosition(&reply->observable); status == ::android::OK) {
-            return;
+        if (auto status = mDriver->refinePosition(&reply->observable); status != ::android::OK) {
+            reply->observable = kUnknownPosition;
+        }
+    } else {
+        reply->observable = reply->hardware = kUnknownPosition;
+    }
+    if (hasMmapFlag(mContext->getFlags())) {
+        if (auto status = mDriver->getMmapPositionAndLatency(&reply->hardware, &reply->latencyMs);
+            status != ::android::OK) {
+            reply->hardware = kUnknownPosition;
+            reply->latencyMs = StreamDescriptor::LATENCY_UNKNOWN;
         }
     }
-    reply->observable.frames = StreamDescriptor::Position::UNKNOWN;
-    reply->observable.timeNs = StreamDescriptor::Position::UNKNOWN;
 }
 
 void StreamWorkerCommonLogic::populateReplyWrongState(
@@ -224,7 +237,9 @@
                     mState == StreamDescriptor::State::ACTIVE ||
                     mState == StreamDescriptor::State::PAUSED ||
                     mState == StreamDescriptor::State::DRAINING) {
-                    if (!read(fmqByteCount, &reply)) {
+                    if (hasMmapFlag(mContext->getFlags())) {
+                        populateReply(&reply, mIsConnected);
+                    } else if (!read(fmqByteCount, &reply)) {
                         mState = StreamDescriptor::State::ERROR;
                     }
                     if (mState == StreamDescriptor::State::IDLE ||
@@ -470,7 +485,9 @@
                 if (mState != StreamDescriptor::State::ERROR &&
                     mState != StreamDescriptor::State::TRANSFERRING &&
                     mState != StreamDescriptor::State::TRANSFER_PAUSED) {
-                    if (!write(fmqByteCount, &reply)) {
+                    if (hasMmapFlag(mContext->getFlags())) {
+                        populateReply(&reply, mIsConnected);
+                    } else if (!write(fmqByteCount, &reply)) {
                         mState = StreamDescriptor::State::ERROR;
                     }
                     std::shared_ptr<IStreamCallback> asyncCallback = mContext->getAsyncCallback();
@@ -657,6 +674,7 @@
         const std::shared_ptr<StreamCommonInterface>& delegate) {
     mCommon = ndk::SharedRefBase::make<StreamCommonDelegator>(delegate);
     if (!mWorker->start()) {
+        LOG(ERROR) << __func__ << ": Worker start error: " << mWorker->getError();
         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
     }
     if (auto flags = getContext().getFlags();
diff --git a/audio/aidl/default/android.hardware.audio.service-aidl.xml b/audio/aidl/default/android.hardware.audio.service-aidl.xml
index 5278e4f..27f48e2 100644
--- a/audio/aidl/default/android.hardware.audio.service-aidl.xml
+++ b/audio/aidl/default/android.hardware.audio.service-aidl.xml
@@ -1,39 +1,39 @@
 <manifest version="1.0" type="device">
   <hal format="aidl">
     <name>android.hardware.audio.core</name>
-    <version>2</version>
+    <version>3</version>
     <fqname>IModule/default</fqname>
   </hal>
   <hal format="aidl">
     <name>android.hardware.audio.core</name>
-    <version>2</version>
+    <version>3</version>
     <fqname>IModule/r_submix</fqname>
   </hal>
   <hal format="aidl">
     <name>android.hardware.audio.core</name>
-    <version>2</version>
+    <version>3</version>
     <fqname>IModule/bluetooth</fqname>
   </hal>
   <hal format="aidl">
     <name>android.hardware.audio.core</name>
-    <version>2</version>
+    <version>3</version>
     <fqname>IConfig/default</fqname>
   </hal>
   <!-- Uncomment when these modules present in the configuration
   <hal format="aidl">
     <name>android.hardware.audio.core</name>
-    <version>1</version>
+    <version>3</version>
     <fqname>IModule/stub</fqname>
   </hal>
   <hal format="aidl">
     <name>android.hardware.audio.core</name>
-    <version>1</version>
+    <version>3</version>
     <fqname>IModule/usb</fqname>
   </hal>
   -->
   <hal format="aidl">
     <name>android.hardware.audio.effect</name>
-    <version>2</version>
+    <version>3</version>
     <fqname>IFactory/default</fqname>
   </hal>
 </manifest>
diff --git a/audio/aidl/default/include/core-impl/Module.h b/audio/aidl/default/include/core-impl/Module.h
index a326217..00eeb4e 100644
--- a/audio/aidl/default/include/core-impl/Module.h
+++ b/audio/aidl/default/include/core-impl/Module.h
@@ -205,6 +205,9 @@
     virtual std::unique_ptr<Configuration> initializeConfig();
     virtual int32_t getNominalLatencyMs(
             const ::aidl::android::media::audio::common::AudioPortConfig& portConfig);
+    virtual ndk::ScopedAStatus createMmapBuffer(
+            const ::aidl::android::hardware::audio::core::StreamContext& context,
+            ::aidl::android::hardware::audio::core::StreamDescriptor* desc);
 
     // Utility and helper functions accessible to subclasses.
     static int32_t calculateBufferSizeFrames(int32_t latencyMs, int32_t sampleRateHz) {
diff --git a/audio/aidl/default/include/core-impl/Stream.h b/audio/aidl/default/include/core-impl/Stream.h
index 21e63f9..6b45866 100644
--- a/audio/aidl/default/include/core-impl/Stream.h
+++ b/audio/aidl/default/include/core-impl/Stream.h
@@ -177,6 +177,11 @@
     virtual ::android::status_t refinePosition(StreamDescriptor::Position* /*position*/) {
         return ::android::OK;
     }
+    // Implement 'getMmapPositionAndLatency' is necessary if driver can support mmap stream.
+    virtual ::android::status_t getMmapPositionAndLatency(StreamDescriptor::Position* /*position*/,
+                                                          int32_t* /*latency*/) {
+        return ::android::OK;
+    }
     virtual void shutdown() = 0;  // This function is only called once.
 };
 
@@ -241,6 +246,7 @@
     virtual bool start() = 0;
     virtual pid_t getTid() = 0;
     virtual void stop() = 0;
+    virtual std::string getError() = 0;
 };
 
 template <class WorkerLogic>
@@ -260,6 +266,7 @@
     }
     pid_t getTid() override { return WorkerImpl::getTid(); }
     void stop() override { return WorkerImpl::stop(); }
+    std::string getError() override { return WorkerImpl::getError(); }
 };
 
 class StreamInWorkerLogic : public StreamWorkerCommonLogic {
diff --git a/audio/aidl/sounddose/Android.bp b/audio/aidl/sounddose/Android.bp
index de3ed64..8b2d74b 100644
--- a/audio/aidl/sounddose/Android.bp
+++ b/audio/aidl/sounddose/Android.bp
@@ -56,11 +56,11 @@
         // IMPORTANT: Update latest_android_hardware_audio_sounddose every time you
         // add the latest frozen version to versions_with_info
     ],
-    frozen: true,
+    frozen: false,
 }
 
 // Note: This should always be one version ahead of the last frozen version
-latest_android_hardware_audio_sounddose = "android.hardware.audio.sounddose-V2"
+latest_android_hardware_audio_sounddose = "android.hardware.audio.sounddose-V3"
 
 // Modules that depend on android.hardware.audio.sounddose directly can include
 // the following cc_defaults to avoid explicitly managing dependency versions
diff --git a/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp b/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
index d576c7c..bbc4caf 100644
--- a/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
@@ -56,6 +56,7 @@
 using namespace android;
 using aidl::android::hardware::audio::common::AudioOffloadMetadata;
 using aidl::android::hardware::audio::common::getChannelCount;
+using aidl::android::hardware::audio::common::hasMmapFlag;
 using aidl::android::hardware::audio::common::isAnyBitPositionFlagSet;
 using aidl::android::hardware::audio::common::isBitPositionFlagSet;
 using aidl::android::hardware::audio::common::isTelephonyDeviceType;
@@ -637,19 +638,39 @@
           mCommandMQ(new CommandMQ(descriptor.command)),
           mReplyMQ(new ReplyMQ(descriptor.reply)),
           mBufferSizeFrames(descriptor.bufferSizeFrames),
-          mDataMQ(maybeCreateDataMQ(descriptor)) {}
+          mDataMQ(maybeCreateDataMQ(descriptor)),
+          mIsMmapped(isMmapped(descriptor)),
+          mSharedMemoryFd(maybeGetMmapFd(descriptor)) {
+        if (isMmapped()) {
+            mSharedMemory = (int8_t*)mmap(nullptr, getBufferSizeBytes(), PROT_READ | PROT_WRITE,
+                                          MAP_SHARED, mSharedMemoryFd, 0);
+            if (mSharedMemory == MAP_FAILED) {
+                PLOG(ERROR) << __func__ << ": mmap() failed.";
+                mSharedMemory = nullptr;
+            }
+        }
+    }
+    ~StreamContext() {
+        if (mSharedMemory != nullptr) {
+            munmap(mSharedMemory, getBufferSizeBytes());
+        }
+    }
     void checkIsValid() const {
         EXPECT_NE(0UL, mFrameSizeBytes);
         ASSERT_NE(nullptr, mCommandMQ);
         EXPECT_TRUE(mCommandMQ->isValid());
         ASSERT_NE(nullptr, mReplyMQ);
         EXPECT_TRUE(mReplyMQ->isValid());
-        if (mDataMQ != nullptr) {
-            EXPECT_TRUE(mDataMQ->isValid());
-            EXPECT_GE(mDataMQ->getQuantumCount() * mDataMQ->getQuantumSize(),
-                      mFrameSizeBytes * mBufferSizeFrames)
-                    << "Data MQ actual buffer size is "
-                       "less than the buffer size as specified by the descriptor";
+        if (isMmapped()) {
+            ASSERT_NE(nullptr, mSharedMemory);
+        } else {
+            if (mDataMQ != nullptr) {
+                EXPECT_TRUE(mDataMQ->isValid());
+                EXPECT_GE(mDataMQ->getQuantumCount() * mDataMQ->getQuantumSize(),
+                          mFrameSizeBytes * mBufferSizeFrames)
+                        << "Data MQ actual buffer size is "
+                           "less than the buffer size as specified by the descriptor";
+            }
         }
     }
     size_t getBufferSizeBytes() const { return mFrameSizeBytes * mBufferSizeFrames; }
@@ -658,6 +679,8 @@
     DataMQ* getDataMQ() const { return mDataMQ.get(); }
     size_t getFrameSizeBytes() const { return mFrameSizeBytes; }
     ReplyMQ* getReplyMQ() const { return mReplyMQ.get(); }
+    bool isMmapped() const { return mIsMmapped; }
+    int8_t* getMmapMemory() const { return mSharedMemory; }
 
   private:
     static std::unique_ptr<DataMQ> maybeCreateDataMQ(const StreamDescriptor& descriptor) {
@@ -667,12 +690,26 @@
         }
         return nullptr;
     }
+    static bool isMmapped(const StreamDescriptor& descriptor) {
+        using Tag = StreamDescriptor::AudioBuffer::Tag;
+        return descriptor.audio.getTag() == Tag::mmap;
+    }
+    static int32_t maybeGetMmapFd(const StreamDescriptor& descriptor) {
+        using Tag = StreamDescriptor::AudioBuffer::Tag;
+        if (descriptor.audio.getTag() == Tag::mmap) {
+            return descriptor.audio.get<Tag::mmap>().sharedMemory.fd.get();
+        }
+        return -1;
+    }
 
     const size_t mFrameSizeBytes;
     std::unique_ptr<CommandMQ> mCommandMQ;
     std::unique_ptr<ReplyMQ> mReplyMQ;
     const size_t mBufferSizeFrames;
     std::unique_ptr<DataMQ> mDataMQ;
+    const bool mIsMmapped;
+    const int32_t mSharedMemoryFd;
+    int8_t* mSharedMemory = nullptr;
 };
 
 struct StreamEventReceiver {
@@ -868,12 +905,15 @@
           mDataMQ(context.getDataMQ()),
           mData(context.getBufferSizeBytes()),
           mDriver(driver),
-          mEventReceiver(eventReceiver) {}
+          mEventReceiver(eventReceiver),
+          mIsMmapped(context.isMmapped()),
+          mSharedMemory(context.getMmapMemory()) {}
     StreamContext::CommandMQ* getCommandMQ() const { return mCommandMQ; }
     StreamContext::ReplyMQ* getReplyMQ() const { return mReplyMQ; }
     StreamContext::DataMQ* getDataMQ() const { return mDataMQ; }
     StreamLogicDriver* getDriver() const { return mDriver; }
     StreamEventReceiver* getEventReceiver() const { return mEventReceiver; }
+    bool isMmapped() const { return mIsMmapped; }
 
     std::string init() override {
         LOG(DEBUG) << __func__;
@@ -914,6 +954,22 @@
         LOG(ERROR) << __func__ << ": writing of " << mData.size() << " bytes to MQ failed";
         return false;
     }
+    bool readDataFromMmap(size_t readCount) {
+        if (mSharedMemory != nullptr) {
+            std::memcpy(mData.data(), mSharedMemory, readCount);
+            return true;
+        }
+        LOG(ERROR) << __func__ << ": reading of " << readCount << " bytes from mmap failed";
+        return false;
+    }
+    bool writeDataToMmap() {
+        if (mSharedMemory != nullptr) {
+            std::memcpy(mSharedMemory, mData.data(), mData.size());
+            return true;
+        }
+        LOG(ERROR) << __func__ << ": writing of " << mData.size() << " bytes to mmap failed";
+        return false;
+    }
 
   private:
     StreamContext::CommandMQ* mCommandMQ;
@@ -923,6 +979,8 @@
     StreamLogicDriver* const mDriver;
     StreamEventReceiver* const mEventReceiver;
     int mLastEventSeq = StreamEventReceiver::kEventSeqInit;
+    const bool mIsMmapped;
+    int8_t* mSharedMemory = nullptr;
 };
 
 class StreamReaderLogic : public StreamCommonLogic {
@@ -970,7 +1028,8 @@
                        << ": received invalid byte count in the reply: " << reply.fmqByteCount;
             return Status::ABORT;
         }
-        if (static_cast<size_t>(reply.fmqByteCount) != getDataMQ()->availableToRead()) {
+        if (!isMmapped() &&
+            static_cast<size_t>(reply.fmqByteCount) != getDataMQ()->availableToRead()) {
             LOG(ERROR) << __func__
                        << ": the byte count in the reply is not the same as the amount of "
                        << "data available in the MQ: " << reply.fmqByteCount
@@ -991,8 +1050,10 @@
             return Status::ABORT;
         }
         const bool acceptedReply = getDriver()->processValidReply(reply);
-        if (const size_t readCount = getDataMQ()->availableToRead(); readCount > 0) {
-            if (readDataFromMQ(readCount)) {
+        if (const size_t readCount =
+                    !isMmapped() ? getDataMQ()->availableToRead() : reply.fmqByteCount;
+            readCount > 0) {
+            if (isMmapped() ? readDataFromMmap(readCount) : readDataFromMQ(readCount)) {
                 goto checkAcceptedReply;
             }
             LOG(ERROR) << __func__ << ": reading of " << readCount << " data bytes from MQ failed";
@@ -1028,8 +1089,10 @@
             LOG(ERROR) << __func__ << ": no next command";
             return Status::ABORT;
         }
-        if (actualSize != 0 && !writeDataToMQ()) {
-            return Status::ABORT;
+        if (actualSize != 0) {
+            if (isMmapped() ? !writeDataToMmap() : !writeDataToMQ()) {
+                return Status::ABORT;
+            }
         }
         LOG(DEBUG) << "Writing command: " << command.toString();
         if (!getCommandMQ()->writeBlocking(&command, 1)) {
@@ -1058,7 +1121,7 @@
             return Status::ABORT;
         }
         // It is OK for the implementation to leave data in the MQ when the stream is paused.
-        if (reply.state != StreamDescriptor::State::PAUSED &&
+        if (!isMmapped() && reply.state != StreamDescriptor::State::PAUSED &&
             getDataMQ()->availableToWrite() != getDataMQ()->getQuantumCount()) {
             LOG(ERROR) << __func__ << ": the HAL module did not consume all data from the data MQ: "
                        << "available to write " << getDataMQ()->availableToWrite()
@@ -2904,15 +2967,24 @@
 
 class StreamLogicDefaultDriver : public StreamLogicDriver {
   public:
-    StreamLogicDefaultDriver(std::shared_ptr<StateSequence> commands, size_t frameSizeBytes)
-        : mCommands(commands), mFrameSizeBytes(frameSizeBytes) {
+    StreamLogicDefaultDriver(std::shared_ptr<StateSequence> commands, size_t frameSizeBytes,
+                             bool isMmap)
+        : mCommands(commands), mFrameSizeBytes(frameSizeBytes), mIsMmap(isMmap) {
         mCommands->rewind();
     }
 
-    // The three methods below is intended to be called after the worker
+    // The five methods below is intended to be called after the worker
     // thread has joined, thus no extra synchronization is needed.
     bool hasObservablePositionIncrease() const { return mObservablePositionIncrease; }
-    bool hasRetrogradeObservablePosition() const { return mRetrogradeObservablePosition; }
+    bool hasObservableRetrogradePosition() const { return mRetrogradeObservablePosition; }
+    bool hasHardwarePositionIncrease() const {
+        // For non-MMap, always return true to pass the validation.
+        return mIsMmap ? mHardwarePositionIncrease : true;
+    }
+    bool hasHardwareRetrogradePosition() const {
+        // For non-MMap, always return false to pass the validation.
+        return mIsMmap ? mRetrogradeHardwarePosition : false;
+    }
     std::string getUnexpectedStateTransition() const { return mUnexpectedTransition; }
 
     bool done() override { return mCommands->done(); }
@@ -2940,14 +3012,24 @@
     bool interceptRawReply(const StreamDescriptor::Reply&) override { return false; }
     bool processValidReply(const StreamDescriptor::Reply& reply) override {
         if (reply.observable.frames != StreamDescriptor::Position::UNKNOWN) {
-            if (mPreviousFrames.has_value()) {
-                if (reply.observable.frames > mPreviousFrames.value()) {
+            if (mPreviousObservableFrames.has_value()) {
+                if (reply.observable.frames > mPreviousObservableFrames.value()) {
                     mObservablePositionIncrease = true;
-                } else if (reply.observable.frames < mPreviousFrames.value()) {
+                } else if (reply.observable.frames < mPreviousObservableFrames.value()) {
                     mRetrogradeObservablePosition = true;
                 }
             }
-            mPreviousFrames = reply.observable.frames;
+            mPreviousObservableFrames = reply.observable.frames;
+        }
+        if (mIsMmap) {
+            if (mPreviousHardwareFrames.has_value()) {
+                if (reply.hardware.frames > mPreviousHardwareFrames.value()) {
+                    mHardwarePositionIncrease = true;
+                } else if (reply.hardware.frames < mPreviousHardwareFrames.value()) {
+                    mRetrogradeHardwarePosition = true;
+                }
+            }
+            mPreviousHardwareFrames = reply.hardware.frames;
         }
 
         auto expected = mCommands->getExpectedStates();
@@ -2974,10 +3056,14 @@
   protected:
     std::shared_ptr<StateSequence> mCommands;
     const size_t mFrameSizeBytes;
+    const bool mIsMmap;
     std::optional<StreamDescriptor::State> mPreviousState;
-    std::optional<int64_t> mPreviousFrames;
+    std::optional<int64_t> mPreviousObservableFrames;
     bool mObservablePositionIncrease = false;
     bool mRetrogradeObservablePosition = false;
+    std::optional<int64_t> mPreviousHardwareFrames;
+    bool mHardwarePositionIncrease = false;
+    bool mRetrogradeHardwarePosition = false;
     std::string mUnexpectedTransition;
 };
 
@@ -2988,8 +3074,8 @@
 static bool skipStreamIoTestForMixPortConfig(const AudioPortConfig& portConfig) {
     return (portConfig.flags.value().getTag() == AudioIoFlags::input &&
             isAnyBitPositionFlagSet(portConfig.flags.value().template get<AudioIoFlags::input>(),
-                                    {AudioInputFlags::MMAP_NOIRQ, AudioInputFlags::VOIP_TX,
-                                     AudioInputFlags::HW_HOTWORD, AudioInputFlags::HOTWORD_TAP})) ||
+                                    {AudioInputFlags::VOIP_TX, AudioInputFlags::HW_HOTWORD,
+                                     AudioInputFlags::HOTWORD_TAP})) ||
            (portConfig.flags.value().getTag() == AudioIoFlags::output &&
             isAnyBitPositionFlagSet(
                     portConfig.flags.value().template get<AudioIoFlags::output>(),
@@ -3029,8 +3115,8 @@
 
     void StartWorkerToSendBurstCommands() {
         const StreamContext* context = mStream->getStreamContext();
-        mWorkerDriver = std::make_unique<StreamLogicDefaultDriver>(makeBurstCommands(mIsSync),
-                                                                   context->getFrameSizeBytes());
+        mWorkerDriver = std::make_unique<StreamLogicDefaultDriver>(
+                makeBurstCommands(mIsSync), context->getFrameSizeBytes(), context->isMmapped());
         mWorker = std::make_unique<typename IOTraits<Stream>::Worker>(
                 *context, mWorkerDriver.get(), mStream->getStreamEventReceiver());
         LOG(DEBUG) << __func__ << ": starting " << IOTraits<Stream>::directionStr << " worker...";
@@ -3047,10 +3133,13 @@
         EXPECT_FALSE(mWorker->hasError()) << mWorker->getError();
         EXPECT_EQ("", mWorkerDriver->getUnexpectedStateTransition());
         if (validatePosition) {
-            if (IOTraits<Stream>::is_input) {
+            if (IOTraits<Stream>::is_input &&
+                !mStream->getStreamContext()->isMmapped() /*TODO(b/274456992) remove*/) {
                 EXPECT_TRUE(mWorkerDriver->hasObservablePositionIncrease());
+                EXPECT_TRUE(mWorkerDriver->hasHardwarePositionIncrease());
             }
-            EXPECT_FALSE(mWorkerDriver->hasRetrogradeObservablePosition());
+            EXPECT_FALSE(mWorkerDriver->hasObservableRetrogradePosition());
+            EXPECT_FALSE(mWorkerDriver->hasHardwareRetrogradePosition());
         }
         mWorker.reset();
         mWorkerDriver.reset();
@@ -3984,7 +4073,7 @@
         }
     }
 
-    bool ValidateObservablePosition(const AudioDevice& device) {
+    bool ValidatePosition(const AudioDevice& device) {
         return !isTelephonyDeviceType(device.type.type);
     }
 
@@ -3998,7 +4087,8 @@
         if (skipStreamIoTestForDevice(stream.getDevice())) return;
         ASSERT_EQ("", stream.skipTestReason());
         StreamLogicDefaultDriver driver(commandsAndStates,
-                                        stream.getStreamContext()->getFrameSizeBytes());
+                                        stream.getStreamContext()->getFrameSizeBytes(),
+                                        stream.getStreamContext()->isMmapped());
         typename IOTraits<Stream>::Worker worker(*stream.getStreamContext(), &driver,
                                                  stream.getStreamEventReceiver());
 
@@ -4008,11 +4098,14 @@
         worker.join();
         EXPECT_FALSE(worker.hasError()) << worker.getError();
         EXPECT_EQ("", driver.getUnexpectedStateTransition());
-        if (ValidateObservablePosition(stream.getDevice())) {
-            if (validatePositionIncrease) {
+        if (ValidatePosition(stream.getDevice())) {
+            if (validatePositionIncrease &&
+                !stream.getStreamContext()->isMmapped() /*TODO(b/274456992) remove*/) {
                 EXPECT_TRUE(driver.hasObservablePositionIncrease());
+                EXPECT_TRUE(driver.hasHardwarePositionIncrease());
             }
-            EXPECT_FALSE(driver.hasRetrogradeObservablePosition());
+            EXPECT_FALSE(driver.hasObservableRetrogradePosition());
+            EXPECT_FALSE(driver.hasHardwareRetrogradePosition());
         }
     }
 
@@ -4028,7 +4121,8 @@
         ASSERT_EQ("", stream.skipTestReason());
         ASSERT_NO_FATAL_FAILURE(stream.TeardownPatchSetUpStream(module.get()));
         StreamLogicDefaultDriver driver(commandsAndStates,
-                                        stream.getStreamContext()->getFrameSizeBytes());
+                                        stream.getStreamContext()->getFrameSizeBytes(),
+                                        stream.getStreamContext()->isMmapped());
         typename IOTraits<Stream>::Worker worker(*stream.getStreamContext(), &driver,
                                                  stream.getStreamEventReceiver());
         ASSERT_NO_FATAL_FAILURE(stream.ReconnectPatch(module.get()));
@@ -4039,11 +4133,14 @@
         worker.join();
         EXPECT_FALSE(worker.hasError()) << worker.getError();
         EXPECT_EQ("", driver.getUnexpectedStateTransition());
-        if (ValidateObservablePosition(stream.getDevice())) {
-            if (validatePositionIncrease) {
+        if (ValidatePosition(stream.getDevice())) {
+            if (validatePositionIncrease &&
+                !stream.getStreamContext()->isMmapped() /*TODO(b/274456992) remove*/) {
                 EXPECT_TRUE(driver.hasObservablePositionIncrease());
+                EXPECT_TRUE(driver.hasHardwarePositionIncrease());
             }
-            EXPECT_FALSE(driver.hasRetrogradeObservablePosition());
+            EXPECT_FALSE(driver.hasObservableRetrogradePosition());
+            EXPECT_FALSE(driver.hasHardwareRetrogradePosition());
         }
     }
 };
diff --git a/audio/aidl/vts/VtsHalAudioTargetTestTemplate.xml b/audio/aidl/vts/VtsHalAudioTargetTestTemplate.xml
index c92e852..4170b4c 100644
--- a/audio/aidl/vts/VtsHalAudioTargetTestTemplate.xml
+++ b/audio/aidl/vts/VtsHalAudioTargetTestTemplate.xml
@@ -33,6 +33,6 @@
     <test class="com.android.tradefed.testtype.GTest" >
         <option name="native-test-device-path" value="/data/local/tmp" />
         <option name="module-name" value="{MODULE}" />
-        <option name="native-test-timeout" value="10m" />
+        <option name="native-test-timeout" value="30m" />
     </test>
 </configuration>
diff --git a/audio/aidl/vts/VtsHalEnvironmentalReverbTargetTest.cpp b/audio/aidl/vts/VtsHalEnvironmentalReverbTargetTest.cpp
index 5fe27f6..e31aae6 100644
--- a/audio/aidl/vts/VtsHalEnvironmentalReverbTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalEnvironmentalReverbTargetTest.cpp
@@ -17,6 +17,7 @@
 #define LOG_TAG "VtsHalEnvironmentalReverbTest"
 #include <android-base/logging.h>
 #include <audio_utils/power.h>
+#include <audio_utils/primitives.h>
 #include <system/audio.h>
 #include <numeric>
 
@@ -49,6 +50,8 @@
 
 static const TagVectorPair kDiffusionParam = {EnvironmentalReverb::diffusionPm,
                                               {200, 400, 600, 800, 1000}};
+static const TagVectorPair kDensityParam = {EnvironmentalReverb::densityPm,
+                                            {0, 200, 400, 600, 800, 1000}};
 
 static const std::vector<TagValuePair> kParamsMinimumValue = {
         {EnvironmentalReverb::roomLevelMb, kMinRoomLevel},
@@ -350,8 +353,14 @@
         mInput.resize(kBufferSize);
         generateSineWaveInput(mInput);
     }
-    void SetUp() override { SetUpReverb(); }
-    void TearDown() override { TearDownReverb(); }
+    void SetUp() override {
+        SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
+        SetUpReverb();
+    }
+    void TearDown() override {
+        SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
+        TearDownReverb();
+    }
 
     void assertEnergyIncreasingWithParameter(bool bypass) {
         createEnvParam(EnvironmentalReverb::bypass, bypass);
@@ -415,12 +424,16 @@
         std::tie(mTag, mValue) = std::get<TAG_VALUE_PAIR>(GetParam());
     }
     void SetUp() override {
+        SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
         SetUpReverb();
         createEnvParam(EnvironmentalReverb::roomLevelMb, kMinRoomLevel);
         ASSERT_NO_FATAL_FAILURE(
                 setAndVerifyParam(EX_NONE, mEnvParam, EnvironmentalReverb::roomLevelMb));
     }
-    void TearDown() override { TearDownReverb(); }
+    void TearDown() override {
+        SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
+        TearDownReverb();
+    }
 
     EnvironmentalReverb::Tag mTag;
     int mValue;
@@ -466,8 +479,14 @@
         mInput.resize(kBufferSize);
         generateSineWaveInput(mInput);
     }
-    void SetUp() override { SetUpReverb(); }
-    void TearDown() override { TearDownReverb(); }
+    void SetUp() override {
+        SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
+        SetUpReverb();
+    }
+    void TearDown() override {
+        SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
+        TearDownReverb();
+    }
 
     float getMean(std::vector<float>& buffer) {
         return std::accumulate(buffer.begin(), buffer.end(), 0.0) / buffer.size();
@@ -475,9 +494,7 @@
 
     float getVariance(std::vector<float>& buffer) {
         if (isAuxiliary()) {
-            for (size_t i = 0; i < buffer.size(); i++) {
-                buffer[i] += mInput[i];
-            }
+            accumulate_float(buffer.data(), mInput.data(), buffer.size());
         }
         float mean = getMean(buffer);
         float squaredDeltas =
@@ -524,6 +541,78 @@
 
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EnvironmentalReverbDiffusionTest);
 
+enum ParamDensityTest { DESCRIPTOR, TAG_DENSITY_VALUE, PARAM_DENSITY_VALUE, IS_INPUT_MUTE };
+
+class EnvironmentalReverbDensityTest
+    : public ::testing::TestWithParam<std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>,
+                                                 EnvironmentalReverb::Tag, int, bool>>,
+      public EnvironmentalReverbHelper {
+  public:
+    EnvironmentalReverbDensityTest() : EnvironmentalReverbHelper(std::get<DESCRIPTOR>(GetParam())) {
+        mTag = std::get<TAG_DENSITY_VALUE>(GetParam());
+        mParamValues = std::get<PARAM_DENSITY_VALUE>(GetParam());
+        mIsInputMute = (std::get<IS_INPUT_MUTE>(GetParam()));
+        mInput.resize(kBufferSize);
+        if (mIsInputMute) {
+            std::fill(mInput.begin(), mInput.end(), 0);
+        } else {
+            generateSineWaveInput(mInput);
+        }
+    }
+    void SetUp() override {
+        SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
+        SetUpReverb();
+    }
+    void TearDown() override {
+        SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
+        TearDownReverb();
+    }
+
+    EnvironmentalReverb::Tag mTag;
+    int mParamValues;
+    std::vector<float> mInput;
+    bool mIsInputMute;
+};
+
+TEST_P(EnvironmentalReverbDensityTest, DensityOutput) {
+    float inputRmse =
+            audio_utils_compute_energy_mono(mInput.data(), AUDIO_FORMAT_PCM_FLOAT, mInput.size());
+
+    std::vector<float> output(kBufferSize);
+    setParameterAndProcess(mInput, output, mParamValues, mTag);
+
+    if (isAuxiliary() && !mIsInputMute) {
+        accumulate_float(output.data(), mInput.data(), output.size());
+    }
+
+    float outputRmse =
+            audio_utils_compute_energy_mono(output.data(), AUDIO_FORMAT_PCM_FLOAT, output.size());
+    if (inputRmse != 0) {
+        EXPECT_GT(outputRmse, 0);
+    } else {
+        EXPECT_EQ(outputRmse, inputRmse);
+    }
+}
+
+INSTANTIATE_TEST_SUITE_P(
+        EnvironmentalReverbTest, EnvironmentalReverbDensityTest,
+        ::testing::Combine(
+                testing::ValuesIn(kDescPair = EffectFactoryHelper::getAllEffectDescriptors(
+                                          IFactory::descriptor, getEffectTypeUuidEnvReverb())),
+                testing::Values(kDensityParam.first), testing::ValuesIn(kDensityParam.second),
+                testing::Bool()),
+        [](const testing::TestParamInfo<EnvironmentalReverbDensityTest::ParamType>& info) {
+            auto descriptor = std::get<DESCRIPTOR>(info.param).second;
+            auto tag = std::get<TAG_DENSITY_VALUE>(info.param);
+            auto value = std::get<PARAM_DENSITY_VALUE>(info.param);
+            std::string isInputMute = std::to_string(std::get<IS_INPUT_MUTE>(info.param));
+            std::string name = getPrefix(descriptor) + "_Tag_" + toString(tag) + "_Value_" +
+                               std::to_string(value) + "_isInputMute_" + isInputMute;
+            return name;
+        });
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EnvironmentalReverbDensityTest);
+
 int main(int argc, char** argv) {
     ::testing::InitGoogleTest(&argc, argv);
     ::testing::UnitTest::GetInstance()->listeners().Append(new TestExecutionTracer());
diff --git a/automotive/audiocontrol/aidl/Android.bp b/automotive/audiocontrol/aidl/Android.bp
index 0eb17fe..edb29c9 100644
--- a/automotive/audiocontrol/aidl/Android.bp
+++ b/automotive/audiocontrol/aidl/Android.bp
@@ -62,12 +62,12 @@
         },
 
     ],
-    frozen: true,
+    frozen: false,
 
 }
 
 // Note: This should always be one version ahead of the last frozen version
-latest_android_hardware_automotive_audiocontrol = "android.hardware.automotive.audiocontrol-V4"
+latest_android_hardware_automotive_audiocontrol = "android.hardware.automotive.audiocontrol-V5"
 
 cc_defaults {
     name: "latest_android_hardware_automotive_audiocontrol_cpp_static",
diff --git a/automotive/evs/aidl/Android.bp b/automotive/evs/aidl/Android.bp
index dfb15c6..5b2f82f 100644
--- a/automotive/evs/aidl/Android.bp
+++ b/automotive/evs/aidl/Android.bp
@@ -44,6 +44,9 @@
         ndk: {
             min_sdk_version: "29",
         },
+        rust: {
+            enabled: true,
+        },
     },
     versions_with_info: [
         {
diff --git a/automotive/evs/aidl/rust_impl/Android.bp b/automotive/evs/aidl/rust_impl/Android.bp
new file mode 100644
index 0000000..ac8b90f
--- /dev/null
+++ b/automotive/evs/aidl/rust_impl/Android.bp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+rust_binary {
+    name: "android.hardware.automotive.evs-aidl-rust-service",
+    relative_install_path: "hw",
+    vendor: true,
+    srcs: ["src/*.rs"],
+    crate_root: "src/main.rs",
+    vintf_fragments: ["manifest_evs-rust-service.xml"],
+    init_rc: ["evs-rust-service.rc"],
+    rustlibs: [
+        "android.hardware.automotive.evs-V2-rust",
+        "libbinder_rs",
+        "liblog_rust",
+    ],
+}
diff --git a/automotive/evs/aidl/rust_impl/README.md b/automotive/evs/aidl/rust_impl/README.md
new file mode 100644
index 0000000..bf00aed
--- /dev/null
+++ b/automotive/evs/aidl/rust_impl/README.md
@@ -0,0 +1,21 @@
+# Rust Skeleton EVS HAL implementation.
+
+WARNING: This is not a reference EVS HAL implementation and therefore does not
+provide any actual functionality.
+
+This folder contains a skeleton EVS HAL implementation in Rust to demonstrate
+how vendors could implement their EVS HAL in Rust. To compile and run this
+implementation, please include below package to the device build script:
+
+* `android.hardware.automotive.evs-aidl-rust-service`
+
+Please note that this service will attempt to register the service as
+`IEvsEnumerator/rust/0` and therefore is also required to be declared in the
+service context by adding below line to a proper `service_contexts` file:
+
+> android.hardware.automotive.evs.IEvsEnumerator/rust/0 u:object_r:hal_evs_service:s0
+
+This implementation intentionally returns `binder::StatusCode::UNKNOWN_ERROR`
+for any API call except deprecated API for ultrasonics; the process will be
+panicked on these methods instead. Hence, this implementation does not comply
+with VTS tests and vendors must replace each method with actual implementation.
diff --git a/automotive/evs/aidl/rust_impl/evs-rust-service.rc b/automotive/evs/aidl/rust_impl/evs-rust-service.rc
new file mode 100644
index 0000000..3741b21
--- /dev/null
+++ b/automotive/evs/aidl/rust_impl/evs-rust-service.rc
@@ -0,0 +1,8 @@
+service vendor.evs-hal-rust-default /vendor/bin/hw/android.hardware.automotive.evs-aidl-rust-service
+    class early_hal
+    priority -20
+    user graphics
+    group automotive_evs camera
+    onrestart restart cardisplayproxyd
+    onrestart restart evsmanagerd
+    disabled
diff --git a/automotive/evs/aidl/rust_impl/manifest_evs-rust-service.xml b/automotive/evs/aidl/rust_impl/manifest_evs-rust-service.xml
new file mode 100644
index 0000000..813cbb2
--- /dev/null
+++ b/automotive/evs/aidl/rust_impl/manifest_evs-rust-service.xml
@@ -0,0 +1,7 @@
+<manifest version="2.0" type="device">
+    <hal format="aidl">
+        <name>android.hardware.automotive.evs</name>
+        <version>2</version>
+        <fqname>IEvsEnumerator/rust/0</fqname>
+    </hal>
+</manifest>
diff --git a/automotive/evs/aidl/rust_impl/src/default_evs_hal.rs b/automotive/evs/aidl/rust_impl/src/default_evs_hal.rs
new file mode 100644
index 0000000..72b2d53
--- /dev/null
+++ b/automotive/evs/aidl/rust_impl/src/default_evs_hal.rs
@@ -0,0 +1,113 @@
+//
+// Copyright (C) 2024 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.
+//
+
+use android_hardware_automotive_evs::aidl::android::hardware::automotive::evs::{
+    CameraDesc::CameraDesc, DisplayState::DisplayState, IEvsCamera::IEvsCamera,
+    IEvsDisplay::IEvsDisplay, IEvsEnumerator::IEvsEnumerator,
+    IEvsEnumeratorStatusCallback::IEvsEnumeratorStatusCallback,
+    IEvsUltrasonicsArray::IEvsUltrasonicsArray, Stream::Stream,
+    UltrasonicsArrayDesc::UltrasonicsArrayDesc,
+};
+
+pub struct DefaultEvsHal {}
+
+impl binder::Interface for DefaultEvsHal {}
+
+impl IEvsEnumerator for DefaultEvsHal {
+    fn closeCamera(
+        &self,
+        _: &binder::Strong<(dyn IEvsCamera + 'static)>,
+    ) -> std::result::Result<(), binder::Status> {
+        Err(binder::StatusCode::UNKNOWN_ERROR.into())
+    }
+
+    fn closeDisplay(
+        &self,
+        _: &binder::Strong<(dyn IEvsDisplay + 'static)>,
+    ) -> std::result::Result<(), binder::Status> {
+        Err(binder::StatusCode::UNKNOWN_ERROR.into())
+    }
+
+    fn closeUltrasonicsArray(
+        &self,
+        _: &binder::Strong<(dyn IEvsUltrasonicsArray + 'static)>,
+    ) -> std::result::Result<(), binder::Status> {
+        unimplemented!()
+    }
+
+    fn getCameraList(&self) -> std::result::Result<std::vec::Vec<CameraDesc>, binder::Status> {
+        Err(binder::StatusCode::UNKNOWN_ERROR.into())
+    }
+
+    fn getDisplayIdList(&self) -> std::result::Result<std::vec::Vec<u8>, binder::Status> {
+        Err(binder::StatusCode::UNKNOWN_ERROR.into())
+    }
+
+    fn getDisplayState(&self) -> std::result::Result<DisplayState, binder::Status> {
+        Err(binder::StatusCode::UNKNOWN_ERROR.into())
+    }
+
+    fn getStreamList(
+        &self,
+        _: &CameraDesc,
+    ) -> std::result::Result<std::vec::Vec<Stream>, binder::Status> {
+        Err(binder::StatusCode::UNKNOWN_ERROR.into())
+    }
+
+    fn getUltrasonicsArrayList(
+        &self,
+    ) -> std::result::Result<std::vec::Vec<UltrasonicsArrayDesc>, binder::Status> {
+        unimplemented!()
+    }
+
+    fn isHardware(&self) -> std::result::Result<bool, binder::Status> {
+        Err(binder::StatusCode::UNKNOWN_ERROR.into())
+    }
+
+    fn openCamera(
+        &self,
+        _: &str,
+        _: &Stream,
+    ) -> std::result::Result<binder::Strong<(dyn IEvsCamera + 'static)>, binder::Status> {
+        Err(binder::StatusCode::UNKNOWN_ERROR.into())
+    }
+
+    fn openDisplay(
+        &self,
+        _: i32,
+    ) -> std::result::Result<binder::Strong<(dyn IEvsDisplay + 'static)>, binder::Status> {
+        Err(binder::StatusCode::UNKNOWN_ERROR.into())
+    }
+
+    fn openUltrasonicsArray(
+        &self,
+        _: &str,
+    ) -> std::result::Result<binder::Strong<(dyn IEvsUltrasonicsArray + 'static)>, binder::Status>
+    {
+        unimplemented!()
+    }
+
+    fn registerStatusCallback(
+        &self,
+        _: &binder::Strong<(dyn IEvsEnumeratorStatusCallback + 'static)>,
+    ) -> std::result::Result<(), binder::Status> {
+        Err(binder::StatusCode::UNKNOWN_ERROR.into())
+    }
+
+    fn getDisplayStateById(&self, _: i32) -> std::result::Result<DisplayState, binder::Status> {
+        Err(binder::StatusCode::UNKNOWN_ERROR.into())
+    }
+}
diff --git a/automotive/evs/aidl/rust_impl/src/main.rs b/automotive/evs/aidl/rust_impl/src/main.rs
new file mode 100644
index 0000000..df312c0
--- /dev/null
+++ b/automotive/evs/aidl/rust_impl/src/main.rs
@@ -0,0 +1,42 @@
+//
+// Copyright (C) 2024 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.
+//
+
+mod default_evs_hal;
+
+use crate::default_evs_hal::DefaultEvsHal;
+
+use android_hardware_automotive_evs::aidl::android::hardware::automotive::evs::IEvsEnumerator::BnEvsEnumerator;
+
+use log::info;
+
+fn main() {
+    binder::ProcessState::start_thread_pool();
+
+    let service = DefaultEvsHal {};
+
+    // Register HAL implementation as rust/0 instance.
+    let service_name = "android.hardware.automotive.evs.IEvsEnumerator/rust/0";
+    let service_binder = BnEvsEnumerator::new_binder(service, binder::BinderFeatures::default());
+
+    binder::add_service(service_name, service_binder.as_binder())
+        .expect(format!("Failed to register {}.", service_name).as_str());
+    info!("EVS Hardware Enumerator is ready");
+
+    binder::ProcessState::join_thread_pool();
+
+    // In normal operation, we don't expect the thread pool to exit.
+    info!("EVS Hardware Enumerator is shutting down");
+}
diff --git a/automotive/vehicle/2.0/default/Android.bp b/automotive/vehicle/2.0/default/Android.bp
index 94a5882..76d44f8 100644
--- a/automotive/vehicle/2.0/default/Android.bp
+++ b/automotive/vehicle/2.0/default/Android.bp
@@ -290,7 +290,8 @@
     ],
     fuzz_config: {
         cc: [
-            "android-media-fuzzing-reports@google.com",
+            "ericjeong@google.com",
+            "shanyu@google.com",
         ],
         componentid: 533764,
         hotlists: [
diff --git a/automotive/vehicle/TEST_MAPPING b/automotive/vehicle/TEST_MAPPING
index 77629a9..d848774 100644
--- a/automotive/vehicle/TEST_MAPPING
+++ b/automotive/vehicle/TEST_MAPPING
@@ -45,6 +45,9 @@
       "name": "FakeVehicleHardwareTest"
     },
     {
+      "name": "GRPCVehicleHardwareUnitTest"
+    },
+    {
       "name": "CarServiceUnitTest",
       "options" : [
         {
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h b/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h
index 79d3e77..ec69894 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h
@@ -327,6 +327,8 @@
     static android::base::Result<float> safelyParseFloat(int index, const std::string& s);
     static android::base::Result<int32_t> parsePropId(const std::vector<std::string>& options,
                                                       size_t index);
+    static android::base::Result<int32_t> parseAreaId(const std::vector<std::string>& options,
+                                                      size_t index, int32_t propId);
 };
 
 }  // namespace fake
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp b/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
index 4f060e2..54dcca2 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
@@ -1902,6 +1902,37 @@
     return safelyParseInt<int32_t>(index, propIdStr);
 }
 
+// Parses areaId option ("-a"). It can be an Integer or a string in the form of "AREA_1" or
+// "AREA_1 | AREA_2 | ..."
+Result<int32_t> FakeVehicleHardware::parseAreaId(const std::vector<std::string>& options,
+                                                 size_t index, int32_t propId) {
+    const std::string& areaIdStr = options[index];
+    auto result = safelyParseInt<int32_t>(index, areaIdStr);
+    if (result.ok()) {
+        return result;
+    }
+
+    // Check for pattern matching "AREA_1 | AREA_2 | AREA_3".
+    std::regex pattern(R"(^\w+(?:( )?\|( )?\w+)*$)");
+    std::smatch match;
+    int32_t areaId = 0;
+    if (!std::regex_match(areaIdStr, match, pattern)) {
+        return result;
+    }
+    pattern = R"(\w+)";
+
+    std::sregex_iterator end;
+    for (std::sregex_iterator it(areaIdStr.begin(), areaIdStr.end(), pattern); it != end; it++) {
+        // Parse each areas contained in this areaId.
+        auto result = stringToArea(it->str(), propId);
+        if (!result.ok()) {
+            return result;
+        }
+        areaId |= result.value();
+    }
+    return areaId;
+}
+
 std::string FakeVehicleHardware::dumpSpecificProperty(const std::vector<std::string>& options) {
     if (auto result = checkArgumentsSize(options, /*minSize=*/2); !result.ok()) {
         return getErrorMsg(result);
@@ -1958,6 +1989,7 @@
     prop.status = VehiclePropertyStatus::AVAILABLE;
     optionIndex++;
     std::unordered_set<std::string> parsedOptions;
+    int32_t areaIdIndex = -1;
 
     while (optionIndex < options.size()) {
         std::string argType = options[optionIndex];
@@ -2032,13 +2064,7 @@
             if (argValuesSize != 1) {
                 return Error() << "Expect exact one value when using \"-a\"\n";
             }
-            auto int32Result = safelyParseInt<int32_t>(currentIndex, argValues[0]);
-            if (!int32Result.ok()) {
-                return Error() << StringPrintf("Area ID: \"%s\" is not a valid int: %s\n",
-                                               argValues[0].c_str(),
-                                               getErrorMsg(int32Result).c_str());
-            }
-            prop.areaId = int32Result.value();
+            areaIdIndex = currentIndex;
         } else if (EqualsIgnoreCase(argType, "-t")) {
             if (argValuesSize != 1) {
                 return Error() << "Expect exact one value when using \"-t\"\n";
@@ -2055,6 +2081,17 @@
         }
     }
 
+    if (areaIdIndex != -1) {
+        auto int32Result = parseAreaId(options, areaIdIndex, prop.prop);
+        if (!int32Result.ok()) {
+            return Error() << StringPrintf(
+                           "Area ID: \"%s\" is not a valid int or "
+                           "one or more area names: %s\n",
+                           options[areaIdIndex].c_str(), getErrorMsg(int32Result).c_str());
+        }
+        prop.areaId = int32Result.value();
+    }
+
     return prop;
 }
 
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp b/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp
index 0924360..8dbba19 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp
@@ -77,6 +77,7 @@
 using ::aidl::android::hardware::automotive::vehicle::VehicleApPowerStateReq;
 using ::aidl::android::hardware::automotive::vehicle::VehicleApPowerStateShutdownParam;
 using ::aidl::android::hardware::automotive::vehicle::VehicleAreaMirror;
+using ::aidl::android::hardware::automotive::vehicle::VehicleAreaSeat;
 using ::aidl::android::hardware::automotive::vehicle::VehicleHwKeyInputAction;
 using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig;
 using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
@@ -2781,6 +2782,8 @@
 
 std::vector<SetPropTestCase> GenSetPropParams() {
     std::string infoMakeProperty = std::to_string(toInt(VehicleProperty::INFO_MAKE));
+    std::string testVendorProperty =
+            std::to_string(toInt(TestVendorProperty::VENDOR_EXTENSION_FLOAT_PROPERTY));
     return {
             {"success_set_string", {"--set", infoMakeProperty, "-s", CAR_MAKE}, true},
             {"success_set_with_name", {"--set", "INFO_MAKE", "-s", CAR_MAKE}, true},
@@ -2889,6 +2892,14 @@
              {"--set", infoMakeProperty, "-a", "-s", CAR_MAKE},
              false,
              "Expect exact one value"},
+            {"fail_invalid_area_name",
+             {"--set", testVendorProperty, "-a", "ROW_1_LEFT|NO_SUCH_AREA", "-f", "1.234"},
+             false,
+             "not a valid int or one or more area names"},
+            {"fail_invalid_area_format",
+             {"--set", testVendorProperty, "-a", "ROW_1_LEFT|||ROW_2_LEFT", "-f", "1.234"},
+             false,
+             "not a valid int or one or more area names"},
     };
 }
 
@@ -2933,6 +2944,86 @@
     ASSERT_EQ(3.402823466E+38f, value.value.floatValues[2]);
 }
 
+TEST_F(FakeVehicleHardwareTest, SetPropertyWithPropertyNameAreaId) {
+    int32_t areaId = toInt(VehicleAreaSeat::ROW_1_LEFT);
+    getHardware()->dump(
+            {"--set", "HVAC_TEMPERATURE_SET", "-a", std::to_string(areaId), "-f", "22.345"});
+
+    VehiclePropValue requestProp;
+    requestProp.prop = toInt(VehicleProperty::HVAC_TEMPERATURE_SET);
+    requestProp.areaId = areaId;
+    auto result = getValue(requestProp);
+
+    ASSERT_TRUE(result.ok());
+    VehiclePropValue value = result.value();
+    ASSERT_EQ(value.prop, toInt(VehicleProperty::HVAC_TEMPERATURE_SET));
+    ASSERT_EQ(value.areaId, areaId);
+    ASSERT_EQ(1u, value.value.floatValues.size());
+    ASSERT_EQ(22.345f, value.value.floatValues[0]);
+}
+
+TEST_F(FakeVehicleHardwareTest, SetPropertyWithPropertyNameAreaName) {
+    int32_t areaId = toInt(VehicleAreaSeat::ROW_1_LEFT);
+    getHardware()->dump({"--set", "HVAC_TEMPERATURE_SET", "-a", "ROW_1_LEFT", "-f", "22.345"});
+
+    VehiclePropValue requestProp;
+    requestProp.prop = toInt(VehicleProperty::HVAC_TEMPERATURE_SET);
+    requestProp.areaId = areaId;
+    auto result = getValue(requestProp);
+
+    ASSERT_TRUE(result.ok());
+    VehiclePropValue value = result.value();
+    ASSERT_EQ(value.prop, toInt(VehicleProperty::HVAC_TEMPERATURE_SET));
+    ASSERT_EQ(value.areaId, areaId);
+    ASSERT_EQ(1u, value.value.floatValues.size());
+    ASSERT_EQ(22.345f, value.value.floatValues[0]);
+}
+
+TEST_F(FakeVehicleHardwareTest, GetPropertyWithPropertyNameAreaName) {
+    auto result = getHardware()->dump({"--get", "HVAC_TEMPERATURE_SET", "-a", "ROW_1_LEFT"});
+
+    // Default value is 17
+    ASSERT_THAT(result.buffer, ContainsRegex("17"));
+
+    getHardware()->dump({"--set", "HVAC_TEMPERATURE_SET", "-a", "ROW_1_LEFT", "-f", "22"});
+    result = getHardware()->dump({"--get", "HVAC_TEMPERATURE_SET", "-a", "ROW_1_LEFT"});
+
+    ASSERT_THAT(result.buffer, ContainsRegex("22"));
+}
+
+TEST_F(FakeVehicleHardwareTest, SetPropertyWithPropertyNameTwoAreasInOneId) {
+    int32_t propId = toInt(TestVendorProperty::VENDOR_EXTENSION_FLOAT_PROPERTY);
+    std::string testVendorProperty = std::to_string(propId);
+    getHardware()->dump({"--set", testVendorProperty, "-a", "ROW_1_LEFT|ROW_2_LEFT|ROW_2_CENTER",
+                         "-f", "1.234"});
+
+    VehiclePropValue requestProp;
+    requestProp.prop = propId;
+    int32_t areaId = toInt(VehicleAreaSeat::ROW_1_LEFT) | toInt(VehicleAreaSeat::ROW_2_LEFT) |
+                     toInt(VehicleAreaSeat::ROW_2_CENTER);
+    requestProp.areaId = areaId;
+    auto result = getValue(requestProp);
+
+    ASSERT_TRUE(result.ok());
+    VehiclePropValue value = result.value();
+    ASSERT_EQ(value.prop, propId);
+    ASSERT_EQ(value.areaId, areaId);
+    ASSERT_EQ(1u, value.value.floatValues.size());
+    ASSERT_EQ(1.234f, value.value.floatValues[0]);
+
+    // Ignore space between two areas.
+    getHardware()->dump({"--set", testVendorProperty, "-a",
+                         "ROW_1_LEFT | ROW_2_LEFT | ROW_2_CENTER", "-f", "2.345"});
+    result = getValue(requestProp);
+
+    ASSERT_TRUE(result.ok());
+    value = result.value();
+    ASSERT_EQ(value.prop, propId);
+    ASSERT_EQ(value.areaId, areaId);
+    ASSERT_EQ(1u, value.value.floatValues.size());
+    ASSERT_EQ(2.345f, value.value.floatValues[0]);
+}
+
 struct OptionsTestCase {
     std::string name;
     std::vector<std::string> options;
diff --git a/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.cpp b/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.cpp
index f44573a..73bb521 100644
--- a/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.cpp
+++ b/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.cpp
@@ -20,6 +20,7 @@
 
 #include <android-base/logging.h>
 #include <grpc++/grpc++.h>
+#include <utils/SystemClock.h>
 
 #include <cstdlib>
 #include <mutex>
@@ -28,11 +29,16 @@
 
 namespace android::hardware::automotive::vehicle::virtualization {
 
-static std::shared_ptr<::grpc::ChannelCredentials> getChannelCredentials() {
-    // TODO(chenhaosjtuacm): get secured credentials here
+namespace {
+
+constexpr size_t MAX_RETRY_COUNT = 5;
+
+std::shared_ptr<::grpc::ChannelCredentials> getChannelCredentials() {
     return ::grpc::InsecureChannelCredentials();
 }
 
+}  // namespace
+
 GRPCVehicleHardware::GRPCVehicleHardware(std::string service_addr)
     : mServiceAddr(std::move(service_addr)),
       mGrpcChannel(::grpc::CreateChannel(mServiceAddr, getChannelCredentials())),
@@ -40,11 +46,13 @@
       mValuePollingThread([this] { ValuePollingLoop(); }) {}
 
 // Only used for unit testing.
-GRPCVehicleHardware::GRPCVehicleHardware(std::unique_ptr<proto::VehicleServer::StubInterface> stub)
-    : mServiceAddr(""),
-      mGrpcChannel(nullptr),
-      mGrpcStub(std::move(stub)),
-      mValuePollingThread([] {}) {}
+GRPCVehicleHardware::GRPCVehicleHardware(std::unique_ptr<proto::VehicleServer::StubInterface> stub,
+                                         bool startValuePollingLoop)
+    : mServiceAddr(""), mGrpcChannel(nullptr), mGrpcStub(std::move(stub)) {
+    if (startValuePollingLoop) {
+        mValuePollingThread = std::thread([this] { ValuePollingLoop(); });
+    }
+}
 
 GRPCVehicleHardware::~GRPCVehicleHardware() {
     {
@@ -52,7 +60,9 @@
         mShuttingDownFlag.store(true);
     }
     mShutdownCV.notify_all();
-    mValuePollingThread.join();
+    if (mValuePollingThread.joinable()) {
+        mValuePollingThread.join();
+    }
 }
 
 std::vector<aidlvhal::VehiclePropConfig> GRPCVehicleHardware::getAllPropertyConfigs() const {
@@ -109,36 +119,117 @@
 aidlvhal::StatusCode GRPCVehicleHardware::getValues(
         std::shared_ptr<const GetValuesCallback> callback,
         const std::vector<aidlvhal::GetValueRequest>& requests) const {
-    ::grpc::ClientContext context;
+    std::vector<aidlvhal::GetValueResult> results;
+    auto status = getValuesWithRetry(requests, &results, /*retryCount=*/0);
+    if (status != aidlvhal::StatusCode::OK) {
+        return status;
+    }
+    if (!results.empty()) {
+        (*callback)(std::move(results));
+    }
+    return status;
+}
+
+aidlvhal::StatusCode GRPCVehicleHardware::getValuesWithRetry(
+        const std::vector<aidlvhal::GetValueRequest>& requests,
+        std::vector<aidlvhal::GetValueResult>* results, size_t retryCount) const {
+    if (retryCount == MAX_RETRY_COUNT) {
+        LOG(ERROR) << __func__ << ": GRPC GetValues Failed, failed to get the latest value after "
+                   << retryCount << " retries";
+        return aidlvhal::StatusCode::TRY_AGAIN;
+    }
+
     proto::VehiclePropValueRequests protoRequests;
-    proto::GetValueResults protoResults;
+    std::unordered_map<int64_t, const aidlvhal::GetValueRequest*> requestById;
     for (const auto& request : requests) {
         auto& protoRequest = *protoRequests.add_requests();
         protoRequest.set_request_id(request.requestId);
         proto_msg_converter::aidlToProto(request.prop, protoRequest.mutable_value());
+        requestById[request.requestId] = &request;
     }
+
     // TODO(chenhaosjtuacm): Make it Async.
+    ::grpc::ClientContext context;
+    proto::GetValueResults protoResults;
     auto grpc_status = mGrpcStub->GetValues(&context, protoRequests, &protoResults);
     if (!grpc_status.ok()) {
         LOG(ERROR) << __func__ << ": GRPC GetValues Failed: " << grpc_status.error_message();
         return aidlvhal::StatusCode::INTERNAL_ERROR;
     }
-    std::vector<aidlvhal::GetValueResult> results;
+
+    std::vector<aidlvhal::GetValueRequest> retryRequests;
     for (const auto& protoResult : protoResults.results()) {
-        auto& result = results.emplace_back();
-        result.requestId = protoResult.request_id();
-        result.status = static_cast<aidlvhal::StatusCode>(protoResult.status());
-        if (protoResult.has_value()) {
-            aidlvhal::VehiclePropValue value;
-            proto_msg_converter::protoToAidl(protoResult.value(), &value);
-            result.prop = std::move(value);
+        int64_t requestId = protoResult.request_id();
+        auto it = requestById.find(requestId);
+        if (it == requestById.end()) {
+            LOG(ERROR) << __func__
+                       << "Invalid getValue request with unknown request ID: " << requestId
+                       << ", ignore";
+            continue;
         }
+
+        if (!protoResult.has_value()) {
+            auto& result = results->emplace_back();
+            result.requestId = requestId;
+            result.status = static_cast<aidlvhal::StatusCode>(protoResult.status());
+            continue;
+        }
+
+        aidlvhal::VehiclePropValue value;
+        proto_msg_converter::protoToAidl(protoResult.value(), &value);
+
+        // VHAL proxy server uses a different timestamp then AAOS timestamp, so we have to reset
+        // the timestamp.
+        // TODO(b/350822044): Remove this once we use timestamp from proxy server.
+        if (!setAndroidTimestamp(&value)) {
+            // This is a rare case when we receive a property update event reflecting a new value
+            // for the property before we receive the get value result. This means that the result
+            // is already outdated, hence we should retry getting the latest value again.
+            LOG(WARNING) << __func__ << "getValue result for propId: " << value.prop
+                         << " areaId: " << value.areaId << " is oudated, retry";
+            retryRequests.push_back(*(it->second));
+            continue;
+        }
+
+        auto& result = results->emplace_back();
+        result.requestId = requestId;
+        result.status = static_cast<aidlvhal::StatusCode>(protoResult.status());
+        result.prop = std::move(value);
     }
-    (*callback)(std::move(results));
+
+    if (retryRequests.size() != 0) {
+        return getValuesWithRetry(retryRequests, results, retryCount++);
+    }
 
     return aidlvhal::StatusCode::OK;
 }
 
+bool GRPCVehicleHardware::setAndroidTimestamp(aidlvhal::VehiclePropValue* propValue) const {
+    PropIdAreaId propIdAreaId = {
+            .propId = propValue->prop,
+            .areaId = propValue->areaId,
+    };
+    int64_t now = elapsedRealtimeNano();
+    int64_t externalTimestamp = propValue->timestamp;
+
+    {
+        std::lock_guard lck(mLatestUpdateTimestampsMutex);
+        auto it = mLatestUpdateTimestamps.find(propIdAreaId);
+        if (it == mLatestUpdateTimestamps.end() || externalTimestamp > (it->second).first) {
+            mLatestUpdateTimestamps[propIdAreaId].first = externalTimestamp;
+            mLatestUpdateTimestamps[propIdAreaId].second = now;
+            propValue->timestamp = now;
+            return true;
+        }
+        if (externalTimestamp == (it->second).first) {
+            propValue->timestamp = (it->second).second;
+            return true;
+        }
+    }
+    // externalTimestamp < (it->second).first, the value is outdated.
+    return false;
+}
+
 void GRPCVehicleHardware::registerOnPropertyChangeEvent(
         std::unique_ptr<const PropertyChangeCallback> callback) {
     std::lock_guard lck(mCallbackMutex);
@@ -248,46 +339,61 @@
 
 void GRPCVehicleHardware::ValuePollingLoop() {
     while (!mShuttingDownFlag.load()) {
-        ::grpc::ClientContext context;
-
-        bool rpc_stopped{false};
-        std::thread shuttingdown_watcher([this, &rpc_stopped, &context]() {
-            std::unique_lock<std::mutex> lck(mShutdownMutex);
-            mShutdownCV.wait(lck, [this, &rpc_stopped]() {
-                return rpc_stopped || mShuttingDownFlag.load();
-            });
-            context.TryCancel();
-        });
-
-        auto value_stream =
-                mGrpcStub->StartPropertyValuesStream(&context, ::google::protobuf::Empty());
-        LOG(INFO) << __func__ << ": GRPC Value Streaming Started";
-        proto::VehiclePropValues protoValues;
-        while (!mShuttingDownFlag.load() && value_stream->Read(&protoValues)) {
-            std::vector<aidlvhal::VehiclePropValue> values;
-            for (const auto protoValue : protoValues.values()) {
-                values.push_back(aidlvhal::VehiclePropValue());
-                proto_msg_converter::protoToAidl(protoValue, &values.back());
-            }
-            std::shared_lock lck(mCallbackMutex);
-            if (mOnPropChange) {
-                (*mOnPropChange)(values);
-            }
-        }
-
-        {
-            std::lock_guard lck(mShutdownMutex);
-            rpc_stopped = true;
-        }
-        mShutdownCV.notify_all();
-        shuttingdown_watcher.join();
-
-        auto grpc_status = value_stream->Finish();
-        // never reach here until connection lost
-        LOG(ERROR) << __func__ << ": GRPC Value Streaming Failed: " << grpc_status.error_message();
-
+        pollValue();
         // try to reconnect
     }
 }
 
+void GRPCVehicleHardware::pollValue() {
+    ::grpc::ClientContext context;
+
+    bool rpc_stopped{false};
+    std::thread shuttingdown_watcher([this, &rpc_stopped, &context]() {
+        std::unique_lock<std::mutex> lck(mShutdownMutex);
+        mShutdownCV.wait(
+                lck, [this, &rpc_stopped]() { return rpc_stopped || mShuttingDownFlag.load(); });
+        context.TryCancel();
+    });
+
+    auto value_stream = mGrpcStub->StartPropertyValuesStream(&context, ::google::protobuf::Empty());
+    LOG(INFO) << __func__ << ": GRPC Value Streaming Started";
+    proto::VehiclePropValues protoValues;
+    while (!mShuttingDownFlag.load() && value_stream->Read(&protoValues)) {
+        std::vector<aidlvhal::VehiclePropValue> values;
+        for (const auto protoValue : protoValues.values()) {
+            aidlvhal::VehiclePropValue aidlValue = {};
+            proto_msg_converter::protoToAidl(protoValue, &aidlValue);
+
+            // VHAL proxy server uses a different timestamp then AAOS timestamp, so we have to
+            // reset the timestamp.
+            // TODO(b/350822044): Remove this once we use timestamp from proxy server.
+            if (!setAndroidTimestamp(&aidlValue)) {
+                LOG(WARNING) << __func__ << ": property event for propId: " << aidlValue.prop
+                             << " areaId: " << aidlValue.areaId << " is outdated, ignore";
+                continue;
+            }
+
+            values.push_back(std::move(aidlValue));
+        }
+        if (values.empty()) {
+            continue;
+        }
+        std::shared_lock lck(mCallbackMutex);
+        if (mOnPropChange) {
+            (*mOnPropChange)(values);
+        }
+    }
+
+    {
+        std::lock_guard lck(mShutdownMutex);
+        rpc_stopped = true;
+    }
+    mShutdownCV.notify_all();
+    shuttingdown_watcher.join();
+
+    auto grpc_status = value_stream->Finish();
+    // never reach here until connection lost
+    LOG(ERROR) << __func__ << ": GRPC Value Streaming Failed: " << grpc_status.error_message();
+}
+
 }  // namespace android::hardware::automotive::vehicle::virtualization
diff --git a/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.h b/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.h
index 9750f62..1edf658 100644
--- a/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.h
+++ b/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.h
@@ -20,6 +20,7 @@
 #include <VehicleHalTypes.h>
 #include <VehicleUtils.h>
 #include <android-base/result.h>
+#include <android-base/thread_annotations.h>
 
 #include "VehicleServer.grpc.pb.h"
 #include "VehicleServer.pb.h"
@@ -33,6 +34,7 @@
 #include <shared_mutex>
 #include <string>
 #include <thread>
+#include <unordered_map>
 #include <vector>
 
 namespace android::hardware::automotive::vehicle::virtualization {
@@ -43,9 +45,6 @@
   public:
     explicit GRPCVehicleHardware(std::string service_addr);
 
-    // Only used for unit testing.
-    explicit GRPCVehicleHardware(std::unique_ptr<proto::VehicleServer::StubInterface> stub);
-
     ~GRPCVehicleHardware();
 
     // Get all the property configs.
@@ -94,7 +93,7 @@
     std::unique_ptr<const PropertyChangeCallback> mOnPropChange;
 
   private:
-    void ValuePollingLoop();
+    friend class GRPCVehicleHardwareUnitTest;
 
     std::string mServiceAddr;
     std::shared_ptr<::grpc::Channel> mGrpcChannel;
@@ -106,6 +105,31 @@
     std::mutex mShutdownMutex;
     std::condition_variable mShutdownCV;
     std::atomic<bool> mShuttingDownFlag{false};
+
+    mutable std::mutex mLatestUpdateTimestampsMutex;
+
+    // A map from [propId, areaId] to the latest timestamp this property is updated.
+    // The key is a tuple, the first element is the external timestamp (timestamp set by VHAL
+    // server), the second element is the Android timestamp (elapsedRealtimeNano).
+    mutable std::unordered_map<PropIdAreaId, std::pair<int64_t, int64_t>,
+                               PropIdAreaIdHash> mLatestUpdateTimestamps
+            GUARDED_BY(mLatestUpdateTimestampsMutex);
+
+    // Only used for unit testing.
+    GRPCVehicleHardware(std::unique_ptr<proto::VehicleServer::StubInterface> stub,
+                        bool startValuePollingLoop);
+
+    void ValuePollingLoop();
+    void pollValue();
+
+    aidlvhal::StatusCode getValuesWithRetry(const std::vector<aidlvhal::GetValueRequest>& requests,
+                                            std::vector<aidlvhal::GetValueResult>* results,
+                                            size_t retryCount) const;
+
+    // Check the external timestamp of propValue against the latest updated external timestamp, if
+    // this is an outdated value, return false. Otherwise, update the external timestamp to the
+    // Android timestamp and return true.
+    bool setAndroidTimestamp(aidlvhal::VehiclePropValue* propValue) const;
 };
 
 }  // namespace android::hardware::automotive::vehicle::virtualization
diff --git a/automotive/vehicle/aidl/impl/grpc/GRPCVehicleProxyServer.cpp b/automotive/vehicle/aidl/impl/grpc/GRPCVehicleProxyServer.cpp
index a6abfa3..eb98af0 100644
--- a/automotive/vehicle/aidl/impl/grpc/GRPCVehicleProxyServer.cpp
+++ b/automotive/vehicle/aidl/impl/grpc/GRPCVehicleProxyServer.cpp
@@ -40,7 +40,11 @@
 
 GrpcVehicleProxyServer::GrpcVehicleProxyServer(std::string serverAddr,
                                                std::unique_ptr<IVehicleHardware>&& hardware)
-    : mServiceAddr(std::move(serverAddr)), mHardware(std::move(hardware)) {
+    : GrpcVehicleProxyServer(std::vector<std::string>({serverAddr}), std::move(hardware)){};
+
+GrpcVehicleProxyServer::GrpcVehicleProxyServer(std::vector<std::string> serverAddrs,
+                                               std::unique_ptr<IVehicleHardware>&& hardware)
+    : mServiceAddrs(std::move(serverAddrs)), mHardware(std::move(hardware)) {
     mHardware->registerOnPropertyChangeEvent(
             std::make_unique<const IVehicleHardware::PropertyChangeCallback>(
                     [this](std::vector<aidlvhal::VehiclePropValue> values) {
@@ -254,7 +258,9 @@
     }
     ::grpc::ServerBuilder builder;
     builder.RegisterService(this);
-    builder.AddListeningPort(mServiceAddr, getServerCredentials());
+    for (const std::string& serviceAddr : mServiceAddrs) {
+        builder.AddListeningPort(serviceAddr, getServerCredentials());
+    }
     mServer = builder.BuildAndStart();
     CHECK(mServer) << __func__ << ": failed to create the GRPC server, "
                    << "please make sure the configuration and permissions are correct";
diff --git a/automotive/vehicle/aidl/impl/grpc/GRPCVehicleProxyServer.h b/automotive/vehicle/aidl/impl/grpc/GRPCVehicleProxyServer.h
index dd9e2aa..5ffb531 100644
--- a/automotive/vehicle/aidl/impl/grpc/GRPCVehicleProxyServer.h
+++ b/automotive/vehicle/aidl/impl/grpc/GRPCVehicleProxyServer.h
@@ -41,6 +41,9 @@
   public:
     GrpcVehicleProxyServer(std::string serverAddr, std::unique_ptr<IVehicleHardware>&& hardware);
 
+    GrpcVehicleProxyServer(std::vector<std::string> serverAddrs,
+                           std::unique_ptr<IVehicleHardware>&& hardware);
+
     ::grpc::Status GetAllPropertyConfig(
             ::grpc::ServerContext* context, const ::google::protobuf::Empty* request,
             ::grpc::ServerWriter<proto::VehiclePropConfig>* stream) override;
@@ -116,7 +119,7 @@
         static std::atomic<uint64_t> connection_id_counter_;
     };
 
-    std::string mServiceAddr;
+    std::vector<std::string> mServiceAddrs;
     std::unique_ptr<::grpc::Server> mServer{nullptr};
     std::unique_ptr<IVehicleHardware> mHardware;
 
diff --git a/automotive/vehicle/aidl/impl/grpc/test/GRPCVehicleHardwareUnitTest.cpp b/automotive/vehicle/aidl/impl/grpc/test/GRPCVehicleHardwareUnitTest.cpp
index 3bd7e0e..20af231 100644
--- a/automotive/vehicle/aidl/impl/grpc/test/GRPCVehicleHardwareUnitTest.cpp
+++ b/automotive/vehicle/aidl/impl/grpc/test/GRPCVehicleHardwareUnitTest.cpp
@@ -19,8 +19,10 @@
 
 #include <gmock/gmock.h>
 #include <grpc++/grpc++.h>
+#include <grpcpp/test/mock_stream.h>
 #include <gtest/gtest.h>
 
+#include <utils/SystemClock.h>
 #include <chrono>
 #include <memory>
 #include <string>
@@ -31,98 +33,48 @@
 
 using ::testing::_;
 using ::testing::DoAll;
+using ::testing::ElementsAre;
 using ::testing::NiceMock;
 using ::testing::Return;
 using ::testing::SaveArg;
 using ::testing::SetArgPointee;
+using ::testing::SizeIs;
+
+using ::grpc::testing::MockClientReader;
 
 using proto::MockVehicleServerStub;
 
-const std::string kFakeServerAddr = "0.0.0.0:54321";
-
-class FakeVehicleServer : public proto::VehicleServer::Service {
-  public:
-    ::grpc::Status StartPropertyValuesStream(
-            ::grpc::ServerContext* context, const ::google::protobuf::Empty* request,
-            ::grpc::ServerWriter<proto::VehiclePropValues>* stream) override {
-        stream->Write(proto::VehiclePropValues());
-        // A fake disconnection.
-        return ::grpc::Status(::grpc::StatusCode::ABORTED, "Connection lost.");
-    }
-
-    // Functions that we do not care.
-    ::grpc::Status GetAllPropertyConfig(
-            ::grpc::ServerContext* context, const ::google::protobuf::Empty* request,
-            ::grpc::ServerWriter<proto::VehiclePropConfig>* stream) override {
-        return ::grpc::Status::OK;
-    }
-
-    ::grpc::Status SetValues(::grpc::ServerContext* context,
-                             const proto::VehiclePropValueRequests* requests,
-                             proto::SetValueResults* results) override {
-        return ::grpc::Status::OK;
-    }
-
-    ::grpc::Status GetValues(::grpc::ServerContext* context,
-                             const proto::VehiclePropValueRequests* requests,
-                             proto::GetValueResults* results) override {
-        return ::grpc::Status::OK;
-    }
-};
-
-TEST(GRPCVehicleHardwareUnitTest, Reconnect) {
-    auto receivedUpdate = std::make_shared<std::atomic<int>>(0);
-    auto vehicleHardware = std::make_unique<GRPCVehicleHardware>(kFakeServerAddr);
-    vehicleHardware->registerOnPropertyChangeEvent(
-            std::make_unique<const IVehicleHardware::PropertyChangeCallback>(
-                    [receivedUpdate](const auto&) { receivedUpdate->fetch_add(1); }));
-
-    constexpr size_t kServerRestartTimes = 5;
-    for (size_t serverStart = 0; serverStart < kServerRestartTimes; ++serverStart) {
-        EXPECT_EQ(receivedUpdate->load(), 0);
-        auto fakeServer = std::make_unique<FakeVehicleServer>();
-        ::grpc::ServerBuilder builder;
-        builder.RegisterService(fakeServer.get());
-        builder.AddListeningPort(kFakeServerAddr, ::grpc::InsecureServerCredentials());
-        auto grpcServer = builder.BuildAndStart();
-
-        // Wait until the vehicle hardware received the second update (after one fake
-        // disconnection).
-        constexpr auto kMaxWaitTime = std::chrono::seconds(5);
-        auto startTime = std::chrono::steady_clock::now();
-        while (receivedUpdate->load() <= 1 &&
-               std::chrono::steady_clock::now() - startTime < kMaxWaitTime)
-            ;
-
-        grpcServer->Shutdown();
-        grpcServer->Wait();
-        EXPECT_GT(receivedUpdate->load(), 1);
-
-        // Reset for the next round.
-        receivedUpdate->store(0);
-    }
-}
-
-class GRPCVehicleHardwareMockServerUnitTest : public ::testing::Test {
+class GRPCVehicleHardwareUnitTest : public ::testing::Test {
   protected:
     NiceMock<MockVehicleServerStub>* mGrpcStub;
     std::unique_ptr<GRPCVehicleHardware> mHardware;
 
     void SetUp() override {
         auto stub = std::make_unique<NiceMock<MockVehicleServerStub>>();
-        ;
         mGrpcStub = stub.get();
-        mHardware = std::make_unique<GRPCVehicleHardware>(std::move(stub));
+        // Cannot use make_unique here since the constructor is a private method.
+        mHardware = std::unique_ptr<GRPCVehicleHardware>(
+                new GRPCVehicleHardware(std::move(stub), /*startValuePollingLoop=*/false));
     }
 
     void TearDown() override { mHardware.reset(); }
+
+    // Access GRPCVehicleHardware private method.
+    void pollValue() { mHardware->pollValue(); }
+
+    void startValuePollingLoop(std::unique_ptr<proto::VehicleServer::StubInterface> stub) {
+        mHardware = std::unique_ptr<GRPCVehicleHardware>(
+                new GRPCVehicleHardware(std::move(stub), /*startValuePollingLoop=*/true));
+    }
+
+    void generatePropertyUpdateEvent(int32_t propId, int64_t timestamp);
 };
 
 MATCHER_P(RepeatedInt32Eq, expected_values, "") {
     return std::vector<int32_t>(arg.begin(), arg.end()) == expected_values;
 }
 
-TEST_F(GRPCVehicleHardwareMockServerUnitTest, Subscribe) {
+TEST_F(GRPCVehicleHardwareUnitTest, TestSubscribe) {
     proto::VehicleHalCallStatus protoStatus;
     protoStatus.set_status_code(proto::StatusCode::OK);
     proto::SubscribeRequest actualRequest;
@@ -147,7 +99,7 @@
     EXPECT_EQ(protoOptions.enable_variable_update_rate(), true);
 }
 
-TEST_F(GRPCVehicleHardwareMockServerUnitTest, SubscribeLegacyServer) {
+TEST_F(GRPCVehicleHardwareUnitTest, TestSubscribeLegacyServer) {
     EXPECT_CALL(*mGrpcStub, Subscribe(_, _, _))
             .WillOnce(Return(::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "")));
 
@@ -157,7 +109,7 @@
     EXPECT_EQ(status, aidlvhal::StatusCode::OK);
 }
 
-TEST_F(GRPCVehicleHardwareMockServerUnitTest, SubscribeGrpcFailure) {
+TEST_F(GRPCVehicleHardwareUnitTest, TestSubscribeGrpcFailure) {
     EXPECT_CALL(*mGrpcStub, Subscribe(_, _, _))
             .WillOnce(Return(::grpc::Status(::grpc::StatusCode::INTERNAL, "GRPC Error")));
 
@@ -167,7 +119,7 @@
     EXPECT_EQ(status, aidlvhal::StatusCode::INTERNAL_ERROR);
 }
 
-TEST_F(GRPCVehicleHardwareMockServerUnitTest, SubscribeProtoFailure) {
+TEST_F(GRPCVehicleHardwareUnitTest, TestSubscribeProtoFailure) {
     proto::VehicleHalCallStatus protoStatus;
     protoStatus.set_status_code(proto::StatusCode::NOT_AVAILABLE_SPEED_LOW);
 
@@ -181,7 +133,7 @@
     EXPECT_EQ(status, aidlvhal::StatusCode::NOT_AVAILABLE_SPEED_LOW);
 }
 
-TEST_F(GRPCVehicleHardwareMockServerUnitTest, Unsubscribe) {
+TEST_F(GRPCVehicleHardwareUnitTest, TestUnsubscribe) {
     proto::VehicleHalCallStatus protoStatus;
     protoStatus.set_status_code(proto::StatusCode::OK);
     proto::UnsubscribeRequest actualRequest;
@@ -199,7 +151,7 @@
     EXPECT_EQ(actualRequest.area_id(), areaId);
 }
 
-TEST_F(GRPCVehicleHardwareMockServerUnitTest, UnsubscribeLegacyServer) {
+TEST_F(GRPCVehicleHardwareUnitTest, TestUnsubscribeLegacyServer) {
     EXPECT_CALL(*mGrpcStub, Unsubscribe(_, _, _))
             .WillOnce(Return(::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "")));
 
@@ -208,7 +160,7 @@
     EXPECT_EQ(status, aidlvhal::StatusCode::OK);
 }
 
-TEST_F(GRPCVehicleHardwareMockServerUnitTest, UnsubscribeGrpcFailure) {
+TEST_F(GRPCVehicleHardwareUnitTest, TestUnsubscribeGrpcFailure) {
     EXPECT_CALL(*mGrpcStub, Unsubscribe(_, _, _))
             .WillOnce(Return(::grpc::Status(::grpc::StatusCode::INTERNAL, "GRPC Error")));
 
@@ -217,7 +169,7 @@
     EXPECT_EQ(status, aidlvhal::StatusCode::INTERNAL_ERROR);
 }
 
-TEST_F(GRPCVehicleHardwareMockServerUnitTest, UnsubscribeProtoFailure) {
+TEST_F(GRPCVehicleHardwareUnitTest, TestUnsubscribeProtoFailure) {
     proto::VehicleHalCallStatus protoStatus;
     protoStatus.set_status_code(proto::StatusCode::NOT_AVAILABLE_SPEED_LOW);
 
@@ -230,4 +182,264 @@
     EXPECT_EQ(status, aidlvhal::StatusCode::NOT_AVAILABLE_SPEED_LOW);
 }
 
+TEST_F(GRPCVehicleHardwareUnitTest, TestPollValue) {
+    int64_t testTimestamp = 12345;
+    int32_t testPropId = 54321;
+    int64_t startTimestamp = elapsedRealtimeNano();
+
+    // This will be converted to a unique_ptr in StartPropertyValuesStream. The ownership is passed
+    // there.
+    auto clientReader = new MockClientReader<proto::VehiclePropValues>();
+    EXPECT_CALL(*mGrpcStub, StartPropertyValuesStreamRaw(_, _)).WillOnce(Return(clientReader));
+    EXPECT_CALL(*clientReader, Read(_))
+            .WillOnce([testTimestamp, testPropId](proto::VehiclePropValues* values) {
+                values->Clear();
+                auto value = values->add_values();
+                value->set_timestamp(testTimestamp);
+                value->set_prop(testPropId);
+                return true;
+            })
+            .WillOnce(Return(false));
+    EXPECT_CALL(*clientReader, Finish()).WillOnce(Return(::grpc::Status::OK));
+
+    std::vector<aidlvhal::VehiclePropValue> propertyEvents;
+
+    mHardware->registerOnPropertyChangeEvent(
+            std::make_unique<GRPCVehicleHardware::PropertyChangeCallback>(
+                    [&propertyEvents](const std::vector<aidlvhal::VehiclePropValue>& events) {
+                        for (const auto& event : events) {
+                            propertyEvents.push_back(event);
+                        }
+                    }));
+
+    pollValue();
+
+    ASSERT_THAT(propertyEvents, SizeIs(1));
+    EXPECT_EQ(propertyEvents[0].prop, testPropId);
+    EXPECT_GT(propertyEvents[0].timestamp, startTimestamp)
+            << "Timestamp must be updated to Android timestamp";
+    EXPECT_LT(propertyEvents[0].timestamp, elapsedRealtimeNano())
+            << "Timestamp must be updated to Android timestamp";
+}
+
+TEST_F(GRPCVehicleHardwareUnitTest, TestPollValueIgnoreOutdatedValue) {
+    int64_t testTimestamp1 = 12345;
+    int32_t value1 = 1324;
+    int64_t testTimestamp2 = 12340;
+    int32_t value2 = 1423;
+    int32_t testPropId = 54321;
+    int64_t startTimestamp = elapsedRealtimeNano();
+
+    // This will be converted to a unique_ptr in StartPropertyValuesStream. The ownership is passed
+    // there.
+    auto clientReader = new MockClientReader<proto::VehiclePropValues>();
+    EXPECT_CALL(*mGrpcStub, StartPropertyValuesStreamRaw(_, _)).WillOnce(Return(clientReader));
+    EXPECT_CALL(*clientReader, Read(_))
+            .WillOnce([testTimestamp1, value1, testPropId](proto::VehiclePropValues* values) {
+                values->Clear();
+                auto value = values->add_values();
+                value->set_timestamp(testTimestamp1);
+                value->set_prop(testPropId);
+                value->add_int32_values(value1);
+                return true;
+            })
+            .WillOnce([testTimestamp2, value2, testPropId](proto::VehiclePropValues* values) {
+                values->Clear();
+                // This event is outdated, must be ignored.
+                auto value = values->add_values();
+                value->set_timestamp(testTimestamp2);
+                value->set_prop(testPropId);
+                value->add_int32_values(value2);
+                return true;
+            })
+            .WillOnce(Return(false));
+    EXPECT_CALL(*clientReader, Finish()).WillOnce(Return(::grpc::Status::OK));
+
+    std::vector<aidlvhal::VehiclePropValue> propertyEvents;
+
+    mHardware->registerOnPropertyChangeEvent(
+            std::make_unique<GRPCVehicleHardware::PropertyChangeCallback>(
+                    [&propertyEvents](const std::vector<aidlvhal::VehiclePropValue>& events) {
+                        for (const auto& event : events) {
+                            propertyEvents.push_back(event);
+                        }
+                    }));
+
+    pollValue();
+
+    ASSERT_THAT(propertyEvents, SizeIs(1)) << "Outdated event must be ignored";
+    EXPECT_EQ(propertyEvents[0].prop, testPropId);
+    EXPECT_GT(propertyEvents[0].timestamp, startTimestamp);
+    EXPECT_LT(propertyEvents[0].timestamp, elapsedRealtimeNano());
+    EXPECT_THAT(propertyEvents[0].value.int32Values, ElementsAre(value1));
+}
+
+TEST_F(GRPCVehicleHardwareUnitTest, TestValuePollingLoop) {
+    int64_t testTimestamp = 12345;
+    int32_t testPropId = 54321;
+    auto stub = std::make_unique<NiceMock<MockVehicleServerStub>>();
+
+    // This will be converted to a unique_ptr in StartPropertyValuesStream. The ownership is passed
+    // there.
+    auto clientReader = new MockClientReader<proto::VehiclePropValues>();
+    EXPECT_CALL(*stub, StartPropertyValuesStreamRaw(_, _)).WillOnce(Return(clientReader));
+    EXPECT_CALL(*clientReader, Read(_))
+            .WillRepeatedly([testTimestamp, testPropId](proto::VehiclePropValues* values) {
+                // Sleep for 10ms and always return the same property event.
+                std::this_thread::sleep_for(std::chrono::milliseconds(10));
+                values->Clear();
+                auto value = values->add_values();
+                value->set_timestamp(testTimestamp);
+                value->set_prop(testPropId);
+                return true;
+            });
+    EXPECT_CALL(*clientReader, Finish()).WillOnce(Return(::grpc::Status::OK));
+
+    startValuePollingLoop(std::move(stub));
+
+    std::this_thread::sleep_for(std::chrono::milliseconds(100));
+
+    // This must stop the loop and wait for the thread to finish.
+    mHardware.reset();
+}
+
+TEST_F(GRPCVehicleHardwareUnitTest, TestGetValues) {
+    int64_t testRequestId = 1234;
+    int32_t testPropId = 4321;
+    int32_t testValue = 123456;
+    proto::VehiclePropValueRequests gotRequests;
+    EXPECT_CALL(*mGrpcStub, GetValues(_, _, _))
+            .WillOnce([&gotRequests, testRequestId, testPropId, testValue](
+                              ::grpc::ClientContext* context,
+                              const proto::VehiclePropValueRequests& request,
+                              proto::GetValueResults* response) {
+                gotRequests = request;
+                response->Clear();
+                auto* resultPtr = response->add_results();
+                resultPtr->set_request_id(testRequestId);
+                resultPtr->set_status(proto::StatusCode::OK);
+                auto* valuePtr = resultPtr->mutable_value();
+                valuePtr->set_prop(testPropId);
+                valuePtr->add_int32_values(testValue);
+                return ::grpc::Status::OK;
+            });
+
+    std::vector<aidlvhal::GetValueRequest> requests;
+    requests.push_back(aidlvhal::GetValueRequest{.requestId = testRequestId,
+                                                 .prop = {
+                                                         .prop = testPropId,
+                                                 }});
+
+    std::vector<aidlvhal::GetValueResult> gotResults;
+
+    auto status = mHardware->getValues(
+            std::make_shared<GRPCVehicleHardware::GetValuesCallback>(
+                    [&gotResults](std::vector<aidlvhal::GetValueResult> results) {
+                        for (const auto& result : results) {
+                            gotResults.push_back(result);
+                        }
+                    }),
+            requests);
+
+    ASSERT_EQ(status, aidlvhal::StatusCode::OK);
+    ASSERT_THAT(gotRequests.requests(), SizeIs(1));
+    EXPECT_THAT(gotRequests.requests(0).request_id(), testRequestId);
+    EXPECT_THAT(gotRequests.requests(0).value().prop(), testPropId);
+
+    ASSERT_THAT(gotResults, SizeIs(1));
+    EXPECT_EQ(gotResults[0].requestId, testRequestId);
+    EXPECT_EQ(gotResults[0].status, aidlvhal::StatusCode::OK);
+    EXPECT_EQ(gotResults[0].prop->prop, testPropId);
+    EXPECT_THAT(gotResults[0].prop->value.int32Values, ElementsAre(testValue));
+}
+
+void GRPCVehicleHardwareUnitTest::generatePropertyUpdateEvent(int32_t propId, int64_t timestamp) {
+    // This will be converted to a unique_ptr in StartPropertyValuesStream. The ownership is passed
+    // there.
+    auto clientReader = new MockClientReader<proto::VehiclePropValues>();
+    EXPECT_CALL(*mGrpcStub, StartPropertyValuesStreamRaw(_, _)).WillOnce(Return(clientReader));
+    EXPECT_CALL(*clientReader, Read(_))
+            .WillOnce([timestamp, propId](proto::VehiclePropValues* values) {
+                values->Clear();
+                auto value = values->add_values();
+                value->set_timestamp(timestamp);
+                value->set_prop(propId);
+                return true;
+            })
+            .WillOnce(Return(false));
+    EXPECT_CALL(*clientReader, Finish()).WillOnce(Return(::grpc::Status::OK));
+
+    pollValue();
+}
+
+TEST_F(GRPCVehicleHardwareUnitTest, TestGetValuesOutdatedRetry) {
+    int64_t startTimestamp = elapsedRealtimeNano();
+    int64_t testRequestId = 1234;
+    int32_t testPropId = 4321;
+    int32_t testValue1 = 123456;
+    int32_t testValue2 = 654321;
+    int32_t testTimestamp1 = 1000;
+    int32_t testTimestamp2 = 2000;
+
+    // A property update event for testTimestamp2 happens before getValues returns.
+    generatePropertyUpdateEvent(testPropId, testTimestamp2);
+
+    // GetValues first returns an outdated result, then an up-to-date result.
+    EXPECT_CALL(*mGrpcStub, GetValues(_, _, _))
+            .WillOnce([testRequestId, testPropId, testValue1, testTimestamp1](
+                              ::grpc::ClientContext* context,
+                              const proto::VehiclePropValueRequests& request,
+                              proto::GetValueResults* response) {
+                response->Clear();
+                auto* resultPtr = response->add_results();
+                resultPtr->set_request_id(testRequestId);
+                resultPtr->set_status(proto::StatusCode::OK);
+                auto* valuePtr = resultPtr->mutable_value();
+                valuePtr->set_prop(testPropId);
+                valuePtr->set_timestamp(testTimestamp1);
+                valuePtr->add_int32_values(testValue1);
+                return ::grpc::Status::OK;
+            })
+            .WillOnce([testRequestId, testPropId, testValue2, testTimestamp2](
+                              ::grpc::ClientContext* context,
+                              const proto::VehiclePropValueRequests& request,
+                              proto::GetValueResults* response) {
+                response->Clear();
+                auto* resultPtr = response->add_results();
+                resultPtr->set_request_id(testRequestId);
+                resultPtr->set_status(proto::StatusCode::OK);
+                auto* valuePtr = resultPtr->mutable_value();
+                valuePtr->set_prop(testPropId);
+                valuePtr->set_timestamp(testTimestamp2);
+                valuePtr->add_int32_values(testValue2);
+                return ::grpc::Status::OK;
+            });
+
+    std::vector<aidlvhal::GetValueRequest> requests;
+    requests.push_back(aidlvhal::GetValueRequest{.requestId = testRequestId,
+                                                 .prop = {
+                                                         .prop = testPropId,
+                                                 }});
+
+    std::vector<aidlvhal::GetValueResult> gotResults;
+
+    auto status = mHardware->getValues(
+            std::make_shared<GRPCVehicleHardware::GetValuesCallback>(
+                    [&gotResults](std::vector<aidlvhal::GetValueResult> results) {
+                        for (const auto& result : results) {
+                            gotResults.push_back(result);
+                        }
+                    }),
+            requests);
+
+    ASSERT_EQ(status, aidlvhal::StatusCode::OK);
+    ASSERT_THAT(gotResults, SizeIs(1));
+    EXPECT_EQ(gotResults[0].requestId, testRequestId);
+    EXPECT_EQ(gotResults[0].status, aidlvhal::StatusCode::OK);
+    EXPECT_EQ(gotResults[0].prop->prop, testPropId);
+    EXPECT_THAT(gotResults[0].prop->value.int32Values, ElementsAre(testValue2));
+    EXPECT_GT(gotResults[0].prop->timestamp, startTimestamp);
+    EXPECT_LT(gotResults[0].prop->timestamp, elapsedRealtimeNano());
+}
+
 }  // namespace android::hardware::automotive::vehicle::virtualization
diff --git a/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h b/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h
index f48bb2a..90a7c46 100644
--- a/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h
+++ b/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h
@@ -337,6 +337,9 @@
 // This is for debug purpose only.
 android::base::Result<int32_t> stringToPropId(const std::string& propName);
 
+// This is for debug purpose only. Converts an area's name to its enum definition.
+android::base::Result<int32_t> stringToArea(const std::string& areaName, int32_t propId);
+
 template <typename T>
 void roundToNearestResolution(std::vector<T>& arrayToSanitize, float resolution) {
     if (resolution == 0) {
diff --git a/automotive/vehicle/aidl/impl/utils/common/src/VehicleUtils.cpp b/automotive/vehicle/aidl/impl/utils/common/src/VehicleUtils.cpp
index 4d06e4e..7814c99 100644
--- a/automotive/vehicle/aidl/impl/utils/common/src/VehicleUtils.cpp
+++ b/automotive/vehicle/aidl/impl/utils/common/src/VehicleUtils.cpp
@@ -25,7 +25,13 @@
 
 using ::aidl::android::hardware::automotive::vehicle::StatusCode;
 using ::aidl::android::hardware::automotive::vehicle::toString;
+using ::aidl::android::hardware::automotive::vehicle::VehicleArea;
 using ::aidl::android::hardware::automotive::vehicle::VehicleAreaConfig;
+using ::aidl::android::hardware::automotive::vehicle::VehicleAreaDoor;
+using ::aidl::android::hardware::automotive::vehicle::VehicleAreaMirror;
+using ::aidl::android::hardware::automotive::vehicle::VehicleAreaSeat;
+using ::aidl::android::hardware::automotive::vehicle::VehicleAreaWheel;
+using ::aidl::android::hardware::automotive::vehicle::VehicleAreaWindow;
 using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig;
 using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
 using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyGroup;
@@ -44,7 +50,7 @@
         return instance;
     }
 
-    Result<int32_t> getPropertyId(const std::string& name) {
+    Result<int32_t> getPropertyId(const std::string& name) const {
         auto it = mPropertyIdByName.find(name);
         if (it == mPropertyIdByName.end()) {
             return Error();
@@ -66,6 +72,52 @@
     }
 };
 
+class AreaByNameSingleton {
+  public:
+    static AreaByNameSingleton& getInstance() {
+        static AreaByNameSingleton instance;
+        return instance;
+    }
+
+    Result<int32_t> getArea(const std::string& name, int32_t propId) const {
+        VehicleArea areaType = getPropArea(propId);
+
+        auto mapIt = mAreaByNameByAreaType.find(areaType);
+        if (mapIt == mAreaByNameByAreaType.end()) {
+            return Error() << "Invalid area type for property ID: " << propIdToString(propId);
+        }
+
+        const auto& areaByName = mapIt->second;
+        auto it = areaByName.find(name);
+        if (it == areaByName.end()) {
+            return Error() << "Invalid area name for property " << propIdToString(propId) << ": "
+                           << name;
+        }
+        return it->second;
+    }
+
+    AreaByNameSingleton(AreaByNameSingleton const&) = delete;
+    void operator=(AreaByNameSingleton const&) = delete;
+
+  private:
+    std::unordered_map<VehicleArea, std::unordered_map<std::string, int32_t>> mAreaByNameByAreaType;
+
+    AreaByNameSingleton() {
+        populateMap(VehicleArea::WINDOW, ndk::internal::enum_values<VehicleAreaWindow>);
+        populateMap(VehicleArea::MIRROR, ndk::internal::enum_values<VehicleAreaMirror>);
+        populateMap(VehicleArea::SEAT, ndk::internal::enum_values<VehicleAreaSeat>);
+        populateMap(VehicleArea::DOOR, ndk::internal::enum_values<VehicleAreaDoor>);
+        populateMap(VehicleArea::WHEEL, ndk::internal::enum_values<VehicleAreaWheel>);
+    }
+
+    template <class T, std::size_t N>
+    void populateMap(VehicleArea areaType, std::array<T, N> values) {
+        for (unsigned int i = 0; i < values.size(); i++) {
+            mAreaByNameByAreaType[areaType].emplace(toString(values[i]), toInt(values[i]));
+        }
+    }
+};
+
 }  // namespace
 
 Result<void> checkPropValue(const VehiclePropValue& value, const VehiclePropConfig* config) {
@@ -254,6 +306,10 @@
     return PropertyIdByNameSingleton::getInstance().getPropertyId(propName);
 }
 
+Result<int32_t> stringToArea(const std::string& areaName, int32_t propId) {
+    return AreaByNameSingleton::getInstance().getArea(areaName, propId);
+}
+
 }  // namespace vehicle
 }  // namespace automotive
 }  // namespace hardware
diff --git a/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h b/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
index fa2a310..b58d0f5 100644
--- a/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
+++ b/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
@@ -31,6 +31,7 @@
 #include <android-base/thread_annotations.h>
 #include <android/binder_auto_utils.h>
 
+#include <functional>
 #include <memory>
 #include <mutex>
 #include <shared_mutex>
@@ -138,12 +139,11 @@
     // Only used for testing.
     int32_t mTestInterfaceVersion = 0;
 
-    // mConfigsByPropId and mConfigFile is lazy initialized.
-    mutable std::mutex mConfigInitLock;
-    mutable bool mConfigInit GUARDED_BY(mConfigInitLock) = false;
+    mutable std::atomic<bool> mConfigInit = false;
+    mutable std::shared_timed_mutex mConfigLock;
     mutable std::unordered_map<int32_t, aidlvhal::VehiclePropConfig> mConfigsByPropId
-            GUARDED_BY(mConfigInitLock);
-    mutable std::unique_ptr<ndk::ScopedFileDescriptor> mConfigFile GUARDED_BY(mConfigInitLock);
+            GUARDED_BY(mConfigLock);
+    mutable std::unique_ptr<ndk::ScopedFileDescriptor> mConfigFile GUARDED_BY(mConfigLock);
 
     std::mutex mLock;
     std::unordered_map<const AIBinder*, std::unique_ptr<OnBinderDiedContext>> mOnBinderDiedContexts
@@ -175,7 +175,10 @@
 
     android::base::Result<std::vector<int64_t>> checkDuplicateRequests(
             const std::vector<aidlvhal::SetValueRequest>& requests);
-    VhalResult<void> checkSubscribeOptions(const std::vector<aidlvhal::SubscribeOptions>& options);
+    VhalResult<void> checkSubscribeOptions(
+            const std::vector<aidlvhal::SubscribeOptions>& options,
+            const std::unordered_map<int32_t, aidlvhal::VehiclePropConfig>& configsByPropId)
+            REQUIRES_SHARED(mConfigLock);
 
     VhalResult<void> checkPermissionHelper(const aidlvhal::VehiclePropValue& value,
                                            aidlvhal::VehiclePropertyAccess accessToTest) const;
@@ -184,7 +187,7 @@
 
     VhalResult<void> checkWritePermission(const aidlvhal::VehiclePropValue& value) const;
 
-    android::base::Result<const aidlvhal::VehiclePropConfig*> getConfig(int32_t propId) const;
+    android::base::Result<aidlvhal::VehiclePropConfig> getConfig(int32_t propId) const;
 
     void onBinderDiedWithContext(const AIBinder* clientId);
 
@@ -196,7 +199,7 @@
 
     bool checkDumpPermission();
 
-    bool getAllPropConfigsFromHardwareLocked() const REQUIRES(mConfigInitLock);
+    bool getAllPropConfigsFromHardwareLocked() const EXCLUDES(mConfigLock);
 
     // The looping handler function to process all onBinderDied or onBinderUnlinked events in
     // mBinderEvents.
@@ -209,10 +212,12 @@
 
     int32_t getVhalInterfaceVersion() const;
 
-    // Gets mConfigsByPropId, lazy init it if necessary.
-    const std::unordered_map<int32_t, aidlvhal::VehiclePropConfig>& getConfigsByPropId() const;
-    // Gets mConfigFile, lazy init it if necessary.
-    const ndk::ScopedFileDescriptor* getConfigFile() const;
+    // Gets mConfigsByPropId, lazy init it if necessary. Note that the reference is only valid in
+    // the scope of the callback and it is guaranteed that read lock is obtained during the
+    // callback.
+    void getConfigsByPropId(
+            std::function<void(const std::unordered_map<int32_t, aidlvhal::VehiclePropConfig>&)>
+                    callback) const EXCLUDES(mConfigLock);
 
     // Puts the property change events into a queue so that they can handled in batch.
     static void batchPropertyChangeEvent(
@@ -239,6 +244,12 @@
 
     static void onBinderUnlinked(void* cookie);
 
+    static void parseSubscribeOptions(
+            const std::vector<aidlvhal::SubscribeOptions>& options,
+            const std::unordered_map<int32_t, aidlvhal::VehiclePropConfig>& configsByPropId,
+            std::vector<aidlvhal::SubscribeOptions>& onChangeSubscriptions,
+            std::vector<aidlvhal::SubscribeOptions>& continuousSubscriptions);
+
     // Test-only
     // Set the default timeout for pending requests.
     void setTimeout(int64_t timeoutInNano);
diff --git a/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp b/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
index 9dc039d..e062a28 100644
--- a/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
@@ -95,6 +95,18 @@
     return sampleRateHz;
 }
 
+class SCOPED_CAPABILITY SharedScopedLockAssertion {
+  public:
+    SharedScopedLockAssertion(std::shared_timed_mutex& mutex) ACQUIRE_SHARED(mutex) {}
+    ~SharedScopedLockAssertion() RELEASE() {}
+};
+
+class SCOPED_CAPABILITY UniqueScopedLockAssertion {
+  public:
+    UniqueScopedLockAssertion(std::shared_timed_mutex& mutex) ACQUIRE(mutex) {}
+    ~UniqueScopedLockAssertion() RELEASE() {}
+};
+
 }  // namespace
 
 DefaultVehicleHal::DefaultVehicleHal(std::unique_ptr<IVehicleHardware> vehicleHardware)
@@ -355,68 +367,82 @@
         }
         filteredConfigs.push_back(std::move(config));
     }
-    for (auto& config : filteredConfigs) {
-        mConfigsByPropId[config.prop] = config;
-    }
-    VehiclePropConfigs vehiclePropConfigs;
-    vehiclePropConfigs.payloads = std::move(filteredConfigs);
-    auto result = LargeParcelableBase::parcelableToStableLargeParcelable(vehiclePropConfigs);
-    if (!result.ok()) {
-        ALOGE("failed to convert configs to shared memory file, error: %s, code: %d",
-              result.error().message().c_str(), static_cast<int>(result.error().code()));
-        mConfigFile = nullptr;
-        return false;
+
+    {
+        std::unique_lock<std::shared_timed_mutex> configWriteLock(mConfigLock);
+        UniqueScopedLockAssertion lockAssertion(mConfigLock);
+
+        for (auto& config : filteredConfigs) {
+            mConfigsByPropId[config.prop] = config;
+        }
+        VehiclePropConfigs vehiclePropConfigs;
+        vehiclePropConfigs.payloads = std::move(filteredConfigs);
+        auto result = LargeParcelableBase::parcelableToStableLargeParcelable(vehiclePropConfigs);
+        if (!result.ok()) {
+            ALOGE("failed to convert configs to shared memory file, error: %s, code: %d",
+                  result.error().message().c_str(), static_cast<int>(result.error().code()));
+            mConfigFile = nullptr;
+            return false;
+        }
+
+        if (result.value() != nullptr) {
+            mConfigFile = std::move(result.value());
+        }
     }
 
-    if (result.value() != nullptr) {
-        mConfigFile = std::move(result.value());
-    }
+    mConfigInit = true;
     return true;
 }
 
-const ScopedFileDescriptor* DefaultVehicleHal::getConfigFile() const {
-    std::scoped_lock lockGuard(mConfigInitLock);
+void DefaultVehicleHal::getConfigsByPropId(
+        std::function<void(const std::unordered_map<int32_t, VehiclePropConfig>&)> callback) const {
     if (!mConfigInit) {
         CHECK(getAllPropConfigsFromHardwareLocked())
                 << "Failed to get property configs from hardware";
-        mConfigInit = true;
     }
-    return mConfigFile.get();
-}
 
-const std::unordered_map<int32_t, VehiclePropConfig>& DefaultVehicleHal::getConfigsByPropId()
-        const {
-    std::scoped_lock lockGuard(mConfigInitLock);
-    if (!mConfigInit) {
-        CHECK(getAllPropConfigsFromHardwareLocked())
-                << "Failed to get property configs from hardware";
-        mConfigInit = true;
-    }
-    return mConfigsByPropId;
+    std::shared_lock<std::shared_timed_mutex> configReadLock(mConfigLock);
+    SharedScopedLockAssertion lockAssertion(mConfigLock);
+
+    callback(mConfigsByPropId);
 }
 
 ScopedAStatus DefaultVehicleHal::getAllPropConfigs(VehiclePropConfigs* output) {
-    const ScopedFileDescriptor* configFile = getConfigFile();
-    const auto& configsByPropId = getConfigsByPropId();
-    if (configFile != nullptr) {
+    if (!mConfigInit) {
+        CHECK(getAllPropConfigsFromHardwareLocked())
+                << "Failed to get property configs from hardware";
+    }
+
+    std::shared_lock<std::shared_timed_mutex> configReadLock(mConfigLock);
+    SharedScopedLockAssertion lockAssertion(mConfigLock);
+
+    if (mConfigFile != nullptr) {
         output->payloads.clear();
-        output->sharedMemoryFd.set(dup(configFile->get()));
+        output->sharedMemoryFd.set(dup(mConfigFile->get()));
         return ScopedAStatus::ok();
     }
-    output->payloads.reserve(configsByPropId.size());
-    for (const auto& [_, config] : configsByPropId) {
+
+    output->payloads.reserve(mConfigsByPropId.size());
+    for (const auto& [_, config] : mConfigsByPropId) {
         output->payloads.push_back(config);
     }
     return ScopedAStatus::ok();
 }
 
-Result<const VehiclePropConfig*> DefaultVehicleHal::getConfig(int32_t propId) const {
-    const auto& configsByPropId = getConfigsByPropId();
-    auto it = configsByPropId.find(propId);
-    if (it == configsByPropId.end()) {
-        return Error() << "no config for property, ID: " << propId;
-    }
-    return &(it->second);
+Result<VehiclePropConfig> DefaultVehicleHal::getConfig(int32_t propId) const {
+    Result<VehiclePropConfig> result;
+    getConfigsByPropId([this, &result, propId](const auto& configsByPropId) {
+        SharedScopedLockAssertion lockAssertion(mConfigLock);
+
+        auto it = configsByPropId.find(propId);
+        if (it == configsByPropId.end()) {
+            result = Error() << "no config for property, ID: " << propId;
+            return;
+        }
+        // Copy the VehiclePropConfig
+        result = it->second;
+    });
+    return result;
 }
 
 Result<void> DefaultVehicleHal::checkProperty(const VehiclePropValue& propValue) {
@@ -425,15 +451,15 @@
     if (!result.ok()) {
         return result.error();
     }
-    const VehiclePropConfig* config = result.value();
-    const VehicleAreaConfig* areaConfig = getAreaConfig(propValue, *config);
+    const VehiclePropConfig& config = result.value();
+    const VehicleAreaConfig* areaConfig = getAreaConfig(propValue, config);
     if (!isGlobalProp(propId) && areaConfig == nullptr) {
         // Ignore areaId for global property. For non global property, check whether areaId is
         // allowed. areaId must appear in areaConfig.
         return Error() << "invalid area ID: " << propValue.areaId << " for prop ID: " << propId
                        << ", not listed in config";
     }
-    if (auto result = checkPropValue(propValue, config); !result.ok()) {
+    if (auto result = checkPropValue(propValue, &config); !result.ok()) {
         return Error() << "invalid property value: " << propValue.toString()
                        << ", error: " << getErrorMsg(result);
     }
@@ -659,17 +685,27 @@
 ScopedAStatus DefaultVehicleHal::getPropConfigs(const std::vector<int32_t>& props,
                                                 VehiclePropConfigs* output) {
     std::vector<VehiclePropConfig> configs;
-    const auto& configsByPropId = getConfigsByPropId();
-    for (int32_t prop : props) {
-        auto it = configsByPropId.find(prop);
-        if (it != configsByPropId.end()) {
-            configs.push_back(it->second);
-        } else {
-            return ScopedAStatus::fromServiceSpecificErrorWithMessage(
-                    toInt(StatusCode::INVALID_ARG),
-                    StringPrintf("no config for property, ID: %" PRId32, prop).c_str());
+    ScopedAStatus status = ScopedAStatus::ok();
+    getConfigsByPropId([this, &configs, &status, &props](const auto& configsByPropId) {
+        SharedScopedLockAssertion lockAssertion(mConfigLock);
+
+        for (int32_t prop : props) {
+            auto it = configsByPropId.find(prop);
+            if (it != configsByPropId.end()) {
+                configs.push_back(it->second);
+            } else {
+                status = ScopedAStatus::fromServiceSpecificErrorWithMessage(
+                        toInt(StatusCode::INVALID_ARG),
+                        StringPrintf("no config for property, ID: %" PRId32, prop).c_str());
+                return;
+            }
         }
+    });
+
+    if (!status.isOk()) {
+        return status;
     }
+
     return vectorToStableLargeParcelable(std::move(configs), output);
 }
 
@@ -691,8 +727,8 @@
 }
 
 VhalResult<void> DefaultVehicleHal::checkSubscribeOptions(
-        const std::vector<SubscribeOptions>& options) {
-    const auto& configsByPropId = getConfigsByPropId();
+        const std::vector<SubscribeOptions>& options,
+        const std::unordered_map<int32_t, VehiclePropConfig>& configsByPropId) {
     for (const auto& option : options) {
         int32_t propId = option.propId;
         auto it = configsByPropId.find(propId);
@@ -757,23 +793,15 @@
             }
         }
     }
+
     return {};
 }
 
-ScopedAStatus DefaultVehicleHal::subscribe(const CallbackType& callback,
-                                           const std::vector<SubscribeOptions>& options,
-                                           [[maybe_unused]] int32_t maxSharedMemoryFileCount) {
-    // TODO(b/205189110): Use shared memory file count.
-    if (callback == nullptr) {
-        return ScopedAStatus::fromExceptionCode(EX_NULL_POINTER);
-    }
-    if (auto result = checkSubscribeOptions(options); !result.ok()) {
-        ALOGE("subscribe: invalid subscribe options: %s", getErrorMsg(result).c_str());
-        return toScopedAStatus(result);
-    }
-    std::vector<SubscribeOptions> onChangeSubscriptions;
-    std::vector<SubscribeOptions> continuousSubscriptions;
-    const auto& configsByPropId = getConfigsByPropId();
+void DefaultVehicleHal::parseSubscribeOptions(
+        const std::vector<SubscribeOptions>& options,
+        const std::unordered_map<int32_t, VehiclePropConfig>& configsByPropId,
+        std::vector<SubscribeOptions>& onChangeSubscriptions,
+        std::vector<SubscribeOptions>& continuousSubscriptions) {
     for (const auto& option : options) {
         int32_t propId = option.propId;
         // We have already validate config exists.
@@ -831,6 +859,34 @@
             onChangeSubscriptions.push_back(std::move(optionCopy));
         }
     }
+}
+
+ScopedAStatus DefaultVehicleHal::subscribe(const CallbackType& callback,
+                                           const std::vector<SubscribeOptions>& options,
+                                           [[maybe_unused]] int32_t maxSharedMemoryFileCount) {
+    // TODO(b/205189110): Use shared memory file count.
+    if (callback == nullptr) {
+        return ScopedAStatus::fromExceptionCode(EX_NULL_POINTER);
+    }
+    std::vector<SubscribeOptions> onChangeSubscriptions;
+    std::vector<SubscribeOptions> continuousSubscriptions;
+    ScopedAStatus returnStatus = ScopedAStatus::ok();
+    getConfigsByPropId([this, &returnStatus, &options, &onChangeSubscriptions,
+                        &continuousSubscriptions](const auto& configsByPropId) {
+        SharedScopedLockAssertion lockAssertion(mConfigLock);
+
+        if (auto result = checkSubscribeOptions(options, configsByPropId); !result.ok()) {
+            ALOGE("subscribe: invalid subscribe options: %s", getErrorMsg(result).c_str());
+            returnStatus = toScopedAStatus(result);
+            return;
+        }
+        parseSubscribeOptions(options, configsByPropId, onChangeSubscriptions,
+                              continuousSubscriptions);
+    });
+
+    if (!returnStatus.isOk()) {
+        return returnStatus;
+    }
 
     {
         // Lock to make sure onBinderDied would not be called concurrently.
@@ -891,13 +947,13 @@
         return StatusError(StatusCode::INVALID_ARG) << getErrorMsg(result);
     }
 
-    const VehiclePropConfig* config = result.value();
-    const VehicleAreaConfig* areaConfig = getAreaConfig(value, *config);
+    const VehiclePropConfig& config = result.value();
+    const VehicleAreaConfig* areaConfig = getAreaConfig(value, config);
 
     if (areaConfig == nullptr && !isGlobalProp(propId)) {
         return StatusError(StatusCode::INVALID_ARG) << "no config for area ID: " << value.areaId;
     }
-    if (!hasRequiredAccess(config->access, accessToTest) &&
+    if (!hasRequiredAccess(config.access, accessToTest) &&
         (areaConfig == nullptr || !hasRequiredAccess(areaConfig->access, accessToTest))) {
         return StatusError(StatusCode::ACCESS_DENIED)
                << StringPrintf("Property %" PRId32 " does not have the following access: %" PRId32,
@@ -966,7 +1022,6 @@
     }
     DumpResult result = mVehicleHardware->dump(options);
     if (result.refreshPropertyConfigs) {
-        std::scoped_lock lockGuard(mConfigInitLock);
         getAllPropConfigsFromHardwareLocked();
     }
     dprintf(fd, "%s", (result.buffer + "\n").c_str());
@@ -974,11 +1029,16 @@
         return STATUS_OK;
     }
     dprintf(fd, "Vehicle HAL State: \n");
-    const auto& configsByPropId = getConfigsByPropId();
+    std::unordered_map<int32_t, VehiclePropConfig> configsByPropIdCopy;
+    getConfigsByPropId([this, &configsByPropIdCopy](const auto& configsByPropId) {
+        SharedScopedLockAssertion lockAssertion(mConfigLock);
+
+        configsByPropIdCopy = configsByPropId;
+    });
     {
         std::scoped_lock<std::mutex> lockGuard(mLock);
         dprintf(fd, "Interface version: %" PRId32 "\n", getVhalInterfaceVersion());
-        dprintf(fd, "Containing %zu property configs\n", configsByPropId.size());
+        dprintf(fd, "Containing %zu property configs\n", configsByPropIdCopy.size());
         dprintf(fd, "Currently have %zu getValues clients\n", mGetValuesClients.size());
         dprintf(fd, "Currently have %zu setValues clients\n", mSetValuesClients.size());
         dprintf(fd, "Currently have %zu subscribe clients\n", countSubscribeClients());
diff --git a/bluetooth/a2dp/1.0/Android.bp b/bluetooth/a2dp/1.0/Android.bp
deleted file mode 100644
index 6ffbefa..0000000
--- a/bluetooth/a2dp/1.0/Android.bp
+++ /dev/null
@@ -1,28 +0,0 @@
-// This file is autogenerated by hidl-gen -Landroidbp.
-
-package {
-    // See: http://go/android-license-faq
-    // A large-scale-change added 'default_applicable_licenses' to import
-    // all of the 'license_kinds' from "hardware_interfaces_license"
-    // to get the below license kinds:
-    //   SPDX-license-identifier-Apache-2.0
-    default_applicable_licenses: ["hardware_interfaces_license"],
-}
-
-hidl_interface {
-    name: "android.hardware.bluetooth.a2dp@1.0",
-    root: "android.hardware",
-    srcs: [
-        "types.hal",
-        "IBluetoothAudioHost.hal",
-        "IBluetoothAudioOffload.hal",
-    ],
-    interfaces: [
-        "android.hidl.base@1.0",
-    ],
-    gen_java: false,
-    apex_available: [
-        "//apex_available:platform",
-        "com.android.btservices",
-    ],
-}
diff --git a/bluetooth/a2dp/1.0/IBluetoothAudioHost.hal b/bluetooth/a2dp/1.0/IBluetoothAudioHost.hal
deleted file mode 100644
index 666419d..0000000
--- a/bluetooth/a2dp/1.0/IBluetoothAudioHost.hal
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * 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.
- */
-
-package android.hardware.bluetooth.a2dp@1.0;
-
-/**
- * HAL interface for Bluetooth A2DP Offload functionality where
- * the encoding of the A2DP data packets is offloaded to platform
- * specific encoders. The A2DP control path is maintained in the
- * Bluetooth stack.
- *
- * This interface is from HAL server to HAL client.
- *
- * The HAL server must call into the IBluetoothAudioHost to initiate
- * the start, suspend and stop of the streaming operation. These
- * calls return immediately and the results, if any, are send over
- * the IBluetoothAudioOffload interface.
- */
-
-interface IBluetoothAudioHost {
-    /**
-     * Invoked when the start stream is requested from HAL server
-     * to HAL client. This indicates that the HAL server
-     * has initialized the platform for streaming use case, and the
-     * HAL client can proceed with the streaming procedure. The
-     * result of the operation must be provided by the HAL
-     * client using the IBluetoothAudioOffload interface.
-     */
-    oneway startStream();
-
-    /**
-     * Invoked when the suspend stream is requested from HAL server
-     * to HAL client. This indicates that the HAL server
-     * wants to suspend the streaming procedure. The result of the
-     * operation must be provided by the HAL client using the
-     * IBluetoothAudioOffload interface.
-     */
-    oneway suspendStream();
-
-    /**
-     * Invoked when the stop stream is requested from HAL server
-     * to HAL client. This indicates that the HAL server wants to
-     * stop and reset the streaming procedure. There is no result
-     * provided by the HAL client for this call.
-     */
-    oneway stopStream();
-
-};
diff --git a/bluetooth/a2dp/1.0/IBluetoothAudioOffload.hal b/bluetooth/a2dp/1.0/IBluetoothAudioOffload.hal
deleted file mode 100644
index 52a580f..0000000
--- a/bluetooth/a2dp/1.0/IBluetoothAudioOffload.hal
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * 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.
- */
-
-package android.hardware.bluetooth.a2dp@1.0;
-
-import IBluetoothAudioHost;
-
-/**
- * HAL interface for Bluetooth A2DP Offload functionality where
- * the encoding of the A2DP data packets is offloaded to platform
- * specific encoders. The A2DP control path is maintained in the
- * Bluetooth stack.
- *
- * This interface is from HAL client to HAL server.
- *
- * The HAL client must provide the handle of IBluetoothAudioHost as well
- * as codec configuration to the HAL server, when its connected to an
- * active A2DP Sink device. HAL Server, based on the feedback from the Audio
- * framework must call into the commands provided by the IBluetoothAudioHost.
- * HAL client must call into IBluetoothAudioOffload to provide the status of
- * these commands. Once the device becomes inactive, the HAL client must
- * call the endSession to terminate the session with the HAL server.
- */
-interface IBluetoothAudioOffload {
-
-    /**
-     * Indicates that the HAL client is connected to an A2DP Sink device
-     * and is ready to stream audio. This function is also used to register
-     * the BluetoothAudioHost interface and the provide the current negotiated
-     * codec.
-     *
-     * |endSession| must be called to unregister the interface.
-     *
-     * @param hostIf interface used to request stream control
-     * @param codecConfig Codec configuration as negotiated with the A2DP Sink
-     *    device
-     * @return status one of the following
-     *    SUCCESS if HAL server successfully initializes the platform with the
-     *        given codec configuration
-     *    UNSUPPORTED_CODEC_CONFIGURATION if HAL server cannot initialize the
-     *        platform with the given codec configuration
-     *    FAILURE if HAL server cannot initialize the platform for any other
-     *        reason
-     */
-    startSession(IBluetoothAudioHost hostIf, CodecConfiguration codecConfig) generates (Status status);
-
-    /**
-     * Updates status for start stream request. The HAL client may need
-     * to communicate to Bluetooth Controller and remote Sink device, in which
-     * case it must update with PENDING status. Once the operation is
-     * completed, it must return with either SUCCESS or FAILURE.
-     *
-     * @param status SUCCESS, FAILURE or PENDING
-     */
-    oneway streamStarted(Status status);
-
-    /**
-     * Updates status for suspend stream request. The HAL client may need
-     * to communicate to Bluetooth Controller and remote device, in which case
-     * it must update with PENDING status. Once the operation is completed, it
-     * must return with either SUCCESS or FAILURE.
-     *
-     * @param status SUCCESS, FAILURE or PENDING
-     */
-    oneway streamSuspended(Status status);
-
-    /**
-     * Ends the current A2DP offload session and unregisters the
-     * BluetoothAudioHost interface.
-     */
-    oneway endSession();
-};
diff --git a/bluetooth/a2dp/1.0/default/Android.bp b/bluetooth/a2dp/1.0/default/Android.bp
deleted file mode 100644
index f368dd4..0000000
--- a/bluetooth/a2dp/1.0/default/Android.bp
+++ /dev/null
@@ -1,22 +0,0 @@
-package {
-    // See: http://go/android-license-faq
-    // A large-scale-change added 'default_applicable_licenses' to import
-    // all of the 'license_kinds' from "hardware_interfaces_license"
-    // to get the below license kinds:
-    //   SPDX-license-identifier-Apache-2.0
-    default_applicable_licenses: ["hardware_interfaces_license"],
-}
-
-cc_library_shared {
-    name: "android.hardware.bluetooth.a2dp@1.0-impl.mock",
-    relative_install_path: "hw",
-    vendor: true,
-    srcs: [
-        "BluetoothAudioOffload.cpp",
-    ],
-    shared_libs: [
-        "libhidlbase",
-        "libutils",
-        "android.hardware.bluetooth.a2dp@1.0",
-    ],
-}
diff --git a/bluetooth/a2dp/1.0/default/BluetoothAudioOffload.cpp b/bluetooth/a2dp/1.0/default/BluetoothAudioOffload.cpp
deleted file mode 100644
index 9abb88d..0000000
--- a/bluetooth/a2dp/1.0/default/BluetoothAudioOffload.cpp
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * 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 "BluetoothAudioOffload.h"
-
-namespace android {
-namespace hardware {
-namespace bluetooth {
-namespace a2dp {
-namespace V1_0 {
-namespace implementation {
-
-IBluetoothAudioOffload* HIDL_FETCH_IBluetoothAudioOffload(
-    const char* /* name */) {
-  return new BluetoothAudioOffload();
-}
-
-// Methods from
-// ::android::hardware::bluetooth::a2dp::V1_0::IBluetoothAudioOffload follow.
-Return<::android::hardware::bluetooth::a2dp::V1_0::Status>
-BluetoothAudioOffload::startSession(
-    const sp<::android::hardware::bluetooth::a2dp::V1_0::IBluetoothAudioHost>&
-        hostIf __unused,
-    const ::android::hardware::bluetooth::a2dp::V1_0::CodecConfiguration&
-        codecConfig __unused) {
-  /**
-   * Initialize the audio platform if codecConfiguration is supported.
-   * Save the the IBluetoothAudioHost interface, so that it can be used
-   * later to send stream control commands to the HAL client, based on
-   * interaction with Audio framework.
-   */
-  return ::android::hardware::bluetooth::a2dp::V1_0::Status::FAILURE;
-}
-
-Return<void> BluetoothAudioOffload::streamStarted(
-    ::android::hardware::bluetooth::a2dp::V1_0::Status status __unused) {
-  /**
-   * Streaming on control path has started,
-   * HAL server should start the streaming on data path.
-   */
-  return Void();
-}
-
-Return<void> BluetoothAudioOffload::streamSuspended(
-    ::android::hardware::bluetooth::a2dp::V1_0::Status status __unused) {
-  /**
-   * Streaming on control path has suspend,
-   * HAL server should suspend the streaming on data path.
-   */
-  return Void();
-}
-
-Return<void> BluetoothAudioOffload::endSession() {
-  /**
-   * Cleanup the audio platform as remote A2DP Sink device is no
-   * longer active
-   */
-  return Void();
-}
-
-}  // namespace implementation
-}  // namespace V1_0
-}  // namespace a2dp
-}  // namespace bluetooth
-}  // namespace hardware
-}  // namespace android
diff --git a/bluetooth/a2dp/1.0/default/BluetoothAudioOffload.h b/bluetooth/a2dp/1.0/default/BluetoothAudioOffload.h
deleted file mode 100644
index 16a83c2..0000000
--- a/bluetooth/a2dp/1.0/default/BluetoothAudioOffload.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef ANDROID_HARDWARE_BLUETOOTH_A2DP_V1_0_BLUETOOTHAUDIOOFFLOAD_H
-#define ANDROID_HARDWARE_BLUETOOTH_A2DP_V1_0_BLUETOOTHAUDIOOFFLOAD_H
-
-#include <android/hardware/bluetooth/a2dp/1.0/IBluetoothAudioOffload.h>
-#include <hidl/MQDescriptor.h>
-#include <hidl/Status.h>
-
-namespace android {
-namespace hardware {
-namespace bluetooth {
-namespace a2dp {
-namespace V1_0 {
-namespace implementation {
-
-using ::android::sp;
-using ::android::hardware::hidl_array;
-using ::android::hardware::hidl_memory;
-using ::android::hardware::hidl_string;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-
-struct BluetoothAudioOffload : public IBluetoothAudioOffload {
-  BluetoothAudioOffload() {}
-  // Methods from
-  // ::android::hardware::bluetooth::a2dp::V1_0::IBluetoothAudioOffload follow.
-  Return<::android::hardware::bluetooth::a2dp::V1_0::Status> startSession(
-      const sp<::android::hardware::bluetooth::a2dp::V1_0::IBluetoothAudioHost>&
-          hostIf,
-      const ::android::hardware::bluetooth::a2dp::V1_0::CodecConfiguration&
-          codecConfig) override;
-  Return<void> streamStarted(
-      ::android::hardware::bluetooth::a2dp::V1_0::Status status) override;
-  Return<void> streamSuspended(
-      ::android::hardware::bluetooth::a2dp::V1_0::Status status) override;
-  Return<void> endSession() override;
-};
-
-extern "C" IBluetoothAudioOffload* HIDL_FETCH_IBluetoothAudioOffload(
-    const char* name);
-
-}  // namespace implementation
-}  // namespace V1_0
-}  // namespace a2dp
-}  // namespace bluetooth
-}  // namespace hardware
-}  // namespace android
-
-#endif  // ANDROID_HARDWARE_BLUETOOTH_A2DP_V1_0_BLUETOOTHAUDIOOFFLOAD_H
diff --git a/bluetooth/a2dp/1.0/types.hal b/bluetooth/a2dp/1.0/types.hal
deleted file mode 100644
index 6a430f0..0000000
--- a/bluetooth/a2dp/1.0/types.hal
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * 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.
- */
-
-package android.hardware.bluetooth.a2dp@1.0;
-
-enum Status : uint8_t {
-    SUCCESS,
-    FAILURE,
-    /** codec configuration not supported by the audio platform */
-    UNSUPPORTED_CODEC_CONFIGURATION ,
-    /** operation is pending */
-    PENDING,
-};
-
-enum CodecType : uint32_t {
-    UNKNOWN = 0x00,
-    SBC = 0x01,
-    AAC = 0x02,
-    APTX = 0x04,
-    APTX_HD = 0x08,
-    LDAC = 0x10,
-};
-enum SampleRate : uint32_t {
-    RATE_UNKNOWN = 0x00,
-    RATE_44100 = 0x01,
-    RATE_48000 = 0x02,
-    RATE_88200 = 0x04,
-    RATE_96000 = 0x08,
-    RATE_176400 = 0x10,
-    RATE_192000 = 0x20,
-};
-enum BitsPerSample : uint8_t {
-    BITS_UNKNOWN = 0x00,
-    BITS_16 = 0x01,
-    BITS_24 = 0x02,
-    BITS_32 = 0x04,
-};
-enum ChannelMode : uint8_t {
-    UNKNOWN = 0x00,
-    MONO = 0x01,
-    STEREO = 0x02,
-};
-struct CodecConfiguration {
-    /** Bluetooth A2DP codec */
-    CodecType codecType;
-    /** Sampling rate for encoder */
-    SampleRate sampleRate;
-    /** Bits per sample for encoder */
-    BitsPerSample bitsPerSample;
-    /** Channel mode for encoder */
-    ChannelMode channelMode;
-    /**
-     * The encoded audio bitrate in bits / second.
-     * 0x00000000 - The audio bitrate is not specified / unused
-     * 0x00000001 - 0x00FFFFFF - Encoded audio bitrate in bits/second
-     * 0x01000000 - 0xFFFFFFFF - Reserved
-     */
-    uint32_t encodedAudioBitrate;
-    /** Peer MTU (in octets) */
-    uint16_t peerMtu;
-    union CodecSpecific {
-        /**
-         * SBC Codec specific information
-         * Refer to SBC Codec specific information elements in A2DP v1.3
-         * Profile Specification.
-         */
-        struct SbcData {
-            /** Block length: 4 bits | Subbands: 2 bits | Allocation Method: 2 bits */
-            uint8_t codecParameters;
-            /** Minimum bitpool value */
-            uint8_t minBitpool;
-            /** Maximum bitpool value */
-            uint8_t maxBitpool;
-        } sbcData;
-        struct LdacData {
-            /**
-             * LDAC bitrate index value:
-             * 0x00 - High
-             * 0x01 - Mid
-             * 0x02 - Low
-             * 0x7F - ABR (Adaptive Bit Rate)
-             */
-            uint8_t bitrateIndex;
-        } ldacData;
-    } codecSpecific;
-};
diff --git a/bluetooth/a2dp/1.0/vts/OWNERS b/bluetooth/a2dp/1.0/vts/OWNERS
deleted file mode 100644
index d3aab51..0000000
--- a/bluetooth/a2dp/1.0/vts/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# Bug component: 27441
-include platform/packages/modules/Bluetooth:/OWNERS
-
-cheneyni@google.com
diff --git a/bluetooth/a2dp/1.0/vts/functional/Android.bp b/bluetooth/a2dp/1.0/vts/functional/Android.bp
deleted file mode 100644
index 0d393bc..0000000
--- a/bluetooth/a2dp/1.0/vts/functional/Android.bp
+++ /dev/null
@@ -1,36 +0,0 @@
-//
-// 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.
-//
-
-package {
-    // See: http://go/android-license-faq
-    // A large-scale-change added 'default_applicable_licenses' to import
-    // all of the 'license_kinds' from "hardware_interfaces_license"
-    // to get the below license kinds:
-    //   SPDX-license-identifier-Apache-2.0
-    default_applicable_licenses: ["hardware_interfaces_license"],
-}
-
-cc_test {
-    name: "VtsHalBluetoothA2dpV1_0TargetTest",
-    defaults: ["VtsHalTargetTestDefaults"],
-    srcs: ["VtsHalBluetoothA2dpV1_0TargetTest.cpp"],
-    static_libs: [
-        "android.hardware.bluetooth@1.0",
-        "android.hardware.bluetooth.a2dp@1.0",
-        "libbluetooth-types",
-    ],
-    test_suites: ["general-tests", "vts"],
-}
diff --git a/bluetooth/a2dp/1.0/vts/functional/VtsHalBluetoothA2dpV1_0TargetTest.cpp b/bluetooth/a2dp/1.0/vts/functional/VtsHalBluetoothA2dpV1_0TargetTest.cpp
deleted file mode 100644
index f7fdf31..0000000
--- a/bluetooth/a2dp/1.0/vts/functional/VtsHalBluetoothA2dpV1_0TargetTest.cpp
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * 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.
- */
-
-#define LOG_TAG "bluetooth_a2dp_hidl_hal_test"
-
-#include <android-base/logging.h>
-#include <android/hardware/bluetooth/a2dp/1.0/IBluetoothAudioHost.h>
-#include <android/hardware/bluetooth/a2dp/1.0/IBluetoothAudioOffload.h>
-#include <gtest/gtest.h>
-#include <hardware/bluetooth.h>
-#include <hidl/GtestPrinter.h>
-#include <hidl/MQDescriptor.h>
-#include <hidl/ServiceManagement.h>
-#include <utils/Log.h>
-
-#include <VtsHalHidlTargetCallbackBase.h>
-
-using ::android::sp;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-using ::android::hardware::bluetooth::a2dp::V1_0::BitsPerSample;
-using ::android::hardware::bluetooth::a2dp::V1_0::ChannelMode;
-using ::android::hardware::bluetooth::a2dp::V1_0::CodecConfiguration;
-using ::android::hardware::bluetooth::a2dp::V1_0::CodecType;
-using ::android::hardware::bluetooth::a2dp::V1_0::IBluetoothAudioHost;
-using ::android::hardware::bluetooth::a2dp::V1_0::IBluetoothAudioOffload;
-using ::android::hardware::bluetooth::a2dp::V1_0::SampleRate;
-using ::android::hardware::bluetooth::a2dp::V1_0::Status;
-
-// The main test class for Bluetooth A2DP HIDL HAL.
-class BluetoothA2dpHidlTest : public ::testing::TestWithParam<std::string> {
- public:
-  virtual void SetUp() override {
-    // currently test passthrough mode only
-    audio_offload = IBluetoothAudioOffload::getService(GetParam());
-    ASSERT_NE(audio_offload, nullptr);
-
-    audio_host = new BluetoothAudioHost(*this);
-    ASSERT_NE(audio_host, nullptr);
-
-    codec.codecType = CodecType::AAC;
-    codec.sampleRate = SampleRate::RATE_44100;
-    codec.bitsPerSample = BitsPerSample::BITS_16;
-    codec.channelMode = ChannelMode::STEREO;
-    codec.encodedAudioBitrate = 320000;
-    codec.peerMtu = 1000;
-  }
-
-  virtual void TearDown() override {}
-
-  // A simple test implementation of IBluetoothAudioHost.
-  class BluetoothAudioHost
-      : public ::testing::VtsHalHidlTargetCallbackBase<BluetoothA2dpHidlTest>,
-        public IBluetoothAudioHost {
-    BluetoothA2dpHidlTest& parent_;
-
-   public:
-    BluetoothAudioHost(BluetoothA2dpHidlTest& parent) : parent_(parent){};
-    virtual ~BluetoothAudioHost() = default;
-
-    Return<void> startStream() override {
-      parent_.audio_offload->streamStarted(Status::SUCCESS);
-      return Void();
-    };
-
-    Return<void> suspendStream() override {
-      parent_.audio_offload->streamSuspended(Status::SUCCESS);
-      return Void();
-    };
-
-    Return<void> stopStream() override { return Void(); };
-  };
-
-  // audio_host is for the Audio HAL to send stream start/suspend/stop commands
-  // to Bluetooth
-  sp<IBluetoothAudioHost> audio_host;
-  // audio_offload is for the Bluetooth HAL to report session started/ended and
-  // handled audio stream started/suspended
-  sp<IBluetoothAudioOffload> audio_offload;
-  // codec is the currently used codec
-  CodecConfiguration codec;
-};
-
-// Empty test: Initialize()/Close() are called in SetUp()/TearDown().
-TEST_P(BluetoothA2dpHidlTest, InitializeAndClose) {}
-
-// Test start and end session
-TEST_P(BluetoothA2dpHidlTest, StartAndEndSession) {
-  EXPECT_EQ(Status::SUCCESS, audio_offload->startSession(audio_host, codec));
-  audio_offload->endSession();
-}
-
-INSTANTIATE_TEST_SUITE_P(
-    PerInstance, BluetoothA2dpHidlTest,
-    testing::ValuesIn(android::hardware::getAllHalInstanceNames(
-        IBluetoothAudioOffload::descriptor)),
-    android::hardware::PrintInstanceNameToString);
-
-GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BluetoothA2dpHidlTest);
diff --git a/bluetooth/audio/aidl/Android.bp b/bluetooth/audio/aidl/Android.bp
index f273c7a..ae55fa9 100644
--- a/bluetooth/audio/aidl/Android.bp
+++ b/bluetooth/audio/aidl/Android.bp
@@ -85,12 +85,12 @@
         },
 
     ],
-    frozen: true,
+    frozen: false,
 
 }
 
 // Note: This should always be one version ahead of the last frozen version
-latest_android_hardware_bluetooth_audio = "android.hardware.bluetooth.audio-V4"
+latest_android_hardware_bluetooth_audio = "android.hardware.bluetooth.audio-V5"
 
 cc_defaults {
     name: "latest_android_hardware_bluetooth_audio_ndk_shared",
diff --git a/bluetooth/audio/aidl/default/bluetooth_audio.xml b/bluetooth/audio/aidl/default/bluetooth_audio.xml
index 3561dd1..767bf8f 100644
--- a/bluetooth/audio/aidl/default/bluetooth_audio.xml
+++ b/bluetooth/audio/aidl/default/bluetooth_audio.xml
@@ -1,7 +1,7 @@
 <manifest version="1.0" type="device">
     <hal format="aidl">
         <name>android.hardware.bluetooth.audio</name>
-        <version>4</version>
+        <version>5</version>
         <fqname>IBluetoothAudioProviderFactory/default</fqname>
     </hal>
 </manifest>
diff --git a/bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.cpp b/bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.cpp
index e83cb9e..110a628 100644
--- a/bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.cpp
+++ b/bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.cpp
@@ -195,6 +195,17 @@
   }
 }
 
+static std::optional<CodecSpecificConfigurationLtv> GetConfigurationLtv(
+    const std::vector<CodecSpecificConfigurationLtv>& configurationLtvs,
+    CodecSpecificConfigurationLtv::Tag tag) {
+  for (const auto ltv : configurationLtvs) {
+    if (ltv.getTag() == tag) {
+      return ltv;
+    }
+  }
+  return std::nullopt;
+}
+
 class BluetoothAudioPort : public BnBluetoothAudioPort {
  public:
   BluetoothAudioPort() {}
@@ -2393,17 +2404,6 @@
     return capability;
   }
 
-  std::optional<CodecSpecificConfigurationLtv> GetConfigurationLtv(
-      const std::vector<CodecSpecificConfigurationLtv>& configurationLtvs,
-      CodecSpecificConfigurationLtv::Tag tag) {
-    for (const auto ltv : configurationLtvs) {
-      if (ltv.getTag() == tag) {
-        return ltv;
-      }
-    }
-    return std::nullopt;
-  }
-
   bool IsAseRequirementSatisfiedWithUnknownChannelCount(
       const std::vector<std::optional<AseDirectionRequirement>>&
           ase_requirements,
@@ -2560,6 +2560,67 @@
     return (num_of_satisfied_ase_requirements == ase_requirements.size());
   }
 
+  static void VerifyCodecParameters(
+      ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider::
+          LeAudioAseConfigurationSetting::AseDirectionConfiguration config) {
+    ASSERT_NE(config.aseConfiguration.codecConfiguration.size(), 0lu);
+    ASSERT_TRUE(config.qosConfiguration.has_value());
+
+    int32_t frame_blocks = 1;  // by default 1 if not set
+    int8_t frame_duration = 0;
+    int32_t octets_per_frame = 0;
+    std::bitset<32> allocation_bitmask = 0;
+
+    for (auto const& param : config.aseConfiguration.codecConfiguration) {
+      if (param.getTag() ==
+          ::aidl::android::hardware::bluetooth::audio::
+              CodecSpecificConfigurationLtv::Tag::codecFrameBlocksPerSDU) {
+        frame_blocks = param
+                           .get<::aidl::android::hardware::bluetooth::audio::
+                                    CodecSpecificConfigurationLtv::Tag::
+                                        codecFrameBlocksPerSDU>()
+                           .value;
+      } else if (param.getTag() ==
+                 ::aidl::android::hardware::bluetooth::audio::
+                     CodecSpecificConfigurationLtv::Tag::frameDuration) {
+        frame_duration = static_cast<int8_t>(
+            param.get<::aidl::android::hardware::bluetooth::audio::
+                          CodecSpecificConfigurationLtv::Tag::frameDuration>());
+      } else if (param.getTag() ==
+                 ::aidl::android::hardware::bluetooth::audio::
+                     CodecSpecificConfigurationLtv::Tag::octetsPerCodecFrame) {
+        octets_per_frame = static_cast<int32_t>(
+            param
+                .get<::aidl::android::hardware::bluetooth::audio::
+                         CodecSpecificConfigurationLtv::Tag::
+                             octetsPerCodecFrame>()
+                .value);
+      } else if (param.getTag() == ::aidl::android::hardware::bluetooth::audio::
+                                       CodecSpecificConfigurationLtv::Tag::
+                                           audioChannelAllocation) {
+        allocation_bitmask = static_cast<int32_t>(
+            param
+                .get<::aidl::android::hardware::bluetooth::audio::
+                         CodecSpecificConfigurationLtv::Tag::
+                             audioChannelAllocation>()
+                .bitmask);
+      }
+    }
+
+    ASSERT_NE(frame_blocks, 0);
+    ASSERT_NE(frame_duration, 0);
+    ASSERT_NE(octets_per_frame, 0);
+
+    auto const num_channels_per_cis = allocation_bitmask.count();
+    ASSERT_NE(num_channels_per_cis, 0);
+
+    // Verify if QoS takes the codec frame blocks per SDU into the account
+    ASSERT_TRUE(config.qosConfiguration->sduIntervalUs >=
+                frame_blocks * frame_duration);
+    ASSERT_TRUE(config.qosConfiguration->maxSdu >=
+                (frame_blocks * num_channels_per_cis * octets_per_frame));
+  }
+
   void VerifyIfRequirementsSatisfied(
       const std::vector<LeAudioConfigurationRequirement>& requirements,
       const std::vector<LeAudioAseConfigurationSetting>& configurations) {
@@ -2592,32 +2653,52 @@
           continue;
         }
 
+        bool sink_req_satisfied = false;
+        if (req.sinkAseRequirement) {
+          ASSERT_TRUE(conf.sinkAseConfiguration.has_value());
+          sink_req_satisfied = IsAseRequirementSatisfied(
+              *req.sinkAseRequirement, *conf.sinkAseConfiguration);
+
+          ASSERT_NE(conf.sinkAseConfiguration->size(), 0lu);
+          for (auto const& cfg : conf.sinkAseConfiguration.value()) {
+            ASSERT_TRUE(cfg.has_value());
+            VerifyCodecParameters(cfg.value());
+          }
+        }
+
+        bool source_req_satisfied = false;
+        if (req.sourceAseRequirement) {
+          ASSERT_TRUE(conf.sourceAseConfiguration.has_value());
+          source_req_satisfied = IsAseRequirementSatisfied(
+              *req.sourceAseRequirement, *conf.sourceAseConfiguration);
+
+          ASSERT_NE(conf.sourceAseConfiguration->size(), 0lu);
+          for (auto const& cfg : conf.sourceAseConfiguration.value()) {
+            ASSERT_TRUE(cfg.has_value());
+            VerifyCodecParameters(cfg.value());
+          }
+        }
+
         if (req.sinkAseRequirement && req.sourceAseRequirement) {
           if (!conf.sinkAseConfiguration || !conf.sourceAseConfiguration) {
             continue;
           }
 
-          if (!IsAseRequirementSatisfied(*req.sinkAseRequirement,
-                                         *conf.sinkAseConfiguration) ||
-              !IsAseRequirementSatisfied(*req.sourceAseRequirement,
-                                         *conf.sourceAseConfiguration)) {
+          if (!sink_req_satisfied || !source_req_satisfied) {
             continue;
           }
           num_of_satisfied_requirements +=
               std::bitset<32>(req.audioContext.bitmask).count();
-
           break;
         } else if (req.sinkAseRequirement) {
-          if (!IsAseRequirementSatisfied(*req.sinkAseRequirement,
-                                         *conf.sinkAseConfiguration)) {
+          if (!sink_req_satisfied) {
             continue;
           }
           num_of_satisfied_requirements +=
               std::bitset<32>(req.audioContext.bitmask).count();
           break;
         } else if (req.sourceAseRequirement) {
-          if (!IsAseRequirementSatisfied(*req.sourceAseRequirement,
-                                         *conf.sourceAseConfiguration)) {
+          if (!source_req_satisfied) {
             continue;
           }
           num_of_satisfied_requirements +=
@@ -4089,17 +4170,6 @@
     return media_audio_context;
   }
 
-  std::optional<CodecSpecificConfigurationLtv> GetConfigurationLtv(
-      const std::vector<CodecSpecificConfigurationLtv>& configurationLtvs,
-      CodecSpecificConfigurationLtv::Tag tag) {
-    for (const auto ltv : configurationLtvs) {
-      if (ltv.getTag() == tag) {
-        return ltv;
-      }
-    }
-    return std::nullopt;
-  }
-
   std::optional<CodecSpecificConfigurationLtv::SamplingFrequency>
   GetBisSampleFreq(const LeAudioBisConfiguration& bis_conf) {
     auto sample_freq_ltv = GetConfigurationLtv(
diff --git a/broadcastradio/aidl/vts/Android.bp b/broadcastradio/aidl/vts/Android.bp
index 78c377d..9cfca42 100644
--- a/broadcastradio/aidl/vts/Android.bp
+++ b/broadcastradio/aidl/vts/Android.bp
@@ -44,4 +44,5 @@
         "general-tests",
         "vts",
     ],
+    disable_framework: true,
 }
diff --git a/camera/common/aidl/Android.bp b/camera/common/aidl/Android.bp
index 8f7d19d..b59c92e 100644
--- a/camera/common/aidl/Android.bp
+++ b/camera/common/aidl/Android.bp
@@ -10,6 +10,7 @@
 
 aidl_interface {
     name: "android.hardware.camera.common",
+    host_supported: true,
     vendor_available: true,
     srcs: ["android/hardware/camera/common/*.aidl"],
     frozen: true,
diff --git a/camera/device/aidl/Android.bp b/camera/device/aidl/Android.bp
index 78aefac..f3a3681 100644
--- a/camera/device/aidl/Android.bp
+++ b/camera/device/aidl/Android.bp
@@ -10,6 +10,7 @@
 
 aidl_interface {
     name: "android.hardware.camera.device",
+    host_supported: true,
     vendor_available: true,
     srcs: ["android/hardware/camera/device/*.aidl"],
     frozen: true,
diff --git a/camera/device/aidl/android/hardware/camera/device/ICameraDeviceSession.aidl b/camera/device/aidl/android/hardware/camera/device/ICameraDeviceSession.aidl
index 62a19cf..63ae320 100644
--- a/camera/device/aidl/android/hardware/camera/device/ICameraDeviceSession.aidl
+++ b/camera/device/aidl/android/hardware/camera/device/ICameraDeviceSession.aidl
@@ -575,6 +575,11 @@
      * This can be called at any point after 'processCaptureRequest' in response
      * to camera clients disabling an active repeating request.
      *
+     * Note: The frame number parameter is the latest possible frame number at which the
+     * ongoing repeating request will end. It is possible that the repeating request may end
+     * before the specified frame number due to reasons such as the camera client abandoning
+     * buffers, which is timing dependent.
+     *
      * Performance requirements:
      * The call must not be blocked for extensive periods and should be extremely lightweight. There
      * must be no frame rate degradation or frame jitter introduced.
diff --git a/camera/metadata/aidl/Android.bp b/camera/metadata/aidl/Android.bp
index ae8ba14..a9c1a1a 100644
--- a/camera/metadata/aidl/Android.bp
+++ b/camera/metadata/aidl/Android.bp
@@ -10,6 +10,7 @@
 
 aidl_interface {
     name: "android.hardware.camera.metadata",
+    host_supported: true,
     vendor_available: true,
     srcs: ["android/hardware/camera/metadata/*.aidl"],
     frozen: true,
diff --git a/camera/provider/aidl/Android.bp b/camera/provider/aidl/Android.bp
index 38a8936..c055caa 100644
--- a/camera/provider/aidl/Android.bp
+++ b/camera/provider/aidl/Android.bp
@@ -10,6 +10,7 @@
 
 aidl_interface {
     name: "android.hardware.camera.provider",
+    host_supported: true,
     vendor_available: true,
     srcs: [
         "android/hardware/camera/provider/*.aidl",
diff --git a/cas/1.2/default/android.hardware.cas@1.2-service-lazy.xml b/cas/1.2/default/android.hardware.cas@1.2-service-lazy.xml
index 9b36406..87c9e02 100644
--- a/cas/1.2/default/android.hardware.cas@1.2-service-lazy.xml
+++ b/cas/1.2/default/android.hardware.cas@1.2-service-lazy.xml
@@ -1,5 +1,5 @@
 <manifest version="1.0" type="device">
-    <hal format="hidl">
+    <hal format="hidl" max-level="7">
         <name>android.hardware.cas</name>
         <transport>hwbinder</transport>
         <version>1.2</version>
diff --git a/cas/1.2/default/android.hardware.cas@1.2-service.xml b/cas/1.2/default/android.hardware.cas@1.2-service.xml
index 9b36406..87c9e02 100644
--- a/cas/1.2/default/android.hardware.cas@1.2-service.xml
+++ b/cas/1.2/default/android.hardware.cas@1.2-service.xml
@@ -1,5 +1,5 @@
 <manifest version="1.0" type="device">
-    <hal format="hidl">
+    <hal format="hidl" max-level="7">
         <name>android.hardware.cas</name>
         <transport>hwbinder</transport>
         <version>1.2</version>
diff --git a/common/aidl/Android.bp b/common/aidl/Android.bp
index 1f5742d..904a3d9 100644
--- a/common/aidl/Android.bp
+++ b/common/aidl/Android.bp
@@ -20,16 +20,18 @@
     backend: {
         java: {
             sdk_version: "module_current",
+            apex_available: [
+                "//apex_available:anyapex",
+                "//apex_available:platform",
+            ],
         },
         cpp: {
             enabled: false,
         },
         ndk: {
             apex_available: [
+                "//apex_available:anyapex",
                 "//apex_available:platform",
-                "com.android.btservices",
-                "com.android.media.swcodec",
-                "com.android.neuralnetworks",
             ],
             min_sdk_version: "29",
         },
diff --git a/common/support/Android.bp b/common/support/Android.bp
index 56700fa..aba5d6b 100644
--- a/common/support/Android.bp
+++ b/common/support/Android.bp
@@ -24,9 +24,8 @@
         "libcutils",
     ],
     apex_available: [
+        "//apex_available:anyapex",
         "//apex_available:platform",
-        "com.android.neuralnetworks",
-        "com.android.media.swcodec",
     ],
     min_sdk_version: "29",
 }
diff --git a/compatibility_matrices/compatibility_matrix.202504.xml b/compatibility_matrices/compatibility_matrix.202504.xml
index 0e714a4..ee62163 100644
--- a/compatibility_matrices/compatibility_matrix.202504.xml
+++ b/compatibility_matrices/compatibility_matrix.202504.xml
@@ -1,7 +1,7 @@
 <compatibility-matrix version="1.0" type="framework" level="202504">
     <hal format="aidl">
         <name>android.hardware.audio.core</name>
-        <version>1-2</version>
+        <version>1-3</version>
         <interface>
             <name>IModule</name>
             <instance>default</instance>
@@ -20,7 +20,7 @@
     </hal>
     <hal format="aidl">
         <name>android.hardware.audio.effect</name>
-        <version>1-2</version>
+        <version>1-3</version>
         <interface>
             <name>IFactory</name>
             <instance>default</instance>
@@ -28,7 +28,7 @@
     </hal>
     <hal format="aidl">
         <name>android.hardware.audio.sounddose</name>
-        <version>1-2</version>
+        <version>1-3</version>
         <interface>
             <name>ISoundDoseFactory</name>
             <instance>default</instance>
@@ -44,7 +44,7 @@
     </hal>
     <hal format="aidl">
         <name>android.hardware.automotive.audiocontrol</name>
-        <version>2-4</version>
+        <version>2-5</version>
         <interface>
             <name>IAudioControl</name>
             <instance>default</instance>
@@ -132,7 +132,7 @@
     </hal>
     <hal format="aidl">
         <name>android.hardware.bluetooth.audio</name>
-        <version>3-4</version>
+        <version>3-5</version>
         <interface>
             <name>IBluetoothAudioProviderFactory</name>
             <instance>default</instance>
@@ -542,7 +542,7 @@
     </hal>
     <hal format="aidl">
          <name>android.hardware.soundtrigger3</name>
-         <version>1-2</version>
+         <version>1-3</version>
          <interface>
              <name>ISoundTriggerHw</name>
              <instance>default</instance>
diff --git a/compatibility_matrices/exclude/fcm_exclude.cpp b/compatibility_matrices/exclude/fcm_exclude.cpp
index 08ef49b..fca9e1c 100644
--- a/compatibility_matrices/exclude/fcm_exclude.cpp
+++ b/compatibility_matrices/exclude/fcm_exclude.cpp
@@ -164,6 +164,7 @@
             // AIDL
             "android.hardware.audio.core.sounddose@1",
             "android.hardware.audio.core.sounddose@2",
+            "android.hardware.audio.core.sounddose@3",
 
             // Deprecated HALs.
             "android.hardware.bluetooth.audio@1",
diff --git a/graphics/common/aidl/Android.bp b/graphics/common/aidl/Android.bp
index 4f5c3d9..c28da4c 100644
--- a/graphics/common/aidl/Android.bp
+++ b/graphics/common/aidl/Android.bp
@@ -24,15 +24,18 @@
         java: {
             enabled: true,
             platform_apis: true,
+            apex_available: [
+                "//apex_available:anyapex",
+                "//apex_available:platform",
+            ],
         },
         cpp: {
             enabled: false,
         },
         ndk: {
             apex_available: [
+                "//apex_available:anyapex",
                 "//apex_available:platform",
-                "com.android.media.swcodec",
-                "com.android.neuralnetworks",
             ],
             min_sdk_version: "29",
         },
diff --git a/keymaster/3.0/default/Android.bp b/keymaster/3.0/default/Android.bp
new file mode 100644
index 0000000..4018cc0
--- /dev/null
+++ b/keymaster/3.0/default/Android.bp
@@ -0,0 +1,57 @@
+// Copyright (C) 2024 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+    // See: http://go/android-license-faq
+    default_applicable_licenses: [
+        "hardware_interfaces_license",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.keymaster@3.0-impl",
+    proprietary: true,
+    relative_install_path: "hw",
+    srcs: ["KeymasterDevice.cpp"],
+    shared_libs: [
+        "android.hardware.keymaster@3.0",
+        "libcrypto",
+        "libhardware",
+        "libhidlbase",
+        "libkeymaster_portable",
+        "libkeymaster3device",
+        "liblog",
+        "libpuresoftkeymasterdevice",
+        "libsoftkeymasterdevice",
+        "libutils",
+    ],
+}
+
+cc_binary {
+    name: "android.hardware.keymaster@3.0-service",
+    relative_install_path: "hw",
+    proprietary: true,
+    init_rc: ["android.hardware.keymaster@3.0-service.rc"],
+    srcs: ["service.cpp"],
+    shared_libs: [
+        "android.hardware.keymaster@3.0",
+        "libbase",
+        "libcutils",
+        "libdl",
+        "libhardware",
+        "libhidlbase",
+        "liblog",
+        "libutils",
+    ],
+}
diff --git a/keymaster/3.0/default/Android.mk b/keymaster/3.0/default/Android.mk
deleted file mode 100644
index 053ad67..0000000
--- a/keymaster/3.0/default/Android.mk
+++ /dev/null
@@ -1,48 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := android.hardware.keymaster@3.0-impl
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../../NOTICE
-LOCAL_PROPRIETARY_MODULE := true
-LOCAL_MODULE_RELATIVE_PATH := hw
-LOCAL_SRC_FILES := \
-    KeymasterDevice.cpp \
-
-LOCAL_SHARED_LIBRARIES := \
-    liblog \
-    libsoftkeymasterdevice \
-    libcrypto \
-    libkeymaster_portable \
-    libpuresoftkeymasterdevice \
-    libkeymaster3device \
-    libhidlbase \
-    libutils \
-    libhardware \
-    android.hardware.keymaster@3.0
-
-include $(BUILD_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE_RELATIVE_PATH := hw
-LOCAL_PROPRIETARY_MODULE := true
-LOCAL_MODULE := android.hardware.keymaster@3.0-service
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../../NOTICE
-LOCAL_INIT_RC := android.hardware.keymaster@3.0-service.rc
-LOCAL_SRC_FILES := \
-    service.cpp
-
-LOCAL_SHARED_LIBRARIES := \
-    liblog \
-    libcutils \
-    libdl \
-    libbase \
-    libutils \
-    libhardware \
-    libhidlbase \
-    android.hardware.keymaster@3.0
-
-include $(BUILD_EXECUTABLE)
diff --git a/security/keymint/support/fuzzer/Android.bp b/security/keymint/support/fuzzer/Android.bp
index 1b1a580..2fa82ec 100644
--- a/security/keymint/support/fuzzer/Android.bp
+++ b/security/keymint/support/fuzzer/Android.bp
@@ -48,6 +48,20 @@
     ],
 }
 
+cc_defaults {
+    name: "keymint_remote_fuzzer_defaults",
+    static_libs: [
+        "libkeymint_remote_prov_support",
+        "android.hardware.security.rkp-V3-ndk",
+    ],
+    shared_libs: [
+        "libcppbor",
+        "libcppcose_rkp",
+        "libjsoncpp",
+        "libkeymaster_portable",
+    ],
+}
+
 cc_fuzz {
     name: "keymint_attestation_fuzzer",
     srcs: [
@@ -67,3 +81,25 @@
         "keymint_fuzzer_defaults",
     ],
 }
+
+cc_fuzz {
+    name: "keymint_remote_prov_fuzzer",
+    srcs: [
+        "keymint_remote_prov_fuzzer.cpp",
+    ],
+    defaults: [
+        "keymint_fuzzer_defaults",
+        "keymint_remote_fuzzer_defaults",
+    ],
+}
+
+cc_fuzz {
+    name: "keymint_rkpsupport_fuzzer",
+    srcs: [
+        "keymint_rkpsupport_fuzzer.cpp",
+    ],
+    defaults: [
+        "keymint_fuzzer_defaults",
+        "keymint_remote_fuzzer_defaults",
+    ],
+}
diff --git a/security/keymint/support/fuzzer/README.md b/security/keymint/support/fuzzer/README.md
index d41af08..4cf6927 100644
--- a/security/keymint/support/fuzzer/README.md
+++ b/security/keymint/support/fuzzer/README.md
@@ -12,6 +12,8 @@
 ## Table of contents
 + [keymint_attestation_fuzzer](#KeyMintAttestation)
 + [keymint_authSet_fuzzer](#KeyMintAuthSet)
++ [keymint_remote_prov_fuzzer](#KeyMintRemoteProv)
++ [keymint_rkpsupport_fuzzer](#KeyMintRemoteKeyProvSupport)
 
 # <a name="KeyMintAttestation"></a> Fuzzer for KeyMintAttestation
 KeyMintAttestation supports the following parameters:
@@ -77,3 +79,53 @@
 $ adb sync data
 $ adb shell /data/fuzz/arm64/keymint_authSet_fuzzer/keymint_authSet_fuzzer
 ```
+
+# <a name="KeyMintRemoteProv"></a> Fuzzer for KeyMintRemoteProv
+KeyMintRemoteProv supports the following parameters:
+1. ChallengeSize(parameter name: "challengeSize")
+2. Challenge(parameter name: "challenge")
+3. NumKeys(parameter name: "numKeys")
+
+| Parameter| Valid Values| Configured Value|
+|------------- |--------------| -------------------- |
+|`challengeSize`| `uint8_t` |Value obtained from FuzzedDataProvider|
+|`challenge`| `std::vector<uint8_t>` |Value obtained from FuzzedDataProvider|
+|`numKeys`| `uint8_t` |Value obtained from FuzzedDataProvider|
+
+#### Steps to run
+1. Build the fuzzer
+```
+$ mm -j$(nproc) keymint_remote_prov_fuzzer
+```
+2. Run on device
+```
+$ adb sync data
+$ adb shell /data/fuzz/arm64/keymint_remote_prov_fuzzer/keymint_remote_prov_fuzzer
+```
+
+# <a name="KeyMintRemoteKeyProvSupport"></a> Fuzzer for KeyMintRemoteKeyProvSupport
+KeyMintRemoteKeyProvSupport supports the following parameters:
+1. SupportedEekCurve(parameter name: "supportedEekCurve")
+2. Length(parameter name: "length")
+3. SerialNumberProp(parameter name: "serialNoProp")
+4. InstanceName(parameter name: "instanceName")
+5. Value(parameter name: "value")
+
+| Parameter| Valid Values| Configured Value|
+|------------- |--------------| -------------------- |
+|`supportedEekCurve`| `uint8_t` |Value obtained from FuzzedDataProvider|
+|`length`| `uint8_t` |Value obtained from FuzzedDataProvider|
+|`serialNoProp`| `string` |Value obtained from FuzzedDataProvider|
+|`instanceName`| `string` |Value obtained from FuzzedDataProvider|
+|`value`| `uint8_t` |Value obtained from FuzzedDataProvider|
+
+#### Steps to run
+1. Build the fuzzer
+```
+$ mm -j$(nproc) keymint_rkpsupport_fuzzer
+```
+2. Run on device
+```
+$ adb sync data
+$ adb shell /data/fuzz/arm64/keymint_rkpsupport_fuzzer/keymint_rkpsupport_fuzzer
+```
diff --git a/security/keymint/support/fuzzer/keymint_remote_prov_fuzzer.cpp b/security/keymint/support/fuzzer/keymint_remote_prov_fuzzer.cpp
new file mode 100644
index 0000000..6bd986c
--- /dev/null
+++ b/security/keymint/support/fuzzer/keymint_remote_prov_fuzzer.cpp
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2024 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/binder_manager.h>
+#include <fuzzer/FuzzedDataProvider.h>
+#include <remote_prov/remote_prov_utils.h>
+#include <utils/Log.h>
+
+namespace android::hardware::security::keymint_support::fuzzer {
+
+using namespace cppcose;
+using namespace aidl::android::hardware::security::keymint;
+using namespace aidl::android::hardware::security::keymint::remote_prov;
+
+constexpr size_t kMinSize = 0;
+constexpr size_t kSupportedNumKeys = 4;
+constexpr size_t kChallengeSize = 64;
+constexpr size_t kMaxBytes = 128;
+const std::string kServiceName =
+        "android.hardware.security.keymint.IRemotelyProvisionedComponent/default";
+
+std::shared_ptr<IRemotelyProvisionedComponent> gRPC = nullptr;
+
+class KeyMintRemoteProv {
+  public:
+    KeyMintRemoteProv(const uint8_t* data, size_t size) : mFdp(data, size){};
+    void process();
+
+  private:
+    std::vector<uint8_t> ExtractPayloadValue(const MacedPublicKey& macedPubKey);
+    FuzzedDataProvider mFdp;
+};
+
+std::vector<uint8_t> KeyMintRemoteProv::ExtractPayloadValue(const MacedPublicKey& macedPubKey) {
+    std::vector<uint8_t> payloadValue;
+
+    auto [coseMac0, _, mac0ParseErr] = cppbor::parse(macedPubKey.macedKey);
+    if (coseMac0) {
+        // The payload is a bstr holding an encoded COSE_Key
+        auto payload = coseMac0->asArray()->get(kCoseMac0Payload)->asBstr();
+        if (payload != nullptr) {
+            payloadValue = payload->value();
+        }
+    }
+    return payloadValue;
+}
+
+void KeyMintRemoteProv::process() {
+    std::vector<MacedPublicKey> keysToSign = std::vector<MacedPublicKey>(
+            mFdp.ConsumeIntegralInRange<uint8_t>(kMinSize, kSupportedNumKeys));
+    cppbor::Array cborKeysToSign;
+    for (auto& key : keysToSign) {
+        // TODO: b/350649166 - Randomize keysToSign
+        std::vector<uint8_t> privateKeyBlob;
+        gRPC->generateEcdsaP256KeyPair(false /* testMode */, &key, &privateKeyBlob);
+
+        std::vector<uint8_t> payloadValue = ExtractPayloadValue(key);
+        cborKeysToSign.add(cppbor::EncodedItem(payloadValue));
+    }
+
+    uint8_t challengeSize = mFdp.ConsumeIntegralInRange<uint8_t>(kMinSize, kChallengeSize);
+    std::vector<uint8_t> challenge = mFdp.ConsumeBytes<uint8_t>(challengeSize);
+
+    std::vector<uint8_t> csr;
+    gRPC->generateCertificateRequestV2(keysToSign, challenge, &csr);
+
+    while (mFdp.remaining_bytes()) {
+        auto invokeProvAPI = mFdp.PickValueInArray<const std::function<void()>>({
+                [&]() { verifyFactoryCsr(cborKeysToSign, csr, gRPC.get(), challenge); },
+                [&]() { verifyProductionCsr(cborKeysToSign, csr, gRPC.get(), challenge); },
+                [&]() { isCsrWithProperDiceChain(csr); },
+        });
+        invokeProvAPI();
+    }
+}
+
+extern "C" int LLVMFuzzerInitialize(int /* *argc */, char /* ***argv */) {
+    ::ndk::SpAIBinder binder(AServiceManager_waitForService(kServiceName.c_str()));
+    gRPC = IRemotelyProvisionedComponent::fromBinder(binder);
+    LOG_ALWAYS_FATAL_IF(!gRPC, "Failed to get IRemotelyProvisionedComponent instance.");
+    return 0;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    KeyMintRemoteProv kmRemoteProv(data, size);
+    kmRemoteProv.process();
+    return 0;
+}
+
+}  // namespace android::hardware::security::keymint_support::fuzzer
diff --git a/security/keymint/support/fuzzer/keymint_rkpsupport_fuzzer.cpp b/security/keymint/support/fuzzer/keymint_rkpsupport_fuzzer.cpp
new file mode 100644
index 0000000..778d48f
--- /dev/null
+++ b/security/keymint/support/fuzzer/keymint_rkpsupport_fuzzer.cpp
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2024 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 <fuzzer/FuzzedDataProvider.h>
+#include <remote_prov/remote_prov_utils.h>
+
+namespace android::hardware::security::keymint_support::fuzzer {
+
+using namespace aidl::android::hardware::security::keymint::remote_prov;
+
+constexpr size_t kMaxBytes = 128;
+
+class KeyMintRemoteKeyProvSupport {
+  public:
+    KeyMintRemoteKeyProvSupport(const uint8_t* data, size_t size) : mFdp(data, size) {}
+    void process();
+
+  private:
+    FuzzedDataProvider mFdp;
+};
+
+void KeyMintRemoteKeyProvSupport::process() {
+    while (mFdp.remaining_bytes()) {
+        auto invokeProvAPI = mFdp.PickValueInArray<const std::function<void()>>({
+                [&]() {
+                    std::vector<uint8_t> eekId;
+                    if (mFdp.ConsumeBool()) {
+                        eekId = mFdp.ConsumeBytes<uint8_t>(kMaxBytes);
+                    }
+                    generateEekChain(mFdp.ConsumeIntegral<uint8_t>() /* supportedEekCurve */,
+                                     mFdp.ConsumeIntegral<uint8_t>() /* length */, eekId);
+                },
+                [&]() { getProdEekChain(mFdp.ConsumeIntegral<uint8_t>() /* supportedEekCurve */); },
+                [&]() {
+                    std::string serialNoProp = mFdp.ConsumeRandomLengthString(kMaxBytes);
+                    std::string instanceName = mFdp.ConsumeRandomLengthString(kMaxBytes);
+                    cppbor::Array array;
+                    array.add(mFdp.ConsumeIntegral<uint8_t>() /* value */);
+                    jsonEncodeCsrWithBuild(instanceName, array, serialNoProp);
+                },
+        });
+        invokeProvAPI();
+    }
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    KeyMintRemoteKeyProvSupport keymintRKPSupport(data, size);
+    keymintRKPSupport.process();
+    return 0;
+}
+
+}  // namespace android::hardware::security::keymint_support::fuzzer
diff --git a/security/keymint/support/remote_prov_utils.cpp b/security/keymint/support/remote_prov_utils.cpp
index b74fd59..6638775 100644
--- a/security/keymint/support/remote_prov_utils.cpp
+++ b/security/keymint/support/remote_prov_utils.cpp
@@ -65,9 +65,9 @@
     return privKey;
 }
 
-ErrMsgOr<bytevec> ecKeyGetPublicKey(const EC_KEY* ecKey) {
+ErrMsgOr<bytevec> ecKeyGetPublicKey(const EC_KEY* ecKey, const int nid) {
     // Extract public key.
-    auto group = EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
+    auto group = EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(nid));
     if (group.get() == nullptr) {
         return "Error creating EC group by curve name";
     }
@@ -123,11 +123,12 @@
     int keyType = EVP_PKEY_base_id(pubKey.get());
     switch (keyType) {
         case EVP_PKEY_EC: {
+            int nid = EVP_PKEY_bits(pubKey.get()) == 384 ? NID_secp384r1 : NID_X9_62_prime256v1;
             auto ecKey = EC_KEY_Ptr(EVP_PKEY_get1_EC_KEY(pubKey.get()));
             if (ecKey.get() == nullptr) {
                 return "Failed to get ec key";
-            }
-            return ecKeyGetPublicKey(ecKey.get());
+          }
+          return ecKeyGetPublicKey(ecKey.get(), nid);
         }
         case EVP_PKEY_ED25519: {
             bytevec rawPubKey;
@@ -165,7 +166,7 @@
     auto privKey = ecKeyGetPrivateKey(ec_key.get());
     if (!privKey) return privKey.moveMessage();
 
-    auto pubKey = ecKeyGetPublicKey(ec_key.get());
+    auto pubKey = ecKeyGetPublicKey(ec_key.get(), NID_X9_62_prime256v1);
     if (!pubKey) return pubKey.moveMessage();
 
     return std::make_tuple(pubKey.moveValue(), privKey.moveValue());
@@ -824,7 +825,7 @@
         }
         if (i == chain.size() - 1) {
             auto key = getRawPublicKey(pubKey);
-            if (!key) key.moveMessage();
+            if (!key) return key.moveMessage();
             rawPubKey = key.moveValue();
         }
     }
diff --git a/sensors/aidl/default/include/sensors-impl/Sensors.h b/sensors/aidl/default/include/sensors-impl/Sensors.h
index 2adbc9d..c90db69 100644
--- a/sensors/aidl/default/include/sensors-impl/Sensors.h
+++ b/sensors/aidl/default/include/sensors-impl/Sensors.h
@@ -97,9 +97,13 @@
             return;
         }
         if (mEventQueue->write(&events.front(), events.size())) {
+            if (mEventQueueFlag == nullptr) {
+                // Don't take the wake lock if we can't wake the receiver to avoid holding it
+                // indefinitely.
+                return;
+            }
             mEventQueueFlag->wake(
                     static_cast<uint32_t>(BnSensors::EVENT_QUEUE_FLAG_BITS_READ_AND_PROCESS));
-
             if (wakeup) {
                 // Keep track of the number of outstanding WAKE_UP events in order to properly hold
                 // a wake lock until the framework has secured a wake lock
diff --git a/soundtrigger/aidl/Android.bp b/soundtrigger/aidl/Android.bp
index af9a5fc..b8b6915 100644
--- a/soundtrigger/aidl/Android.bp
+++ b/soundtrigger/aidl/Android.bp
@@ -35,7 +35,7 @@
             sdk_version: "module_current",
         },
     },
-    frozen: true,
+    frozen: false,
     versions_with_info: [
         {
             version: "1",
@@ -52,7 +52,7 @@
 }
 
 // Note: This should always be one version ahead of the last frozen version
-latest_android_hardware_soundtrigger3 = "android.hardware.soundtrigger3-V2"
+latest_android_hardware_soundtrigger3 = "android.hardware.soundtrigger3-V3"
 
 // Modules that depend on android.hardware.soundtrigger3 directly can include
 // the following java_defaults to avoid explicitly managing dependency versions
diff --git a/tests/extension/vibrator/aidl/Android.bp b/tests/extension/vibrator/aidl/Android.bp
index 0306dca..9d6fdbc 100644
--- a/tests/extension/vibrator/aidl/Android.bp
+++ b/tests/extension/vibrator/aidl/Android.bp
@@ -37,6 +37,12 @@
         java: {
             enabled: false,
         },
+        ndk: {
+            enabled: true,
+        },
+        cpp: {
+            enabled: false,
+        },
     },
     frozen: true,
     versions_with_info: [
diff --git a/tests/extension/vibrator/aidl/client/Android.bp b/tests/extension/vibrator/aidl/client/Android.bp
index 284ac74..00510b7 100644
--- a/tests/extension/vibrator/aidl/client/Android.bp
+++ b/tests/extension/vibrator/aidl/client/Android.bp
@@ -16,16 +16,10 @@
     srcs: [
         // system code has the option to use the unstable C++ libbinder API
         // or the NDK one. For maximum code portability, using the ndk client
-        // makes the most sense, but both are provided here as an example.
-        "test-cpp-client.cpp",
+        // makes the most sense.
         "test-ndk-client.cpp",
     ],
     shared_libs: [
-        "libbinder",
-        "libutils",
-        "android.hardware.vibrator-V2-cpp",
-        "android.hardware.tests.extension.vibrator-V1-cpp",
-
         "libbinder_ndk",
         "android.hardware.vibrator-V2-ndk",
         "android.hardware.tests.extension.vibrator-V1-ndk",
diff --git a/tests/extension/vibrator/aidl/client/test-cpp-client.cpp b/tests/extension/vibrator/aidl/client/test-cpp-client.cpp
deleted file mode 100644
index 015a345..0000000
--- a/tests/extension/vibrator/aidl/client/test-cpp-client.cpp
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <android/hardware/tests/extension/vibrator/ICustomVibrator.h>
-#include <android/hardware/vibrator/IVibrator.h>
-#include <binder/IInterface.h>
-#include <binder/IServiceManager.h>
-#include <gtest/gtest.h>
-
-using android::checked_interface_cast;
-using android::IBinder;
-using android::IInterface;
-using android::OK;
-using android::sp;
-using android::waitForVintfService;
-using android::hardware::tests::extension::vibrator::Directionality;
-using android::hardware::tests::extension::vibrator::ICustomVibrator;
-using android::hardware::vibrator::IVibrator;
-
-TEST(Cpp, CallRootMethod) {
-    sp<IVibrator> vib = waitForVintfService<IVibrator>();
-    ASSERT_NE(nullptr, vib.get());
-    ASSERT_TRUE(vib->off().isOk());
-}
-
-TEST(Cpp, CallExtMethod) {
-    // normally you would want to cache this
-    sp<IVibrator> vib = waitForVintfService<IVibrator>();
-    ASSERT_NE(nullptr, vib.get());
-
-    // getting the extension
-    sp<IBinder> ext;
-    ASSERT_EQ(OK, IInterface::asBinder(vib)->getExtension(&ext));
-    sp<ICustomVibrator> cvib = checked_interface_cast<ICustomVibrator>(ext);
-    ASSERT_NE(nullptr, cvib.get());
-
-    // calling extension method
-    ASSERT_TRUE(cvib->setDirectionality(Directionality::TRANSVERSE).isOk());
-}
diff --git a/tests/extension/vibrator/aidl/client/test-ndk-client.cpp b/tests/extension/vibrator/aidl/client/test-ndk-client.cpp
index c846495..4dd86e8 100644
--- a/tests/extension/vibrator/aidl/client/test-ndk-client.cpp
+++ b/tests/extension/vibrator/aidl/client/test-ndk-client.cpp
@@ -28,7 +28,7 @@
 static const std::string kInstance = std::string() + IVibrator::descriptor + "/default";
 
 TEST(Ndk, CallRootMethod) {
-    SpAIBinder vibBinder = SpAIBinder(AServiceManager_getService(kInstance.c_str()));
+    SpAIBinder vibBinder = SpAIBinder(AServiceManager_waitForService(kInstance.c_str()));
     ASSERT_NE(nullptr, vibBinder.get());
     std::shared_ptr<IVibrator> vib = IVibrator::fromBinder(vibBinder);
     ASSERT_NE(nullptr, vib.get());
@@ -38,7 +38,7 @@
 TEST(Ndk, CallExtMethod) {
     // normally you would want to cache this
     //
-    SpAIBinder vibBinder = SpAIBinder(AServiceManager_getService(kInstance.c_str()));
+    SpAIBinder vibBinder = SpAIBinder(AServiceManager_waitForService(kInstance.c_str()));
     ASSERT_NE(nullptr, vibBinder.get());
     std::shared_ptr<IVibrator> vib = IVibrator::fromBinder(vibBinder);
     ASSERT_NE(nullptr, vib.get());
diff --git a/tests/msgq/1.0/ITestMsgQ.hal b/tests/msgq/1.0/ITestMsgQ.hal
index 0cf9c7c..62bef0a 100644
--- a/tests/msgq/1.0/ITestMsgQ.hal
+++ b/tests/msgq/1.0/ITestMsgQ.hal
@@ -18,8 +18,8 @@
 
 interface ITestMsgQ {
     enum EventFlagBits : uint32_t {
-        FMQ_NOT_EMPTY = 1 << 0,
-        FMQ_NOT_FULL  = 1 << 1,
+        FMQ_NOT_FULL = 1 << 0,
+        FMQ_NOT_EMPTY  = 1 << 1,
     };
 
     /**
diff --git a/vibrator/aidl/Android.bp b/vibrator/aidl/Android.bp
index b5199e2..fe76450 100644
--- a/vibrator/aidl/Android.bp
+++ b/vibrator/aidl/Android.bp
@@ -20,6 +20,12 @@
         java: {
             sdk_version: "system_current",
         },
+        ndk: {
+            enabled: true,
+        },
+        cpp: {
+            enabled: false,
+        },
     },
     versions: [
         "1",
diff --git a/vibrator/aidl/vts/Android.bp b/vibrator/aidl/vts/Android.bp
index b6d2fb2..166b30b 100644
--- a/vibrator/aidl/vts/Android.bp
+++ b/vibrator/aidl/vts/Android.bp
@@ -17,10 +17,10 @@
     tidy_timeout_srcs: ["VtsHalVibratorTargetTest.cpp"],
     srcs: ["VtsHalVibratorTargetTest.cpp"],
     shared_libs: [
-        "libbinder",
+        "libbinder_ndk",
     ],
     static_libs: [
-        "android.hardware.vibrator-V2-cpp",
+        "android.hardware.vibrator-V2-ndk",
     ],
     test_suites: [
         "general-tests",
@@ -36,10 +36,10 @@
     ],
     srcs: ["VtsHalVibratorManagerTargetTest.cpp"],
     shared_libs: [
-        "libbinder",
+        "libbinder_ndk",
     ],
     static_libs: [
-        "android.hardware.vibrator-V2-cpp",
+        "android.hardware.vibrator-V2-ndk",
     ],
     test_suites: [
         "general-tests",
diff --git a/vibrator/aidl/vts/VtsHalVibratorManagerTargetTest.cpp b/vibrator/aidl/vts/VtsHalVibratorManagerTargetTest.cpp
index e8ed26a..3c2a360 100644
--- a/vibrator/aidl/vts/VtsHalVibratorManagerTargetTest.cpp
+++ b/vibrator/aidl/vts/VtsHalVibratorManagerTargetTest.cpp
@@ -15,42 +15,40 @@
  */
 #include <aidl/Gtest.h>
 #include <aidl/Vintf.h>
+#include <aidl/android/hardware/vibrator/BnVibratorCallback.h>
+#include <aidl/android/hardware/vibrator/IVibrator.h>
+#include <aidl/android/hardware/vibrator/IVibratorManager.h>
 
-#include <android/hardware/vibrator/BnVibratorCallback.h>
-#include <android/hardware/vibrator/IVibrator.h>
-#include <android/hardware/vibrator/IVibratorManager.h>
-#include <binder/IServiceManager.h>
-#include <binder/ProcessState.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
 
 #include <cmath>
 #include <future>
 
-using android::ProcessState;
-using android::sp;
-using android::String16;
-using android::binder::Status;
-using android::hardware::vibrator::BnVibratorCallback;
-using android::hardware::vibrator::CompositeEffect;
-using android::hardware::vibrator::CompositePrimitive;
-using android::hardware::vibrator::Effect;
-using android::hardware::vibrator::EffectStrength;
-using android::hardware::vibrator::IVibrator;
-using android::hardware::vibrator::IVibratorManager;
+#include "test_utils.h"
+
+using aidl::android::hardware::vibrator::BnVibratorCallback;
+using aidl::android::hardware::vibrator::CompositeEffect;
+using aidl::android::hardware::vibrator::CompositePrimitive;
+using aidl::android::hardware::vibrator::Effect;
+using aidl::android::hardware::vibrator::EffectStrength;
+using aidl::android::hardware::vibrator::IVibrator;
+using aidl::android::hardware::vibrator::IVibratorManager;
 using std::chrono::high_resolution_clock;
 
-const std::vector<Effect> kEffects{android::enum_range<Effect>().begin(),
-                                   android::enum_range<Effect>().end()};
-const std::vector<EffectStrength> kEffectStrengths{android::enum_range<EffectStrength>().begin(),
-                                                   android::enum_range<EffectStrength>().end()};
-const std::vector<CompositePrimitive> kPrimitives{android::enum_range<CompositePrimitive>().begin(),
-                                                  android::enum_range<CompositePrimitive>().end()};
+const std::vector<Effect> kEffects{ndk::enum_range<Effect>().begin(),
+                                   ndk::enum_range<Effect>().end()};
+const std::vector<EffectStrength> kEffectStrengths{ndk::enum_range<EffectStrength>().begin(),
+                                                   ndk::enum_range<EffectStrength>().end()};
+const std::vector<CompositePrimitive> kPrimitives{ndk::enum_range<CompositePrimitive>().begin(),
+                                                  ndk::enum_range<CompositePrimitive>().end()};
 
 class CompletionCallback : public BnVibratorCallback {
   public:
     CompletionCallback(const std::function<void()>& callback) : mCallback(callback) {}
-    Status onComplete() override {
+    ndk::ScopedAStatus onComplete() override {
         mCallback();
-        return Status::ok();
+        return ndk::ScopedAStatus::ok();
     }
 
   private:
@@ -60,55 +58,50 @@
 class VibratorAidl : public testing::TestWithParam<std::string> {
   public:
     virtual void SetUp() override {
-        manager = android::waitForDeclaredService<IVibratorManager>(String16(GetParam().c_str()));
+        auto serviceName = GetParam().c_str();
+        manager = IVibratorManager::fromBinder(
+                ndk::SpAIBinder(AServiceManager_waitForService(serviceName)));
         ASSERT_NE(manager, nullptr);
-        ASSERT_TRUE(manager->getCapabilities(&capabilities).isOk());
-        EXPECT_TRUE(manager->getVibratorIds(&vibratorIds).isOk());
+        EXPECT_OK(manager->getCapabilities(&capabilities));
+        EXPECT_OK(manager->getVibratorIds(&vibratorIds));
     }
 
-    sp<IVibratorManager> manager;
+    std::shared_ptr<IVibratorManager> manager;
     int32_t capabilities;
     std::vector<int32_t> vibratorIds;
 };
 
-inline bool isUnknownOrUnsupported(Status status) {
-    return status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
-           status.transactionError() == android::UNKNOWN_TRANSACTION;
-}
-
 TEST_P(VibratorAidl, ValidateExistingVibrators) {
-    sp<IVibrator> vibrator;
-    for (auto& id : vibratorIds) {
-        EXPECT_TRUE(manager->getVibrator(id, &vibrator).isOk());
+    std::shared_ptr<IVibrator> vibrator;
+    for (int32_t id : vibratorIds) {
+        EXPECT_OK(manager->getVibrator(id, &vibrator));
         ASSERT_NE(vibrator, nullptr);
     }
 }
 
 TEST_P(VibratorAidl, GetVibratorWithInvalidId) {
     int32_t invalidId = *max_element(vibratorIds.begin(), vibratorIds.end()) + 1;
-    sp<IVibrator> vibrator;
-    EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
-              manager->getVibrator(invalidId, &vibrator).exceptionCode());
+    std::shared_ptr<IVibrator> vibrator;
+    EXPECT_ILLEGAL_ARGUMENT(manager->getVibrator(invalidId, &vibrator));
     ASSERT_EQ(vibrator, nullptr);
 }
 
 TEST_P(VibratorAidl, ValidatePrepareSyncedExistingVibrators) {
     if (!(capabilities & IVibratorManager::CAP_SYNC)) return;
     if (vibratorIds.empty()) return;
-    EXPECT_TRUE(manager->prepareSynced(vibratorIds).isOk());
-    EXPECT_TRUE(manager->cancelSynced().isOk());
+    EXPECT_OK(manager->prepareSynced(vibratorIds));
+    EXPECT_OK(manager->cancelSynced());
 }
 
 TEST_P(VibratorAidl, PrepareSyncedEmptySetIsInvalid) {
     if (!(capabilities & IVibratorManager::CAP_SYNC)) return;
     std::vector<int32_t> emptyIds;
-    EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, manager->prepareSynced(emptyIds).exceptionCode());
+    EXPECT_ILLEGAL_ARGUMENT(manager->prepareSynced(emptyIds));
 }
 
 TEST_P(VibratorAidl, PrepareSyncedNotSupported) {
     if (!(capabilities & IVibratorManager::CAP_SYNC)) {
-        Status status = manager->prepareSynced(vibratorIds);
-        EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+        EXPECT_UNKNOWN_OR_UNSUPPORTED(manager->prepareSynced(vibratorIds));
     }
 }
 
@@ -117,15 +110,14 @@
     if (!(capabilities & IVibratorManager::CAP_SYNC)) return;
     if (!(capabilities & IVibratorManager::CAP_PREPARE_ON)) {
         uint32_t durationMs = 250;
-        EXPECT_TRUE(manager->prepareSynced(vibratorIds).isOk());
-        sp<IVibrator> vibrator;
-        for (auto& id : vibratorIds) {
-            EXPECT_TRUE(manager->getVibrator(id, &vibrator).isOk());
+        EXPECT_OK(manager->prepareSynced(vibratorIds));
+        std::shared_ptr<IVibrator> vibrator;
+        for (int32_t id : vibratorIds) {
+            EXPECT_OK(manager->getVibrator(id, &vibrator));
             ASSERT_NE(vibrator, nullptr);
-            Status status = vibrator->on(durationMs, nullptr);
-            EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+            EXPECT_UNKNOWN_OR_UNSUPPORTED(vibrator->on(durationMs, nullptr));
         }
-        EXPECT_TRUE(manager->cancelSynced().isOk());
+        EXPECT_OK(manager->cancelSynced());
     }
 }
 
@@ -133,16 +125,16 @@
     if (vibratorIds.empty()) return;
     if (!(capabilities & IVibratorManager::CAP_SYNC)) return;
     if (!(capabilities & IVibratorManager::CAP_PREPARE_ON)) {
-        EXPECT_TRUE(manager->prepareSynced(vibratorIds).isOk());
-        sp<IVibrator> vibrator;
-        for (auto& id : vibratorIds) {
-            EXPECT_TRUE(manager->getVibrator(id, &vibrator).isOk());
+        EXPECT_OK(manager->prepareSynced(vibratorIds));
+        std::shared_ptr<IVibrator> vibrator;
+        for (int32_t id : vibratorIds) {
+            EXPECT_OK(manager->getVibrator(id, &vibrator));
             ASSERT_NE(vibrator, nullptr);
             int32_t lengthMs = 0;
-            Status status = vibrator->perform(kEffects[0], kEffectStrengths[0], nullptr, &lengthMs);
-            EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+            EXPECT_UNKNOWN_OR_UNSUPPORTED(
+                    vibrator->perform(kEffects[0], kEffectStrengths[0], nullptr, &lengthMs));
         }
-        EXPECT_TRUE(manager->cancelSynced().isOk());
+        EXPECT_OK(manager->cancelSynced());
     }
 }
 
@@ -157,15 +149,14 @@
         effect.scale = 1.0f;
         composite.emplace_back(effect);
 
-        EXPECT_TRUE(manager->prepareSynced(vibratorIds).isOk());
-        sp<IVibrator> vibrator;
-        for (auto& id : vibratorIds) {
-            EXPECT_TRUE(manager->getVibrator(id, &vibrator).isOk());
+        EXPECT_OK(manager->prepareSynced(vibratorIds));
+        std::shared_ptr<IVibrator> vibrator;
+        for (int32_t id : vibratorIds) {
+            EXPECT_OK(manager->getVibrator(id, &vibrator));
             ASSERT_NE(vibrator, nullptr);
-            Status status = vibrator->compose(composite, nullptr);
-            EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+            EXPECT_UNKNOWN_OR_UNSUPPORTED(vibrator->compose(composite, nullptr));
         }
-        EXPECT_TRUE(manager->cancelSynced().isOk());
+        EXPECT_OK(manager->cancelSynced());
     }
 }
 
@@ -177,51 +168,58 @@
 
     std::promise<void> completionPromise;
     std::future<void> completionFuture{completionPromise.get_future()};
-    sp<CompletionCallback> callback =
-            new CompletionCallback([&completionPromise] { completionPromise.set_value(); });
+    auto callback = ndk::SharedRefBase::make<CompletionCallback>(
+            [&completionPromise] { completionPromise.set_value(); });
     uint32_t durationMs = 250;
     std::chrono::milliseconds timeout{durationMs * 2};
 
-    EXPECT_TRUE(manager->prepareSynced(vibratorIds).isOk());
-    sp<IVibrator> vibrator;
-    for (auto& id : vibratorIds) {
-        EXPECT_TRUE(manager->getVibrator(id, &vibrator).isOk());
+    EXPECT_OK(manager->prepareSynced(vibratorIds));
+    std::shared_ptr<IVibrator> vibrator;
+    for (int32_t id : vibratorIds) {
+        EXPECT_OK(manager->getVibrator(id, &vibrator));
         ASSERT_NE(vibrator, nullptr);
-        EXPECT_TRUE(vibrator->on(durationMs, nullptr).isOk());
+        EXPECT_OK(vibrator->on(durationMs, nullptr));
     }
 
-    EXPECT_TRUE(manager->triggerSynced(callback).isOk());
+    EXPECT_OK(manager->triggerSynced(callback));
     EXPECT_EQ(completionFuture.wait_for(timeout), std::future_status::ready);
-    EXPECT_TRUE(manager->cancelSynced().isOk());
+    EXPECT_OK(manager->cancelSynced());
 }
 
 TEST_P(VibratorAidl, TriggerSyncNotSupported) {
     if (!(capabilities & IVibratorManager::CAP_SYNC)) {
-        Status status = manager->triggerSynced(nullptr);
-        EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+        EXPECT_UNKNOWN_OR_UNSUPPORTED(manager->triggerSynced(nullptr));
     }
 }
 
 TEST_P(VibratorAidl, TriggerCallbackNotSupported) {
     if (!(capabilities & IVibratorManager::CAP_SYNC)) return;
     if (!(capabilities & IVibratorManager::CAP_TRIGGER_CALLBACK)) {
-        sp<CompletionCallback> callback = new CompletionCallback([] {});
-        EXPECT_TRUE(manager->prepareSynced(vibratorIds).isOk());
-        Status status = manager->triggerSynced(callback);
-        EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
-        EXPECT_TRUE(manager->cancelSynced().isOk());
+        auto callback = ndk::SharedRefBase::make<CompletionCallback>([] {});
+        EXPECT_OK(manager->prepareSynced(vibratorIds));
+        EXPECT_UNKNOWN_OR_UNSUPPORTED(manager->triggerSynced(callback));
+        EXPECT_OK(manager->cancelSynced());
     }
 }
 
+std::vector<std::string> FindVibratorManagerNames() {
+    std::vector<std::string> names;
+    constexpr auto callback = [](const char* instance, void* context) {
+        std::string fullName = std::string(IVibratorManager::descriptor) + "/" + instance;
+        static_cast<std::vector<std::string>*>(context)->emplace_back(fullName);
+    };
+    AServiceManager_forEachDeclaredInstance(IVibratorManager::descriptor,
+                                            static_cast<void*>(&names), callback);
+    return names;
+}
+
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VibratorAidl);
-INSTANTIATE_TEST_SUITE_P(
-        Vibrator, VibratorAidl,
-        testing::ValuesIn(android::getAidlHalInstanceNames(IVibratorManager::descriptor)),
-        android::PrintInstanceNameToString);
+INSTANTIATE_TEST_SUITE_P(Vibrator, VibratorAidl, testing::ValuesIn(FindVibratorManagerNames()),
+                         android::PrintInstanceNameToString);
 
 int main(int argc, char** argv) {
     ::testing::InitGoogleTest(&argc, argv);
-    ProcessState::self()->setThreadPoolMaxThreadCount(1);
-    ProcessState::self()->startThreadPool();
+    ABinderProcess_setThreadPoolMaxThreadCount(1);
+    ABinderProcess_startThreadPool();
     return RUN_ALL_TESTS();
 }
diff --git a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
index db474d6..65a1e84 100644
--- a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
+++ b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
@@ -15,38 +15,37 @@
  */
 #include <aidl/Gtest.h>
 #include <aidl/Vintf.h>
-#include <android/hardware/vibrator/BnVibratorCallback.h>
-#include <android/hardware/vibrator/IVibrator.h>
-#include <android/hardware/vibrator/IVibratorManager.h>
-#include <binder/IServiceManager.h>
-#include <binder/ProcessState.h>
+#include <aidl/android/hardware/vibrator/BnVibratorCallback.h>
+#include <aidl/android/hardware/vibrator/IVibrator.h>
+#include <aidl/android/hardware/vibrator/IVibratorManager.h>
+
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
 
 #include <cmath>
 #include <future>
 
-using android::ProcessState;
-using android::sp;
-using android::String16;
-using android::binder::Status;
-using android::hardware::vibrator::ActivePwle;
-using android::hardware::vibrator::BnVibratorCallback;
-using android::hardware::vibrator::Braking;
-using android::hardware::vibrator::BrakingPwle;
-using android::hardware::vibrator::CompositeEffect;
-using android::hardware::vibrator::CompositePrimitive;
-using android::hardware::vibrator::Effect;
-using android::hardware::vibrator::EffectStrength;
-using android::hardware::vibrator::IVibrator;
-using android::hardware::vibrator::IVibratorManager;
-using android::hardware::vibrator::PrimitivePwle;
+#include "test_utils.h"
+
+using aidl::android::hardware::vibrator::ActivePwle;
+using aidl::android::hardware::vibrator::BnVibratorCallback;
+using aidl::android::hardware::vibrator::Braking;
+using aidl::android::hardware::vibrator::BrakingPwle;
+using aidl::android::hardware::vibrator::CompositeEffect;
+using aidl::android::hardware::vibrator::CompositePrimitive;
+using aidl::android::hardware::vibrator::Effect;
+using aidl::android::hardware::vibrator::EffectStrength;
+using aidl::android::hardware::vibrator::IVibrator;
+using aidl::android::hardware::vibrator::IVibratorManager;
+using aidl::android::hardware::vibrator::PrimitivePwle;
 using std::chrono::high_resolution_clock;
 
 using namespace ::std::chrono_literals;
 
-const std::vector<Effect> kEffects{android::enum_range<Effect>().begin(),
-                                   android::enum_range<Effect>().end()};
-const std::vector<EffectStrength> kEffectStrengths{android::enum_range<EffectStrength>().begin(),
-                                                   android::enum_range<EffectStrength>().end()};
+const std::vector<Effect> kEffects{ndk::enum_range<Effect>().begin(),
+                                   ndk::enum_range<Effect>().end()};
+const std::vector<EffectStrength> kEffectStrengths{ndk::enum_range<EffectStrength>().begin(),
+                                                   ndk::enum_range<EffectStrength>().end()};
 
 const std::vector<Effect> kInvalidEffects = {
     static_cast<Effect>(static_cast<int32_t>(kEffects.front()) - 1),
@@ -59,8 +58,7 @@
 };
 
 const std::vector<CompositePrimitive> kCompositePrimitives{
-    android::enum_range<CompositePrimitive>().begin(),
-    android::enum_range<CompositePrimitive>().end()};
+        ndk::enum_range<CompositePrimitive>().begin(), ndk::enum_range<CompositePrimitive>().end()};
 
 const std::vector<CompositePrimitive> kRequiredPrimitives = {
         CompositePrimitive::CLICK,      CompositePrimitive::LIGHT_TICK,
@@ -74,14 +72,36 @@
 };
 
 // Timeout to wait for vibration callback completion.
-static constexpr auto VIBRATION_CALLBACK_TIMEOUT = 100ms;
+static constexpr std::chrono::milliseconds VIBRATION_CALLBACK_TIMEOUT = 100ms;
+
+static std::vector<std::string> findVibratorManagerNames() {
+    std::vector<std::string> names;
+    constexpr auto callback = [](const char* instance, void* context) {
+        auto fullName = std::string(IVibratorManager::descriptor) + "/" + instance;
+        static_cast<std::vector<std::string>*>(context)->emplace_back(fullName);
+    };
+    AServiceManager_forEachDeclaredInstance(IVibratorManager::descriptor,
+                                            static_cast<void*>(&names), callback);
+    return names;
+}
+
+static std::vector<std::string> findUnmanagedVibratorNames() {
+    std::vector<std::string> names;
+    constexpr auto callback = [](const char* instance, void* context) {
+        auto fullName = std::string(IVibrator::descriptor) + "/" + instance;
+        static_cast<std::vector<std::string>*>(context)->emplace_back(fullName);
+    };
+    AServiceManager_forEachDeclaredInstance(IVibrator::descriptor, static_cast<void*>(&names),
+                                            callback);
+    return names;
+}
 
 class CompletionCallback : public BnVibratorCallback {
   public:
     CompletionCallback(const std::function<void()> &callback) : mCallback(callback) {}
-    Status onComplete() override {
+    ndk::ScopedAStatus onComplete() override {
         mCallback();
-        return Status::ok();
+        return ndk::ScopedAStatus::ok();
     }
 
   private:
@@ -93,88 +113,87 @@
     virtual void SetUp() override {
         int32_t managerIdx = std::get<0>(GetParam());
         int32_t vibratorId = std::get<1>(GetParam());
-        auto managerAidlNames = android::getAidlHalInstanceNames(IVibratorManager::descriptor);
 
         if (managerIdx < 0) {
             // Testing a unmanaged vibrator, using vibratorId as index from registered HALs
-            auto vibratorAidlNames = android::getAidlHalInstanceNames(IVibrator::descriptor);
-            ASSERT_LT(vibratorId, vibratorAidlNames.size());
-            auto vibratorName = String16(vibratorAidlNames[vibratorId].c_str());
-            vibrator = android::waitForDeclaredService<IVibrator>(vibratorName);
+            std::vector<std::string> vibratorNames = findUnmanagedVibratorNames();
+            ASSERT_LT(vibratorId, vibratorNames.size());
+            vibrator = IVibrator::fromBinder(ndk::SpAIBinder(
+                    AServiceManager_waitForService(vibratorNames[vibratorId].c_str())));
         } else {
             // Testing a managed vibrator, using vibratorId to retrieve it from the manager
-            ASSERT_LT(managerIdx, managerAidlNames.size());
-            auto managerName = String16(managerAidlNames[managerIdx].c_str());
-            auto vibratorManager = android::waitForDeclaredService<IVibratorManager>(managerName);
-            auto vibratorResult = vibratorManager->getVibrator(vibratorId, &vibrator);
-            ASSERT_TRUE(vibratorResult.isOk());
+            std::vector<std::string> managerNames = findVibratorManagerNames();
+            ASSERT_LT(managerIdx, managerNames.size());
+            auto vibratorManager = IVibratorManager::fromBinder(ndk::SpAIBinder(
+                    AServiceManager_waitForService(managerNames[managerIdx].c_str())));
+            EXPECT_OK(vibratorManager->getVibrator(vibratorId, &vibrator))
+                    << "\n  For vibrator id: " << vibratorId;
         }
 
         ASSERT_NE(vibrator, nullptr);
-        ASSERT_TRUE(vibrator->getCapabilities(&capabilities).isOk());
+        EXPECT_OK(vibrator->getCapabilities(&capabilities));
     }
 
     virtual void TearDown() override {
         // Reset vibrator state between tests.
-        EXPECT_TRUE(vibrator->off().isOk());
+        EXPECT_OK(vibrator->off());
     }
 
-    sp<IVibrator> vibrator;
+    std::shared_ptr<IVibrator> vibrator;
     int32_t capabilities;
 };
 
-inline bool isUnknownOrUnsupported(Status status) {
-    return status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
-           status.transactionError() == android::UNKNOWN_TRANSACTION;
-}
-
-static float getResonantFrequencyHz(sp<IVibrator> vibrator, int32_t capabilities) {
+static float getResonantFrequencyHz(const std::shared_ptr<IVibrator>& vibrator,
+                                    int32_t capabilities) {
     float resonantFrequencyHz;
-    Status status = vibrator->getResonantFrequency(&resonantFrequencyHz);
+    ndk::ScopedAStatus status = vibrator->getResonantFrequency(&resonantFrequencyHz);
     if (capabilities & IVibrator::CAP_GET_RESONANT_FREQUENCY) {
+        EXPECT_OK(std::move(status));
         EXPECT_GT(resonantFrequencyHz, 0);
-        EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
     } else {
-        EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+        EXPECT_UNKNOWN_OR_UNSUPPORTED(std::move(status));
     }
     return resonantFrequencyHz;
 }
 
-static float getFrequencyResolutionHz(sp<IVibrator> vibrator, int32_t capabilities) {
+static float getFrequencyResolutionHz(const std::shared_ptr<IVibrator>& vibrator,
+                                      int32_t capabilities) {
     float freqResolutionHz;
-    Status status = vibrator->getFrequencyResolution(&freqResolutionHz);
+    ndk::ScopedAStatus status = vibrator->getFrequencyResolution(&freqResolutionHz);
     if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) {
+        EXPECT_OK(std::move(status));
         EXPECT_GT(freqResolutionHz, 0);
-        EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
     } else {
-        EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+        EXPECT_UNKNOWN_OR_UNSUPPORTED(std::move(status));
     }
     return freqResolutionHz;
 }
 
-static float getFrequencyMinimumHz(sp<IVibrator> vibrator, int32_t capabilities) {
+static float getFrequencyMinimumHz(const std::shared_ptr<IVibrator>& vibrator,
+                                   int32_t capabilities) {
     float freqMinimumHz;
-    Status status = vibrator->getFrequencyMinimum(&freqMinimumHz);
+    ndk::ScopedAStatus status = vibrator->getFrequencyMinimum(&freqMinimumHz);
     if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) {
-        EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
+        EXPECT_OK(std::move(status));
 
         float resonantFrequencyHz = getResonantFrequencyHz(vibrator, capabilities);
 
         EXPECT_GT(freqMinimumHz, 0);
         EXPECT_LE(freqMinimumHz, resonantFrequencyHz);
     } else {
-        EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+        EXPECT_UNKNOWN_OR_UNSUPPORTED(std::move(status));
     }
     return freqMinimumHz;
 }
 
-static float getFrequencyMaximumHz(sp<IVibrator> vibrator, int32_t capabilities) {
+static float getFrequencyMaximumHz(const std::shared_ptr<IVibrator>& vibrator,
+                                   int32_t capabilities) {
     std::vector<float> bandwidthAmplitudeMap;
-    Status status = vibrator->getBandwidthAmplitudeMap(&bandwidthAmplitudeMap);
+    ndk::ScopedAStatus status = vibrator->getBandwidthAmplitudeMap(&bandwidthAmplitudeMap);
     if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) {
-        EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
+        EXPECT_OK(std::move(status));
     } else {
-        EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+        EXPECT_UNKNOWN_OR_UNSUPPORTED(std::move(status));
     }
 
     float freqMaximumHz = ((bandwidthAmplitudeMap.size() - 1) *
@@ -191,7 +210,8 @@
     return 1.0;
 }
 
-static ActivePwle composeValidActivePwle(sp<IVibrator> vibrator, int32_t capabilities) {
+static ActivePwle composeValidActivePwle(const std::shared_ptr<IVibrator>& vibrator,
+                                         int32_t capabilities) {
     float frequencyHz;
     if (capabilities & IVibrator::CAP_GET_RESONANT_FREQUENCY) {
         frequencyHz = getResonantFrequencyHz(vibrator, capabilities);
@@ -212,9 +232,9 @@
 }
 
 TEST_P(VibratorAidl, OnThenOffBeforeTimeout) {
-    EXPECT_TRUE(vibrator->on(2000, nullptr /*callback*/).isOk());
+    EXPECT_OK(vibrator->on(2000, nullptr /*callback*/));
     sleep(1);
-    EXPECT_TRUE(vibrator->off().isOk());
+    EXPECT_OK(vibrator->off());
 }
 
 TEST_P(VibratorAidl, OnWithCallback) {
@@ -223,26 +243,25 @@
 
     std::promise<void> completionPromise;
     std::future<void> completionFuture{completionPromise.get_future()};
-    sp<CompletionCallback> callback =
-        new CompletionCallback([&completionPromise] { completionPromise.set_value(); });
+    auto callback = ndk::SharedRefBase::make<CompletionCallback>(
+            [&completionPromise] { completionPromise.set_value(); });
     uint32_t durationMs = 250;
     auto timeout = std::chrono::milliseconds(durationMs) + VIBRATION_CALLBACK_TIMEOUT;
-    EXPECT_TRUE(vibrator->on(durationMs, callback).isOk());
+    EXPECT_OK(vibrator->on(durationMs, callback));
     EXPECT_EQ(completionFuture.wait_for(timeout), std::future_status::ready);
-    EXPECT_TRUE(vibrator->off().isOk());
+    EXPECT_OK(vibrator->off());
 }
 
 TEST_P(VibratorAidl, OnCallbackNotSupported) {
     if (!(capabilities & IVibrator::CAP_ON_CALLBACK)) {
-        sp<CompletionCallback> callback = new CompletionCallback([] {});
-        Status status = vibrator->on(250, callback);
-        EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+        auto callback = ndk::SharedRefBase::make<CompletionCallback>([] {});
+        EXPECT_UNKNOWN_OR_UNSUPPORTED(vibrator->on(250, callback));
     }
 }
 
 TEST_P(VibratorAidl, ValidateEffect) {
     std::vector<Effect> supported;
-    ASSERT_TRUE(vibrator->getSupportedEffects(&supported).isOk());
+    EXPECT_OK(vibrator->getSupportedEffects(&supported));
 
     for (Effect effect : kEffects) {
         bool isEffectSupported =
@@ -250,15 +269,18 @@
 
         for (EffectStrength strength : kEffectStrengths) {
             int32_t lengthMs = 0;
-            Status status = vibrator->perform(effect, strength, nullptr /*callback*/, &lengthMs);
+            ndk::ScopedAStatus status =
+                    vibrator->perform(effect, strength, nullptr /*callback*/, &lengthMs);
 
             if (isEffectSupported) {
-                EXPECT_TRUE(status.isOk()) << toString(effect) << " " << toString(strength);
+                EXPECT_OK(std::move(status))
+                        << "\n  For effect: " << toString(effect) << " " << toString(strength);
                 EXPECT_GT(lengthMs, 0);
                 usleep(lengthMs * 1000);
+                EXPECT_OK(vibrator->off());
             } else {
-                EXPECT_TRUE(isUnknownOrUnsupported(status))
-                        << status << " " << toString(effect) << " " << toString(strength);
+                EXPECT_UNKNOWN_OR_UNSUPPORTED(std::move(status))
+                        << "\n  For effect: " << toString(effect) << " " << toString(strength);
             }
         }
     }
@@ -269,7 +291,7 @@
         return;
 
     std::vector<Effect> supported;
-    ASSERT_TRUE(vibrator->getSupportedEffects(&supported).isOk());
+    EXPECT_OK(vibrator->getSupportedEffects(&supported));
 
     for (Effect effect : kEffects) {
         bool isEffectSupported =
@@ -278,25 +300,26 @@
         for (EffectStrength strength : kEffectStrengths) {
             std::promise<void> completionPromise;
             std::future<void> completionFuture{completionPromise.get_future()};
-            sp<CompletionCallback> callback =
-                new CompletionCallback([&completionPromise] { completionPromise.set_value(); });
+            auto callback = ndk::SharedRefBase::make<CompletionCallback>(
+                    [&completionPromise] { completionPromise.set_value(); });
             int lengthMs = 0;
-            Status status = vibrator->perform(effect, strength, callback, &lengthMs);
+            ndk::ScopedAStatus status = vibrator->perform(effect, strength, callback, &lengthMs);
 
             if (isEffectSupported) {
-                EXPECT_TRUE(status.isOk());
+                EXPECT_OK(std::move(status))
+                        << "\n  For effect: " << toString(effect) << " " << toString(strength);
                 EXPECT_GT(lengthMs, 0);
             } else {
-                EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+                EXPECT_UNKNOWN_OR_UNSUPPORTED(std::move(status))
+                        << "\n  For effect: " << toString(effect) << " " << toString(strength);
             }
 
-            if (!status.isOk())
-                continue;
+            if (lengthMs <= 0) continue;
 
             auto timeout = std::chrono::milliseconds(lengthMs) + VIBRATION_CALLBACK_TIMEOUT;
             EXPECT_EQ(completionFuture.wait_for(timeout), std::future_status::ready);
 
-            EXPECT_TRUE(vibrator->off().isOk());
+            EXPECT_OK(vibrator->off());
         }
     }
 }
@@ -307,10 +330,10 @@
 
     for (Effect effect : kEffects) {
         for (EffectStrength strength : kEffectStrengths) {
-            sp<CompletionCallback> callback = new CompletionCallback([] {});
+            auto callback = ndk::SharedRefBase::make<CompletionCallback>([] {});
             int lengthMs;
-            Status status = vibrator->perform(effect, strength, callback, &lengthMs);
-            EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+            EXPECT_UNKNOWN_OR_UNSUPPORTED(vibrator->perform(effect, strength, callback, &lengthMs))
+                    << "\n  For effect: " << toString(effect) << " " << toString(strength);
         }
     }
 }
@@ -319,53 +342,52 @@
     for (Effect effect : kInvalidEffects) {
         for (EffectStrength strength : kEffectStrengths) {
             int32_t lengthMs;
-            Status status = vibrator->perform(effect, strength, nullptr /*callback*/, &lengthMs);
-            EXPECT_TRUE(isUnknownOrUnsupported(status))
-                    << status << toString(effect) << " " << toString(strength);
+            EXPECT_UNKNOWN_OR_UNSUPPORTED(
+                    vibrator->perform(effect, strength, nullptr /*callback*/, &lengthMs))
+                    << "\n  For effect: " << toString(effect) << " " << toString(strength);
         }
     }
     for (Effect effect : kEffects) {
         for (EffectStrength strength : kInvalidEffectStrengths) {
             int32_t lengthMs;
-            Status status = vibrator->perform(effect, strength, nullptr /*callback*/, &lengthMs);
-            EXPECT_TRUE(isUnknownOrUnsupported(status))
-                    << status << " " << toString(effect) << " " << toString(strength);
+            EXPECT_UNKNOWN_OR_UNSUPPORTED(
+                    vibrator->perform(effect, strength, nullptr /*callback*/, &lengthMs))
+                    << "\n  For effect: " << toString(effect) << " " << toString(strength);
         }
     }
 }
 
 TEST_P(VibratorAidl, ChangeVibrationAmplitude) {
     if (capabilities & IVibrator::CAP_AMPLITUDE_CONTROL) {
-        EXPECT_EQ(Status::EX_NONE, vibrator->setAmplitude(0.1f).exceptionCode());
-        EXPECT_TRUE(vibrator->on(2000, nullptr /*callback*/).isOk());
-        EXPECT_EQ(Status::EX_NONE, vibrator->setAmplitude(0.5f).exceptionCode());
+        EXPECT_OK(vibrator->setAmplitude(0.1f));
+        EXPECT_OK(vibrator->on(2000, nullptr /*callback*/));
+        EXPECT_OK(vibrator->setAmplitude(0.5f));
         sleep(1);
-        EXPECT_EQ(Status::EX_NONE, vibrator->setAmplitude(1.0f).exceptionCode());
+        EXPECT_OK(vibrator->setAmplitude(1.0f));
         sleep(1);
-        EXPECT_TRUE(vibrator->off().isOk());
+        EXPECT_OK(vibrator->off());
     }
 }
 
 TEST_P(VibratorAidl, AmplitudeOutsideRangeFails) {
     if (capabilities & IVibrator::CAP_AMPLITUDE_CONTROL) {
-        EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, vibrator->setAmplitude(-1).exceptionCode());
-        EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, vibrator->setAmplitude(0).exceptionCode());
-        EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, vibrator->setAmplitude(1.1).exceptionCode());
+        EXPECT_ILLEGAL_ARGUMENT(vibrator->setAmplitude(-1));
+        EXPECT_ILLEGAL_ARGUMENT(vibrator->setAmplitude(0));
+        EXPECT_ILLEGAL_ARGUMENT(vibrator->setAmplitude(1.1));
     }
 }
 
 TEST_P(VibratorAidl, AmplitudeReturnsUnsupportedMatchingCapabilities) {
     if ((capabilities & IVibrator::CAP_AMPLITUDE_CONTROL) == 0) {
-        Status status = vibrator->setAmplitude(1);
-        EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+        EXPECT_UNKNOWN_OR_UNSUPPORTED(vibrator->setAmplitude(1));
     }
 }
 
 TEST_P(VibratorAidl, ChangeVibrationExternalControl) {
     if (capabilities & IVibrator::CAP_EXTERNAL_CONTROL) {
-        EXPECT_TRUE(vibrator->setExternalControl(true).isOk());
+        EXPECT_OK(vibrator->setExternalControl(true));
         sleep(1);
-        EXPECT_TRUE(vibrator->setExternalControl(false).isOk());
+        EXPECT_OK(vibrator->setExternalControl(false));
         sleep(1);
     }
 }
@@ -375,15 +397,15 @@
         (capabilities & IVibrator::CAP_EXTERNAL_AMPLITUDE_CONTROL) > 0;
 
     if (capabilities & IVibrator::CAP_EXTERNAL_CONTROL) {
-        EXPECT_TRUE(vibrator->setExternalControl(true).isOk());
+        EXPECT_OK(vibrator->setExternalControl(true));
 
-        Status amplitudeStatus = vibrator->setAmplitude(0.5);
         if (supportsExternalAmplitudeControl) {
-            EXPECT_TRUE(amplitudeStatus.isOk());
+            EXPECT_OK(vibrator->setAmplitude(0.5));
         } else {
-            EXPECT_TRUE(isUnknownOrUnsupported(amplitudeStatus)) << amplitudeStatus;
+            EXPECT_UNKNOWN_OR_UNSUPPORTED(vibrator->setAmplitude(0.5));
         }
-        EXPECT_TRUE(vibrator->setExternalControl(false).isOk());
+
+        EXPECT_OK(vibrator->setExternalControl(false));
     } else {
         EXPECT_FALSE(supportsExternalAmplitudeControl);
     }
@@ -391,18 +413,16 @@
 
 TEST_P(VibratorAidl, ExternalControlUnsupportedMatchingCapabilities) {
     if ((capabilities & IVibrator::CAP_EXTERNAL_CONTROL) == 0) {
-        Status status = vibrator->setExternalControl(true);
-        EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+        EXPECT_UNKNOWN_OR_UNSUPPORTED(vibrator->setExternalControl(true));
     }
 }
 
 TEST_P(VibratorAidl, GetSupportedPrimitives) {
     if (capabilities & IVibrator::CAP_COMPOSE_EFFECTS) {
         std::vector<CompositePrimitive> supported;
+        EXPECT_OK(vibrator->getSupportedPrimitives(&supported));
 
-        EXPECT_EQ(Status::EX_NONE, vibrator->getSupportedPrimitives(&supported).exceptionCode());
-
-        for (auto primitive : kCompositePrimitives) {
+        for (CompositePrimitive primitive : kCompositePrimitives) {
             bool isPrimitiveSupported =
                 std::find(supported.begin(), supported.end(), primitive) != supported.end();
             bool isPrimitiveRequired =
@@ -417,22 +437,23 @@
 TEST_P(VibratorAidl, GetPrimitiveDuration) {
     if (capabilities & IVibrator::CAP_COMPOSE_EFFECTS) {
         std::vector<CompositePrimitive> supported;
-        ASSERT_TRUE(vibrator->getSupportedPrimitives(&supported).isOk());
+        EXPECT_OK(vibrator->getSupportedPrimitives(&supported));
 
-        for (auto primitive : kCompositePrimitives) {
+        for (CompositePrimitive primitive : kCompositePrimitives) {
             bool isPrimitiveSupported =
                 std::find(supported.begin(), supported.end(), primitive) != supported.end();
             int32_t duration;
 
-            Status status = vibrator->getPrimitiveDuration(primitive, &duration);
-
             if (isPrimitiveSupported) {
-                EXPECT_EQ(Status::EX_NONE, status.exceptionCode());
+                EXPECT_OK(vibrator->getPrimitiveDuration(primitive, &duration))
+                        << "\n  For primitive: " << toString(primitive) << " " << duration;
                 if (primitive != CompositePrimitive::NOOP) {
-                    ASSERT_GT(duration, 0) << toString(primitive) << " " << duration;
+                    ASSERT_GT(duration, 0)
+                            << "\n  For primitive: " << toString(primitive) << " " << duration;
                 }
             } else {
-                EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+                EXPECT_UNKNOWN_OR_UNSUPPORTED(vibrator->getPrimitiveDuration(primitive, &duration))
+                        << "\n  For primitive: " << toString(primitive);
             }
         }
     }
@@ -446,14 +467,14 @@
     std::vector<CompositePrimitive> supported;
     int32_t maxDelay, maxSize;
 
-    ASSERT_TRUE(vibrator->getSupportedPrimitives(&supported).isOk());
-    EXPECT_EQ(Status::EX_NONE, vibrator->getCompositionDelayMax(&maxDelay).exceptionCode());
-    EXPECT_EQ(Status::EX_NONE, vibrator->getCompositionSizeMax(&maxSize).exceptionCode());
+    EXPECT_OK(vibrator->getSupportedPrimitives(&supported));
+    EXPECT_OK(vibrator->getCompositionDelayMax(&maxDelay));
+    EXPECT_OK(vibrator->getCompositionSizeMax(&maxSize));
 
     std::vector<CompositeEffect> composite;
 
     for (int i = 0; i < supported.size(); i++) {
-        auto primitive = supported[i];
+        CompositePrimitive primitive = supported[i];
         float t = static_cast<float>(i + 1) / supported.size();
         CompositeEffect effect;
 
@@ -467,8 +488,8 @@
     }
 
     if (composite.size() != 0) {
-        EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, nullptr).exceptionCode());
-        EXPECT_TRUE(vibrator->off().isOk());
+        EXPECT_OK(vibrator->compose(composite, nullptr));
+        EXPECT_OK(vibrator->off());
     }
 }
 
@@ -477,12 +498,12 @@
         GTEST_SKIP() << "CAP_COMPOSE_EFFECTS not supported";
     }
 
-    auto unsupported = kInvalidPrimitives;
+    std::vector<CompositePrimitive> unsupported(kInvalidPrimitives);
     std::vector<CompositePrimitive> supported;
 
-    ASSERT_TRUE(vibrator->getSupportedPrimitives(&supported).isOk());
+    EXPECT_OK(vibrator->getSupportedPrimitives(&supported));
 
-    for (auto primitive : kCompositePrimitives) {
+    for (CompositePrimitive primitive : kCompositePrimitives) {
         bool isPrimitiveSupported =
                 std::find(supported.begin(), supported.end(), primitive) != supported.end();
 
@@ -491,16 +512,15 @@
         }
     }
 
-    for (auto primitive : unsupported) {
+    for (CompositePrimitive primitive : unsupported) {
         std::vector<CompositeEffect> composite(1);
 
-        for (auto& effect : composite) {
+        for (CompositeEffect& effect : composite) {
             effect.delayMs = 0;
             effect.primitive = primitive;
             effect.scale = 1.0f;
         }
-        Status status = vibrator->compose(composite, nullptr);
-        EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+        EXPECT_UNKNOWN_OR_UNSUPPORTED(vibrator->compose(composite, nullptr));
     }
 }
 
@@ -516,18 +536,18 @@
     effect.primitive = CompositePrimitive::CLICK;
 
     effect.scale = std::nextafter(0.0f, -1.0f);
-    EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, vibrator->compose(composite, nullptr).exceptionCode());
+    EXPECT_ILLEGAL_ARGUMENT(vibrator->compose(composite, nullptr));
 
     effect.scale = 0.0f;
-    EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, nullptr).exceptionCode());
-    EXPECT_TRUE(vibrator->off().isOk());
+    EXPECT_OK(vibrator->compose(composite, nullptr));
+    EXPECT_OK(vibrator->off());
 
     effect.scale = 1.0f;
-    EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, nullptr).exceptionCode());
-    EXPECT_TRUE(vibrator->off().isOk());
+    EXPECT_OK(vibrator->compose(composite, nullptr));
+    EXPECT_OK(vibrator->off());
 
     effect.scale = std::nextafter(1.0f, 2.0f);
-    EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, vibrator->compose(composite, nullptr).exceptionCode());
+    EXPECT_ILLEGAL_ARGUMENT(vibrator->compose(composite, nullptr));
 }
 
 TEST_P(VibratorAidl, ComposeDelayBoundary) {
@@ -537,7 +557,7 @@
 
     int32_t maxDelay;
 
-    EXPECT_EQ(Status::EX_NONE, vibrator->getCompositionDelayMax(&maxDelay).exceptionCode());
+    EXPECT_OK(vibrator->getCompositionDelayMax(&maxDelay));
 
     std::vector<CompositeEffect> composite(1);
     CompositeEffect& effect = composite[0];
@@ -546,19 +566,19 @@
     effect.scale = 1.0f;
 
     effect.delayMs = 0;
-    EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, nullptr).exceptionCode());
-    EXPECT_TRUE(vibrator->off().isOk());
+    EXPECT_OK(vibrator->compose(composite, nullptr));
+    EXPECT_OK(vibrator->off());
 
     effect.delayMs = 1;
-    EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, nullptr).exceptionCode());
-    EXPECT_TRUE(vibrator->off().isOk());
+    EXPECT_OK(vibrator->compose(composite, nullptr));
+    EXPECT_OK(vibrator->off());
 
     effect.delayMs = maxDelay;
-    EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, nullptr).exceptionCode());
-    EXPECT_TRUE(vibrator->off().isOk());
+    EXPECT_OK(vibrator->compose(composite, nullptr));
+    EXPECT_OK(vibrator->off());
 
     effect.delayMs = maxDelay + 1;
-    EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, vibrator->compose(composite, nullptr).exceptionCode());
+    EXPECT_ILLEGAL_ARGUMENT(vibrator->compose(composite, nullptr));
 }
 
 TEST_P(VibratorAidl, ComposeSizeBoundary) {
@@ -568,7 +588,7 @@
 
     int32_t maxSize;
 
-    EXPECT_EQ(Status::EX_NONE, vibrator->getCompositionSizeMax(&maxSize).exceptionCode());
+    EXPECT_OK(vibrator->getCompositionSizeMax(&maxSize));
 
     std::vector<CompositeEffect> composite(maxSize);
     CompositeEffect effect;
@@ -578,11 +598,11 @@
     effect.scale = 1.0f;
 
     std::fill(composite.begin(), composite.end(), effect);
-    EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, nullptr).exceptionCode());
-    EXPECT_TRUE(vibrator->off().isOk());
+    EXPECT_OK(vibrator->compose(composite, nullptr));
+    EXPECT_OK(vibrator->off());
 
     composite.emplace_back(effect);
-    EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, vibrator->compose(composite, nullptr).exceptionCode());
+    EXPECT_ILLEGAL_ARGUMENT(vibrator->compose(composite, nullptr));
 }
 
 TEST_P(VibratorAidl, ComposeCallback) {
@@ -591,18 +611,17 @@
     }
 
     std::vector<CompositePrimitive> supported;
+    EXPECT_OK(vibrator->getSupportedPrimitives(&supported));
 
-    ASSERT_TRUE(vibrator->getSupportedPrimitives(&supported).isOk());
-
-    for (auto primitive : supported) {
+    for (CompositePrimitive primitive : supported) {
         if (primitive == CompositePrimitive::NOOP) {
             continue;
         }
 
         std::promise<void> completionPromise;
         std::future<void> completionFuture{completionPromise.get_future()};
-        sp<CompletionCallback> callback =
-                new CompletionCallback([&completionPromise] { completionPromise.set_value(); });
+        auto callback = ndk::SharedRefBase::make<CompletionCallback>(
+                [&completionPromise] { completionPromise.set_value(); });
         CompositeEffect effect;
         std::vector<CompositeEffect> composite;
         int32_t durationMs;
@@ -615,50 +634,50 @@
         effect.scale = 1.0f;
         composite.emplace_back(effect);
 
-        EXPECT_EQ(Status::EX_NONE,
-                  vibrator->getPrimitiveDuration(primitive, &durationMs).exceptionCode())
-                << toString(primitive);
+        EXPECT_OK(vibrator->getPrimitiveDuration(primitive, &durationMs))
+                << "\n  For primitive: " << toString(primitive);
         duration = std::chrono::milliseconds(durationMs);
 
         start = high_resolution_clock::now();
-        EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, callback).exceptionCode())
-                << toString(primitive);
+        EXPECT_OK(vibrator->compose(composite, callback))
+                << "\n  For primitive: " << toString(primitive);
 
         EXPECT_EQ(completionFuture.wait_for(duration + VIBRATION_CALLBACK_TIMEOUT),
                   std::future_status::ready)
-                << toString(primitive);
+                << "\n  For primitive: " << toString(primitive);
         end = high_resolution_clock::now();
 
         elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
-        EXPECT_GE(elapsed.count(), duration.count()) << toString(primitive);
+        EXPECT_GE(elapsed.count(), duration.count())
+                << "\n  For primitive: " << toString(primitive);
 
-        EXPECT_TRUE(vibrator->off().isOk());
+        EXPECT_OK(vibrator->off()) << "\n  For primitive: " << toString(primitive);
     }
 }
 
 TEST_P(VibratorAidl, AlwaysOn) {
     if (capabilities & IVibrator::CAP_ALWAYS_ON_CONTROL) {
         std::vector<Effect> supported;
-        ASSERT_TRUE(vibrator->getSupportedAlwaysOnEffects(&supported).isOk());
+        EXPECT_OK(vibrator->getSupportedAlwaysOnEffects(&supported));
 
         for (Effect effect : kEffects) {
             bool isEffectSupported =
                 std::find(supported.begin(), supported.end(), effect) != supported.end();
 
             for (EffectStrength strength : kEffectStrengths) {
-                Status status = vibrator->alwaysOnEnable(0, effect, strength);
+                ndk::ScopedAStatus status = vibrator->alwaysOnEnable(0, effect, strength);
 
                 if (isEffectSupported) {
-                    EXPECT_EQ(Status::EX_NONE, status.exceptionCode())
-                        << toString(effect) << " " << toString(strength);
+                    EXPECT_OK(std::move(status))
+                            << "\n  For effect: " << toString(effect) << " " << toString(strength);
                 } else {
-                    EXPECT_TRUE(isUnknownOrUnsupported(status))
-                            << status << " " << toString(effect) << " " << toString(strength);
+                    EXPECT_UNKNOWN_OR_UNSUPPORTED(std::move(status))
+                            << "\n  For effect: " << toString(effect) << " " << toString(strength);
                 }
             }
         }
 
-        EXPECT_EQ(Status::EX_NONE, vibrator->alwaysOnDisable(0).exceptionCode());
+        EXPECT_OK(vibrator->alwaysOnDisable(0));
     }
 }
 
@@ -668,12 +687,12 @@
 
 TEST_P(VibratorAidl, GetQFactor) {
     float qFactor;
-    Status status = vibrator->getQFactor(&qFactor);
+    ndk::ScopedAStatus status = vibrator->getQFactor(&qFactor);
     if (capabilities & IVibrator::CAP_GET_Q_FACTOR) {
+        EXPECT_OK(std::move(status));
         ASSERT_GT(qFactor, 0);
-        EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
     } else {
-        EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+        EXPECT_UNKNOWN_OR_UNSUPPORTED(std::move(status));
     }
 }
 
@@ -687,9 +706,9 @@
 
 TEST_P(VibratorAidl, GetBandwidthAmplitudeMap) {
     std::vector<float> bandwidthAmplitudeMap;
-    Status status = vibrator->getBandwidthAmplitudeMap(&bandwidthAmplitudeMap);
+    ndk::ScopedAStatus status = vibrator->getBandwidthAmplitudeMap(&bandwidthAmplitudeMap);
     if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) {
-        EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
+        EXPECT_OK(std::move(status));
         ASSERT_FALSE(bandwidthAmplitudeMap.empty());
 
         int minMapSize = (getResonantFrequencyHz(vibrator, capabilities) -
@@ -702,42 +721,42 @@
             ASSERT_LE(e, 1.0);
         }
     } else {
-        EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+        EXPECT_UNKNOWN_OR_UNSUPPORTED(std::move(status));
     }
 }
 
 TEST_P(VibratorAidl, GetPwlePrimitiveDurationMax) {
     int32_t durationMs;
-    Status status = vibrator->getPwlePrimitiveDurationMax(&durationMs);
+    ndk::ScopedAStatus status = vibrator->getPwlePrimitiveDurationMax(&durationMs);
     if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) {
+        EXPECT_OK(std::move(status));
         ASSERT_NE(durationMs, 0);
-        EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
     } else {
-        EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+        EXPECT_UNKNOWN_OR_UNSUPPORTED(std::move(status));
     }
 }
 
 TEST_P(VibratorAidl, GetPwleCompositionSizeMax) {
     int32_t maxSize;
-    Status status = vibrator->getPwleCompositionSizeMax(&maxSize);
+    ndk::ScopedAStatus status = vibrator->getPwleCompositionSizeMax(&maxSize);
     if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) {
+        EXPECT_OK(std::move(status));
         ASSERT_NE(maxSize, 0);
-        EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
     } else {
-        EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+        EXPECT_UNKNOWN_OR_UNSUPPORTED(std::move(status));
     }
 }
 
 TEST_P(VibratorAidl, GetSupportedBraking) {
     std::vector<Braking> supported;
-    Status status = vibrator->getSupportedBraking(&supported);
+    ndk::ScopedAStatus status = vibrator->getSupportedBraking(&supported);
     if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) {
         bool isDefaultNoneSupported =
             std::find(supported.begin(), supported.end(), Braking::NONE) != supported.end();
+        EXPECT_OK(std::move(status));
         ASSERT_TRUE(isDefaultNoneSupported);
-        EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
     } else {
-        EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+        EXPECT_UNKNOWN_OR_UNSUPPORTED(std::move(status));
     }
 }
 
@@ -746,7 +765,7 @@
         ActivePwle firstActive = composeValidActivePwle(vibrator, capabilities);
 
         std::vector<Braking> supported;
-        ASSERT_TRUE(vibrator->getSupportedBraking(&supported).isOk());
+        EXPECT_OK(vibrator->getSupportedBraking(&supported));
         bool isClabSupported =
             std::find(supported.begin(), supported.end(), Braking::CLAB) != supported.end();
         BrakingPwle firstBraking;
@@ -765,11 +784,11 @@
         secondBraking.braking = Braking::NONE;
         secondBraking.duration = 10;
 
-        auto pwleQueue =
-            std::vector<PrimitivePwle>{firstActive, firstBraking, secondActive, secondBraking};
+        std::vector<PrimitivePwle> pwleQueue = {firstActive, firstBraking, secondActive,
+                                                secondBraking};
 
-        EXPECT_EQ(Status::EX_NONE, vibrator->composePwle(pwleQueue, nullptr).exceptionCode());
-        EXPECT_TRUE(vibrator->off().isOk());
+        EXPECT_OK(vibrator->composePwle(pwleQueue, nullptr));
+        EXPECT_OK(vibrator->off());
     }
 }
 
@@ -780,8 +799,8 @@
 
     std::promise<void> completionPromise;
     std::future<void> completionFuture{completionPromise.get_future()};
-    sp<CompletionCallback> callback =
-        new CompletionCallback([&completionPromise] { completionPromise.set_value(); });
+    auto callback = ndk::SharedRefBase::make<CompletionCallback>(
+            [&completionPromise] { completionPromise.set_value(); });
     int32_t segmentDurationMaxMs;
     vibrator->getPwlePrimitiveDurationMax(&segmentDurationMaxMs);
     uint32_t durationMs = segmentDurationMaxMs * 2 + 100;  // Sum of 2 active and 1 braking below
@@ -790,27 +809,25 @@
     ActivePwle active = composeValidActivePwle(vibrator, capabilities);
 
     std::vector<Braking> supported;
-    ASSERT_TRUE(vibrator->getSupportedBraking(&supported).isOk());
+    EXPECT_OK(vibrator->getSupportedBraking(&supported));
     bool isClabSupported =
         std::find(supported.begin(), supported.end(), Braking::CLAB) != supported.end();
     BrakingPwle braking;
     braking.braking = isClabSupported ? Braking::CLAB : Braking::NONE;
     braking.duration = 100;
 
-    auto pwleQueue = std::vector<PrimitivePwle>{active, braking, active};
+    std::vector<PrimitivePwle> pwleQueue = {active, braking, active};
 
-    EXPECT_TRUE(vibrator->composePwle(pwleQueue, callback).isOk());
+    EXPECT_OK(vibrator->composePwle(pwleQueue, callback));
     EXPECT_EQ(completionFuture.wait_for(timeout), std::future_status::ready);
-    EXPECT_TRUE(vibrator->off().isOk());
+    EXPECT_OK(vibrator->off());
 }
 
 TEST_P(VibratorAidl, ComposePwleSegmentBoundary) {
     if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) {
         std::vector<PrimitivePwle> pwleQueue;
         // test empty queue
-        EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
-                  vibrator->composePwle(pwleQueue, nullptr).exceptionCode());
-        EXPECT_TRUE(vibrator->off().isOk());
+        EXPECT_ILLEGAL_ARGUMENT(vibrator->composePwle(pwleQueue, nullptr));
 
         ActivePwle active = composeValidActivePwle(vibrator, capabilities);
 
@@ -824,9 +841,7 @@
             pwleQueue.emplace_back(std::move(pwle));
         }
 
-        EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
-                  vibrator->composePwle(pwleQueue, nullptr).exceptionCode());
-        EXPECT_TRUE(vibrator->off().isOk());
+        EXPECT_ILLEGAL_ARGUMENT(vibrator->composePwle(pwleQueue, nullptr));
     }
 }
 
@@ -836,20 +851,16 @@
         active.startAmplitude = getAmplitudeMax() + 1.0;  // Amplitude greater than allowed
         active.endAmplitude = getAmplitudeMax() + 1.0;    // Amplitude greater than allowed
 
-        auto pwleQueueGreater = std::vector<PrimitivePwle>{active};
+        std::vector<PrimitivePwle> pwleQueueGreater = {active};
 
-        EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
-                  vibrator->composePwle(pwleQueueGreater, nullptr).exceptionCode());
-        EXPECT_TRUE(vibrator->off().isOk());
+        EXPECT_ILLEGAL_ARGUMENT(vibrator->composePwle(pwleQueueGreater, nullptr));
 
         active.startAmplitude = getAmplitudeMin() - 1.0;  // Amplitude less than allowed
         active.endAmplitude = getAmplitudeMin() - 1.0;    // Amplitude less than allowed
 
-        auto pwleQueueLess = std::vector<PrimitivePwle>{active};
+        std::vector<PrimitivePwle> pwleQueueLess = {active};
 
-        EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
-                  vibrator->composePwle(pwleQueueLess, nullptr).exceptionCode());
-        EXPECT_TRUE(vibrator->off().isOk());
+        EXPECT_ILLEGAL_ARGUMENT(vibrator->composePwle(pwleQueueLess, nullptr));
     }
 }
 
@@ -865,20 +876,16 @@
             freqMaximumHz + freqResolutionHz;                    // Frequency greater than allowed
         active.endFrequency = freqMaximumHz + freqResolutionHz;  // Frequency greater than allowed
 
-        auto pwleQueueGreater = std::vector<PrimitivePwle>{active};
+        std::vector<PrimitivePwle> pwleQueueGreater = {active};
 
-        EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
-                  vibrator->composePwle(pwleQueueGreater, nullptr).exceptionCode());
-        EXPECT_TRUE(vibrator->off().isOk());
+        EXPECT_ILLEGAL_ARGUMENT(vibrator->composePwle(pwleQueueGreater, nullptr));
 
         active.startFrequency = freqMinimumHz - freqResolutionHz;  // Frequency less than allowed
         active.endFrequency = freqMinimumHz - freqResolutionHz;    // Frequency less than allowed
 
-        auto pwleQueueLess = std::vector<PrimitivePwle>{active};
+        std::vector<PrimitivePwle> pwleQueueLess = {active};
 
-        EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
-                  vibrator->composePwle(pwleQueueLess, nullptr).exceptionCode());
-        EXPECT_TRUE(vibrator->off().isOk());
+        EXPECT_ILLEGAL_ARGUMENT(vibrator->composePwle(pwleQueueLess, nullptr));
     }
 }
 
@@ -890,32 +897,30 @@
         vibrator->getPwlePrimitiveDurationMax(&segmentDurationMaxMs);
         active.duration = segmentDurationMaxMs + 10;  // Segment duration greater than allowed
 
-        auto pwleQueue = std::vector<PrimitivePwle>{active};
+        std::vector<PrimitivePwle> pwleQueue = {active};
 
-        EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
-                  vibrator->composePwle(pwleQueue, nullptr).exceptionCode());
-        EXPECT_TRUE(vibrator->off().isOk());
+        EXPECT_ILLEGAL_ARGUMENT(vibrator->composePwle(pwleQueue, nullptr));
     }
 }
 
 std::vector<std::tuple<int32_t, int32_t>> GenerateVibratorMapping() {
     std::vector<std::tuple<int32_t, int32_t>> tuples;
-    auto managerAidlNames = android::getAidlHalInstanceNames(IVibratorManager::descriptor);
-    std::vector<int32_t> vibratorIds;
 
-    for (int i = 0; i < managerAidlNames.size(); i++) {
-        auto managerName = String16(managerAidlNames[i].c_str());
-        auto vibratorManager = android::waitForDeclaredService<IVibratorManager>(managerName);
+    std::vector<std::string> managerNames = findVibratorManagerNames();
+    std::vector<int32_t> vibratorIds;
+    for (int i = 0; i < managerNames.size(); i++) {
+        auto vibratorManager = IVibratorManager::fromBinder(
+                ndk::SpAIBinder(AServiceManager_waitForService(managerNames[i].c_str())));
         if (vibratorManager->getVibratorIds(&vibratorIds).isOk()) {
-            for (auto &vibratorId : vibratorIds) {
-                tuples.push_back(std::make_tuple(i, vibratorId));
+            for (int32_t vibratorId : vibratorIds) {
+                tuples.emplace_back(i, vibratorId);
             }
         }
     }
 
-    auto vibratorAidlNames = android::getAidlHalInstanceNames(IVibrator::descriptor);
-    for (int i = 0; i < vibratorAidlNames.size(); i++) {
-        tuples.push_back(std::make_tuple(-1, i));
+    std::vector<std::string> vibratorNames = findUnmanagedVibratorNames();
+    for (int i = 0; i < vibratorNames.size(); i++) {
+        tuples.emplace_back(-1, i);
     }
 
     return tuples;
@@ -936,7 +941,7 @@
 
 int main(int argc, char **argv) {
     ::testing::InitGoogleTest(&argc, argv);
-    ProcessState::self()->setThreadPoolMaxThreadCount(1);
-    ProcessState::self()->startThreadPool();
+    ABinderProcess_setThreadPoolMaxThreadCount(1);
+    ABinderProcess_startThreadPool();
     return RUN_ALL_TESTS();
 }
diff --git a/vibrator/aidl/vts/test_utils.h b/vibrator/aidl/vts/test_utils.h
new file mode 100644
index 0000000..aaf3211
--- /dev/null
+++ b/vibrator/aidl/vts/test_utils.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2024 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 VIBRATOR_HAL_TEST_UTILS_H
+#define VIBRATOR_HAL_TEST_UTILS_H
+
+#include <android/binder_auto_utils.h>
+#include <gtest/gtest.h>
+
+#if !defined(EXPECT_OK)
+#define EXPECT_OK(expression)                                                \
+    GTEST_AMBIGUOUS_ELSE_BLOCKER_                                            \
+    if (const ::ndk::ScopedAStatus&& _status = (expression); _status.isOk()) \
+        ;                                                                    \
+    else                                                                     \
+        ADD_FAILURE() << "Expected STATUS_OK for: " << #expression << "\n  Actual: " << _status
+#else
+#error Macro EXPECT_OK already defined unexpectedly
+#endif
+
+#if !defined(EXPECT_UNKNOWN_OR_UNSUPPORTED)
+#define EXPECT_UNKNOWN_OR_UNSUPPORTED(expression)                                                \
+    GTEST_AMBIGUOUS_ELSE_BLOCKER_                                                                \
+    if (const ::ndk::ScopedAStatus&& _status = (expression);                                     \
+        _status.getExceptionCode() == EX_UNSUPPORTED_OPERATION ||                                \
+        _status.getStatus() == STATUS_UNKNOWN_TRANSACTION)                                       \
+        ;                                                                                        \
+    else                                                                                         \
+        ADD_FAILURE() << "Expected STATUS_UNKNOWN_TRANSACTION or EX_UNSUPPORTED_OPERATION for: " \
+                      << #expression << "\n  Actual: " << _status
+#else
+#error Macro EXPECT_UNKNOWN_OR_UNSUPPORTED already defined unexpectedly
+#endif
+
+#if !defined(EXPECT_ILLEGAL_ARGUMENT)
+#define EXPECT_ILLEGAL_ARGUMENT(expression)                                  \
+    GTEST_AMBIGUOUS_ELSE_BLOCKER_                                            \
+    if (const ::ndk::ScopedAStatus&& _status = (expression);                 \
+        _status.getExceptionCode() == EX_ILLEGAL_ARGUMENT)                   \
+        ;                                                                    \
+    else                                                                     \
+        ADD_FAILURE() << "Expected EX_ILLEGAL_ARGUMENT for: " << #expression \
+                      << "\n  Actual: " << _status
+#else
+#error Macro EXPECT_ILLEGAL_ARGUMENT already defined unexpectedly
+#endif
+
+#endif  // VIBRATOR_HAL_TEST_UTILS_H
diff --git a/vibrator/bench/Android.bp b/vibrator/bench/Android.bp
index 87bdab4..b31c719 100644
--- a/vibrator/bench/Android.bp
+++ b/vibrator/bench/Android.bp
@@ -30,12 +30,12 @@
         "benchmark.cpp",
     ],
     shared_libs: [
-        "android.hardware.vibrator-V2-cpp",
+        "android.hardware.vibrator-V2-ndk",
         "android.hardware.vibrator@1.0",
         "android.hardware.vibrator@1.1",
         "android.hardware.vibrator@1.2",
         "android.hardware.vibrator@1.3",
-        "libbinder",
+        "libbinder_ndk",
         "libhardware",
         "libhidlbase",
         "libutils",
diff --git a/vibrator/bench/benchmark.cpp b/vibrator/bench/benchmark.cpp
index 8e8d78f..8fe9cf7 100644
--- a/vibrator/bench/benchmark.cpp
+++ b/vibrator/bench/benchmark.cpp
@@ -16,15 +16,14 @@
 
 #include "benchmark/benchmark.h"
 
+#include <aidl/android/hardware/vibrator/BnVibratorCallback.h>
+#include <aidl/android/hardware/vibrator/IVibrator.h>
+
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
 #include <android/hardware/vibrator/1.3/IVibrator.h>
-#include <android/hardware/vibrator/BnVibratorCallback.h>
-#include <android/hardware/vibrator/IVibrator.h>
-#include <binder/IServiceManager.h>
-#include <binder/ProcessState.h>
 #include <future>
 
-using ::android::enum_range;
-using ::android::sp;
 using ::android::hardware::hidl_enum_range;
 using ::android::hardware::Return;
 using ::android::hardware::details::hidl_enum_values;
@@ -33,10 +32,11 @@
 using ::benchmark::kMicrosecond;
 using ::benchmark::State;
 using ::benchmark::internal::Benchmark;
+using ::ndk::enum_range;
 
 using namespace ::std::chrono_literals;
 
-namespace Aidl = ::android::hardware::vibrator;
+namespace Aidl = ::aidl::android::hardware::vibrator;
 namespace V1_0 = ::android::hardware::vibrator::V1_0;
 namespace V1_1 = ::android::hardware::vibrator::V1_1;
 namespace V1_2 = ::android::hardware::vibrator::V1_2;
@@ -56,8 +56,8 @@
 class BaseBench : public Fixture {
   public:
     void SetUp(State& /*state*/) override {
-        android::ProcessState::self()->setThreadPoolMaxThreadCount(1);
-        android::ProcessState::self()->startThreadPool();
+        ABinderProcess_setThreadPoolMaxThreadCount(1);
+        ABinderProcess_startThreadPool();
     }
 
     void TearDown(State& /*state*/) override {
@@ -75,7 +75,7 @@
     auto getOtherArg(const State& state, std::size_t index) const { return state.range(index + 0); }
 
   protected:
-    sp<I> mVibrator;
+    std::shared_ptr<I> mVibrator;
 };
 
 template <typename I>
@@ -83,7 +83,12 @@
   public:
     void SetUp(State& state) override {
         BaseBench<I>::SetUp(state);
-        this->mVibrator = I::getService();
+        auto service = I::getService();
+        if (service) {
+            this->mVibrator = std::shared_ptr<I>(service.release());
+        } else {
+            this->mVibrator = nullptr;
+        }
     }
 
   protected:
@@ -356,7 +361,9 @@
   public:
     void SetUp(State& state) override {
         BaseBench::SetUp(state);
-        this->mVibrator = android::waitForVintfService<Aidl::IVibrator>();
+        auto serviceName = std::string(Aidl::IVibrator::descriptor) + "/default";
+        this->mVibrator = Aidl::IVibrator::fromBinder(
+                ndk::SpAIBinder(AServiceManager_waitForService(serviceName.c_str())));
     }
 
     void TearDown(State& state) override {
@@ -373,9 +380,9 @@
         return (deviceCapabilities & capabilities) == capabilities;
     }
 
-    bool shouldSkipWithError(State& state, const android::binder::Status&& status) {
+    bool shouldSkipWithError(State& state, const ndk::ScopedAStatus&& status) {
         if (!status.isOk()) {
-            state.SkipWithError(status.toString8().c_str());
+            state.SkipWithError(status.getMessage());
             return true;
         }
         return false;
@@ -407,9 +414,9 @@
     HalCallback() = default;
     ~HalCallback() = default;
 
-    android::binder::Status onComplete() override {
+    ndk::ScopedAStatus onComplete() override {
         mPromise.set_value();
-        return android::binder::Status::ok();
+        return ndk::ScopedAStatus::ok();
     }
 
     std::future<void> getFuture() { return mPromise.get_future(); }
@@ -422,7 +429,9 @@
     auto ms = MAX_ON_DURATION_MS;
 
     for (auto _ : state) {
-        auto cb = hasCapabilities(Aidl::IVibrator::CAP_ON_CALLBACK) ? new HalCallback() : nullptr;
+        auto cb = hasCapabilities(Aidl::IVibrator::CAP_ON_CALLBACK)
+                          ? ndk::SharedRefBase::make<HalCallback>()
+                          : nullptr;
         // Grab the future before callback promise is destroyed by the HAL.
         auto cbFuture = cb ? cb->getFuture() : std::future<void>();
 
@@ -445,7 +454,9 @@
     auto ms = MAX_ON_DURATION_MS;
 
     for (auto _ : state) {
-        auto cb = hasCapabilities(Aidl::IVibrator::CAP_ON_CALLBACK) ? new HalCallback() : nullptr;
+        auto cb = hasCapabilities(Aidl::IVibrator::CAP_ON_CALLBACK)
+                          ? ndk::SharedRefBase::make<HalCallback>()
+                          : nullptr;
         // Grab the future before callback promise is destroyed by the HAL.
         auto cbFuture = cb ? cb->getFuture() : std::future<void>();
 
@@ -487,7 +498,9 @@
         return;
     }
 
-    auto cb = hasCapabilities(Aidl::IVibrator::CAP_ON_CALLBACK) ? new HalCallback() : nullptr;
+    auto cb = hasCapabilities(Aidl::IVibrator::CAP_ON_CALLBACK)
+                      ? ndk::SharedRefBase::make<HalCallback>()
+                      : nullptr;
     if (shouldSkipWithError(state, mVibrator->on(ms, cb))) {
         return;
     }
@@ -689,8 +702,9 @@
     int32_t lengthMs = 0;
 
     for (auto _ : state) {
-        auto cb = hasCapabilities(Aidl::IVibrator::CAP_PERFORM_CALLBACK) ? new HalCallback()
-                                                                         : nullptr;
+        auto cb = hasCapabilities(Aidl::IVibrator::CAP_PERFORM_CALLBACK)
+                          ? ndk::SharedRefBase::make<HalCallback>()
+                          : nullptr;
         // Grab the future before callback promise is destroyed by the HAL.
         auto cbFuture = cb ? cb->getFuture() : std::future<void>();
 
@@ -803,7 +817,7 @@
     effects.push_back(effect);
 
     for (auto _ : state) {
-        auto cb = new HalCallback();
+        auto cb = ndk::SharedRefBase::make<HalCallback>();
         // Grab the future before callback promise is moved and destroyed by the HAL.
         auto cbFuture = cb->getFuture();
 
diff --git a/wifi/supplicant/1.1/vts/Android.mk b/wifi/supplicant/1.1/vts/Android.mk
deleted file mode 100644
index 6361f9b..0000000
--- a/wifi/supplicant/1.1/vts/Android.mk
+++ /dev/null
@@ -1,2 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-include $(call all-makefiles-under,$(LOCAL_PATH))