Merge "Add two missing newlines." into main
diff --git a/audio/aidl/android/hardware/audio/core/StreamDescriptor.aidl b/audio/aidl/android/hardware/audio/core/StreamDescriptor.aidl
index cfe001e..9b7fea2 100644
--- a/audio/aidl/android/hardware/audio/core/StreamDescriptor.aidl
+++ b/audio/aidl/android/hardware/audio/core/StreamDescriptor.aidl
@@ -188,6 +188,14 @@
          * In the 'DRAINING' state the producer is inactive, the consumer is
          * finishing up on the buffer contents, emptying it up. As soon as it
          * gets empty, the stream transfers itself into the next state.
+         *
+         * Note that "early notify" draining is a more complex procedure
+         * intended for transitioning between two clips. Both 'DRAINING' and
+         * 'DRAIN_PAUSED' states have "sub-states" not visible via the API. See
+         * the details in the 'stream-out-async-sm.gv' state machine
+         * description. In the HAL API V3 this behavior is enabled when the
+         * HAL exposes "aosp.clipTransitionSupport" property, and in the HAL
+         * API V4 it is the default behavior.
          */
         DRAINING = 5,
         /**
@@ -234,9 +242,15 @@
         /**
          * Used with output streams only, the HAL module indicates drain
          * completion shortly before all audio data has been consumed in order
-         * to give the client an opportunity to provide data for the next track
+         * to give the client an opportunity to provide data for the next clip
          * for gapless playback. The exact amount of provided time is specific
          * to the HAL implementation.
+         *
+         * In the HAL API V3, the HAL sends two 'onDrainReady' notifications:
+         * one to indicate readiness to receive next clip data, and another when
+         * the previous clip has finished playing. This behavior is enabled when
+         * the HAL exposes "aosp.clipTransitionSupport" property, and in the HAL
+         * API V4 it is the default behavior.
          */
         DRAIN_EARLY_NOTIFY = 2,
     }
diff --git a/audio/aidl/android/hardware/audio/core/stream-out-async-sm.gv b/audio/aidl/android/hardware/audio/core/stream-out-async-sm.gv
index e2da90d..bf75594 100644
--- a/audio/aidl/android/hardware/audio/core/stream-out-async-sm.gv
+++ b/audio/aidl/android/hardware/audio/core/stream-out-async-sm.gv
@@ -32,27 +32,78 @@
     IDLE -> TRANSFERRING [label="burst"];             // producer -> active
     IDLE -> ACTIVE [label="burst"];                   // full write
     ACTIVE -> PAUSED [label="pause"];                 // consumer -> passive (not consuming)
-    ACTIVE -> DRAINING [label="drain"];               // producer -> passive
+    ACTIVE -> DRAINING [label="drain(ALL)"];          // producer -> passive
+    ACTIVE -> DRAINING_en [label="drain(EARLY_NOTIFY)"];  // prepare for clip transition
     ACTIVE -> TRANSFERRING [label="burst"];           // early unblocking
     ACTIVE -> ACTIVE [label="burst"];                 // full write
     TRANSFERRING -> ACTIVE [label="←IStreamCallback.onTransferReady"];
     TRANSFERRING -> TRANSFER_PAUSED [label="pause"];  // consumer -> passive (not consuming)
-    TRANSFERRING -> DRAINING [label="drain"];         // producer -> passive
+    TRANSFERRING -> DRAINING [label="drain(ALL)"];    // producer -> passive
+    TRANSFERRING -> DRAINING_en [label="drain(EARLY_NOTIFY)"]; // prepare for clip transition
     TRANSFER_PAUSED -> TRANSFERRING [label="start"];  // consumer -> active
-    TRANSFER_PAUSED -> DRAIN_PAUSED [label="drain"];  // producer -> passive
+    TRANSFER_PAUSED -> DRAIN_PAUSED [label="drain(ALL)"];  // producer -> passive
     TRANSFER_PAUSED -> IDLE [label="flush"];          // buffer is cleared
     PAUSED -> PAUSED [label="burst"];
     PAUSED -> ACTIVE [label="start"];                 // consumer -> active
     PAUSED -> IDLE [label="flush"];                   // producer -> passive, buffer is cleared
     DRAINING -> IDLE [label="←IStreamCallback.onDrainReady"];
-    DRAINING -> DRAINING [label="←IStreamCallback.onDrainReady"];  // allowed for `DRAIN_EARLY_NOTIFY`
-    DRAINING -> IDLE [label="<empty buffer>"];        // allowed for `DRAIN_EARLY_NOTIFY`
     DRAINING -> TRANSFERRING [label="burst"];         // producer -> active
     DRAINING -> ACTIVE [label="burst"];               // full write
     DRAINING -> DRAIN_PAUSED [label="pause"];         // consumer -> passive (not consuming)
     DRAIN_PAUSED -> DRAINING [label="start"];         // consumer -> active
     DRAIN_PAUSED -> TRANSFER_PAUSED [label="burst"];  // producer -> active
     DRAIN_PAUSED -> IDLE [label="flush"];             // buffer is cleared
+    // Note that the states in both clusters are combined with 'DRAINING' and 'DRAIN_PAUSED'
+    // state at the API level. The 'en' and 'en_sent' attributes only belong to the internal
+    // state of the stream and are not observable outside.
+    subgraph cluster_early_notify_entering {
+        // The stream is preparing for a transition between two clips. After
+        // receiving 'drain(EARLY_NOTIFY)' command, the stream continues playing
+        // the current clip, and at some point notifies the client that it is
+        // ready for the next clip data by issuing the first 'onDrainReady'
+        // callback.
+        label="EARLY_NOTIFY (entering)";
+        color=gray;
+        // Getting 'burst' or 'flush' command in these states resets the "clip
+        // transition" mode.
+        DRAINING_en;
+        DRAIN_PAUSED_en;
+    }
+    subgraph cluster_early_notify_notification_sent {
+        // After the stream has sent "onDrainReady", the client can now send
+        // 'burst' commands with the data of the next clip. These 'bursts' are
+        // always "early unblocking" because the previous clip is still playing
+        // thus the stream is unable to play any of the received data
+        // synchronously (in other words, it can not do a "full write"). To
+        // indicate readiness to accept the next burst the stream uses the usual
+        // 'onTransferReady' callback.
+        label="EARLY_NOTIFY (notification sent)";
+        color=gray;
+        // The state machine remains in these states until the current clip ends
+        // playing. When it ends, the stream sends 'onDrainReady' (note that
+        // it's the second 'onDrainReady' for the same 'drain(EARLY_NOTIFY)'),
+        // and transitions either to 'IDLE' if there is no data for the next
+        // clip, or to 'TRANSFERRING' otherwise. Note that it can not transition
+        // to 'ACTIVE' because that transition is associated with
+        // 'onTransferReady' callback.
+        DRAINING_en_sent;
+        DRAIN_PAUSED_en_sent;
+    }
+    DRAINING_en -> TRANSFERRING [label="burst"];                  // producer -> active
+    DRAINING_en -> ACTIVE [label="burst"];                        // full write
+    DRAINING_en -> DRAIN_PAUSED_en [label="pause"];               // consumer -> passive (not consuming)
+    DRAINING_en -> DRAINING_en_sent [label="←IStreamCallback.onDrainReady"];
+    DRAIN_PAUSED_en -> DRAINING_en [label="start"];               // consumer -> active
+    DRAIN_PAUSED_en -> TRANSFER_PAUSED [label="burst"];           // producer -> active
+    DRAIN_PAUSED_en -> IDLE [label="flush"];                      // buffer is cleared
+    DRAINING_en_sent -> DRAINING_en_sent [label="burst"];
+    DRAINING_en_sent -> DRAINING_en_sent [label="←IStreamCallback.onTransferReady"];
+    DRAINING_en_sent -> DRAIN_PAUSED_en_sent [label="pause"];     // consumer -> passive (not consuming)
+    DRAINING_en_sent -> TRANSFERRING [label="←IStreamCallback.onDrainReady"];
+    DRAINING_en_sent -> IDLE [label="←IStreamCallback.onDrainReady"];
+    DRAIN_PAUSED_en_sent -> DRAINING_en_sent [label="start"];     // consumer -> active
+    DRAIN_PAUSED_en_sent -> DRAIN_PAUSED_en_sent [label="burst"]; // producer -> active
+    DRAIN_PAUSED_en_sent -> IDLE [label="flush"];                 // buffer is cleared
     ANY_STATE -> ERROR [label="←IStreamCallback.onError"];
     ANY_STATE -> CLOSED [label="→IStream*.close"];
     CLOSED -> F;
diff --git a/audio/aidl/default/Module.cpp b/audio/aidl/default/Module.cpp
index 077d80b..123a5ec 100644
--- a/audio/aidl/default/Module.cpp
+++ b/audio/aidl/default/Module.cpp
@@ -612,6 +612,15 @@
     return ndk::ScopedAStatus::ok();
 }
 
+binder_status_t Module::dump(int fd, const char** args, uint32_t numArgs) {
+    for (const auto& portConfig : getConfig().portConfigs) {
+        if (portConfig.ext.getTag() == AudioPortExt::Tag::mix) {
+            getStreams().dump(portConfig.id, fd, args, numArgs);
+        }
+    }
+    return STATUS_OK;
+}
+
 ndk::ScopedAStatus Module::setModuleDebug(
         const ::aidl::android::hardware::audio::core::ModuleDebug& in_debug) {
     LOG(DEBUG) << __func__ << ": " << mType << ": old flags:" << mDebug.toString()
@@ -1546,6 +1555,7 @@
 
 const std::string Module::VendorDebug::kForceTransientBurstName = "aosp.forceTransientBurst";
 const std::string Module::VendorDebug::kForceSynchronousDrainName = "aosp.forceSynchronousDrain";
+const std::string Module::kClipTransitionSupportName = "aosp.clipTransitionSupport";
 
 ndk::ScopedAStatus Module::getVendorParameters(const std::vector<std::string>& in_ids,
                                                std::vector<VendorParameter>* _aidl_return) {
@@ -1560,6 +1570,10 @@
             VendorParameter forceSynchronousDrain{.id = id};
             forceSynchronousDrain.ext.setParcelable(Boolean{mVendorDebug.forceSynchronousDrain});
             _aidl_return->push_back(std::move(forceSynchronousDrain));
+        } else if (id == kClipTransitionSupportName) {
+            VendorParameter clipTransitionSupport{.id = id};
+            clipTransitionSupport.ext.setParcelable(Boolean{true});
+            _aidl_return->push_back(std::move(clipTransitionSupport));
         } else {
             allParametersKnown = false;
             LOG(VERBOSE) << __func__ << ": " << mType << ": unrecognized parameter \"" << id << "\"";
diff --git a/audio/aidl/default/Stream.cpp b/audio/aidl/default/Stream.cpp
index c6c1b5d..2800bed 100644
--- a/audio/aidl/default/Stream.cpp
+++ b/audio/aidl/default/Stream.cpp
@@ -252,9 +252,10 @@
                     mState == StreamDescriptor::State::ACTIVE ||
                     mState == StreamDescriptor::State::PAUSED ||
                     mState == StreamDescriptor::State::DRAINING) {
-                    if (hasMmapFlag(mContext->getFlags())) {
-                        populateReply(&reply, mIsConnected);
-                    } else if (!read(fmqByteCount, &reply)) {
+                    if (bool success = hasMmapFlag(mContext->getFlags())
+                                               ? readMmap(&reply)
+                                               : read(fmqByteCount, &reply);
+                        !success) {
                         mState = StreamDescriptor::State::ERROR;
                     }
                     if (mState == StreamDescriptor::State::IDLE ||
@@ -383,16 +384,38 @@
     return !fatal;
 }
 
+bool StreamInWorkerLogic::readMmap(StreamDescriptor::Reply* reply) {
+    void* buffer = nullptr;
+    size_t frameCount = 0;
+    size_t actualFrameCount = 0;
+    int32_t latency = mContext->getNominalLatencyMs();
+    // use default-initialized parameter values for mmap stream.
+    if (::android::status_t status =
+                mDriver->transfer(buffer, frameCount, &actualFrameCount, &latency);
+        status == ::android::OK) {
+        populateReply(reply, mIsConnected);
+        reply->latencyMs = latency;
+        return true;
+    } else {
+        LOG(ERROR) << __func__ << ": transfer failed: " << status;
+        return false;
+    }
+}
+
 const std::string StreamOutWorkerLogic::kThreadName = "writer";
 
 void StreamOutWorkerLogic::onBufferStateChange(size_t bufferFramesLeft) {
     const StreamDescriptor::State state = mState;
-    LOG(DEBUG) << __func__ << ": state: " << toString(state)
+    const DrainState drainState = mDrainState;
+    LOG(DEBUG) << __func__ << ": state: " << toString(state) << ", drainState: " << drainState
                << ", bufferFramesLeft: " << bufferFramesLeft;
-    if (state == StreamDescriptor::State::TRANSFERRING) {
-        mState = StreamDescriptor::State::ACTIVE;
+    if (state == StreamDescriptor::State::TRANSFERRING || drainState == DrainState::EN_SENT) {
+        if (state == StreamDescriptor::State::TRANSFERRING) {
+            mState = StreamDescriptor::State::ACTIVE;
+        }
         std::shared_ptr<IStreamCallback> asyncCallback = mContext->getAsyncCallback();
         if (asyncCallback != nullptr) {
+            LOG(VERBOSE) << __func__ << ": sending onTransferReady";
             ndk::ScopedAStatus status = asyncCallback->onTransferReady();
             if (!status.isOk()) {
                 LOG(ERROR) << __func__ << ": error from onTransferReady: " << status;
@@ -411,8 +434,10 @@
         mState =
                 hasNextClip ? StreamDescriptor::State::TRANSFERRING : StreamDescriptor::State::IDLE;
         mDrainState = DrainState::NONE;
-        if (drainState == DrainState::ALL && asyncCallback != nullptr) {
+        if ((drainState == DrainState::ALL || drainState == DrainState::EN_SENT) &&
+            asyncCallback != nullptr) {
             LOG(DEBUG) << __func__ << ": sending onDrainReady";
+            // For EN_SENT, this is the second onDrainReady which notifies about clip transition.
             ndk::ScopedAStatus status = asyncCallback->onDrainReady();
             if (!status.isOk()) {
                 LOG(ERROR) << __func__ << ": error from onDrainReady: " << status;
@@ -523,9 +548,10 @@
                 if (mState != StreamDescriptor::State::ERROR &&
                     mState != StreamDescriptor::State::TRANSFERRING &&
                     mState != StreamDescriptor::State::TRANSFER_PAUSED) {
-                    if (hasMmapFlag(mContext->getFlags())) {
-                        populateReply(&reply, mIsConnected);
-                    } else if (!write(fmqByteCount, &reply)) {
+                    if (bool success = hasMmapFlag(mContext->getFlags())
+                                               ? writeMmap(&reply)
+                                               : write(fmqByteCount, &reply);
+                        !success) {
                         mState = StreamDescriptor::State::ERROR;
                     }
                     std::shared_ptr<IStreamCallback> asyncCallback = mContext->getAsyncCallback();
@@ -539,13 +565,17 @@
                             mState = StreamDescriptor::State::TRANSFER_PAUSED;
                         }
                     } else if (mState == StreamDescriptor::State::IDLE ||
-                               mState == StreamDescriptor::State::DRAINING ||
-                               mState == StreamDescriptor::State::ACTIVE) {
+                               mState == StreamDescriptor::State::ACTIVE ||
+                               (mState == StreamDescriptor::State::DRAINING &&
+                                mDrainState != DrainState::EN_SENT)) {
                         if (asyncCallback == nullptr || reply.fmqByteCount == fmqByteCount) {
                             mState = StreamDescriptor::State::ACTIVE;
                         } else {
                             switchToTransientState(StreamDescriptor::State::TRANSFERRING);
                         }
+                    } else if (mState == StreamDescriptor::State::DRAINING &&
+                               mDrainState == DrainState::EN_SENT) {
+                        // keep mState
                     }
                 } else {
                     populateReplyWrongState(&reply, command);
@@ -700,6 +730,24 @@
     return !fatal;
 }
 
+bool StreamOutWorkerLogic::writeMmap(StreamDescriptor::Reply* reply) {
+    void* buffer = nullptr;
+    size_t frameCount = 0;
+    size_t actualFrameCount = 0;
+    int32_t latency = mContext->getNominalLatencyMs();
+    // use default-initialized parameter values for mmap stream.
+    if (::android::status_t status =
+                mDriver->transfer(buffer, frameCount, &actualFrameCount, &latency);
+        status == ::android::OK) {
+        populateReply(reply, mIsConnected);
+        reply->latencyMs = latency;
+        return true;
+    } else {
+        LOG(ERROR) << __func__ << ": transfer failed: " << status;
+        return false;
+    }
+}
+
 StreamCommonImpl::~StreamCommonImpl() {
     // It is responsibility of the class that implements 'DriverInterface' to call 'cleanupWorker'
     // in the destructor. Note that 'cleanupWorker' can not be properly called from this destructor
diff --git a/audio/aidl/default/include/core-impl/Module.h b/audio/aidl/default/include/core-impl/Module.h
index 6a43102..0661015 100644
--- a/audio/aidl/default/include/core-impl/Module.h
+++ b/audio/aidl/default/include/core-impl/Module.h
@@ -61,6 +61,8 @@
     // The vendor extension done via inheritance can override interface methods and augment
     // a call to the base implementation.
 
+    binder_status_t dump(int fd, const char** args, uint32_t numArgs) override;
+
     ndk::ScopedAStatus setModuleDebug(
             const ::aidl::android::hardware::audio::core::ModuleDebug& in_debug) override;
     ndk::ScopedAStatus getTelephony(std::shared_ptr<ITelephony>* _aidl_return) override;
@@ -159,6 +161,7 @@
     // Multimap because both ports and configs can be used by multiple patches.
     using Patches = std::multimap<int32_t, int32_t>;
 
+    static const std::string kClipTransitionSupportName;
     const Type mType;
     std::unique_ptr<Configuration> mConfig;
     ModuleDebug mDebug;
diff --git a/audio/aidl/default/include/core-impl/Stream.h b/audio/aidl/default/include/core-impl/Stream.h
index f0139b4..376c684 100644
--- a/audio/aidl/default/include/core-impl/Stream.h
+++ b/audio/aidl/default/include/core-impl/Stream.h
@@ -307,6 +307,7 @@
 
   private:
     bool read(size_t clientSize, StreamDescriptor::Reply* reply);
+    bool readMmap(StreamDescriptor::Reply* reply);
 };
 using StreamInWorker = StreamWorkerImpl<StreamInWorkerLogic>;
 
@@ -325,6 +326,7 @@
 
   private:
     bool write(size_t clientSize, StreamDescriptor::Reply* reply);
+    bool writeMmap(StreamDescriptor::Reply* reply);
 
     std::shared_ptr<IStreamOutEventCallback> mEventCallback;
 
@@ -651,6 +653,12 @@
         return ndk::ScopedAStatus::ok();
     }
 
+    void dump(int fd, const char** args, uint32_t numArgs) const {
+        auto s = ::ndk::ICInterface::asInterface(mStreamBinder.get());
+        if (s) s->dump(fd, args, numArgs);
+        return;
+    }
+
   private:
     std::weak_ptr<StreamCommonInterface> mStream;
     ndk::SpAIBinder mStreamBinder;
@@ -692,6 +700,12 @@
         }
         return ndk::ScopedAStatus::ok();
     }
+    void dump(int32_t portConfigId, int fd, const char** args, uint32_t numArgs) const {
+        if (auto it = mStreams.find(portConfigId); it != mStreams.end()) {
+            it->second.dump(fd, args, numArgs);
+        }
+        return;
+    }
 
   private:
     // Maps port ids and port config ids to streams. Multimap because a port
diff --git a/audio/aidl/default/include/core-impl/StreamOffloadStub.h b/audio/aidl/default/include/core-impl/StreamOffloadStub.h
index 67abe95..24e98c2 100644
--- a/audio/aidl/default/include/core-impl/StreamOffloadStub.h
+++ b/audio/aidl/default/include/core-impl/StreamOffloadStub.h
@@ -26,14 +26,16 @@
 namespace aidl::android::hardware::audio::core {
 
 struct DspSimulatorState {
+    static constexpr int64_t kSkipBufferNotifyFrames = -1;
+
     const std::string formatEncoding;
     const int sampleRate;
     const int64_t earlyNotifyFrames;
-    const int64_t bufferNotifyFrames;
     DriverCallbackInterface* callback = nullptr;  // set before starting DSP worker
     std::mutex lock;
     std::vector<int64_t> clipFramesLeft GUARDED_BY(lock);
-    int64_t bufferFramesLeft GUARDED_BY(lock);
+    int64_t bufferFramesLeft GUARDED_BY(lock) = 0;
+    int64_t bufferNotifyFrames GUARDED_BY(lock) = kSkipBufferNotifyFrames;
 };
 
 class DspSimulatorLogic : public ::android::hardware::audio::common::StreamLogic {
@@ -68,6 +70,7 @@
   private:
     ::android::status_t startWorkerIfNeeded();
 
+    const int64_t mBufferNotifyFrames;
     DspSimulatorState mState;
     DspSimulatorWorker mDspWorker;
     bool mDspWorkerStarted = false;
diff --git a/audio/aidl/default/stub/StreamOffloadStub.cpp b/audio/aidl/default/stub/StreamOffloadStub.cpp
index 95cef35..155f76d 100644
--- a/audio/aidl/default/stub/StreamOffloadStub.cpp
+++ b/audio/aidl/default/stub/StreamOffloadStub.cpp
@@ -42,14 +42,13 @@
     const int64_t clipFramesPlayed =
             (::android::uptimeNanos() - timeBeginNs) * mSharedState.sampleRate / NANOS_PER_SECOND;
     const int64_t bufferFramesConsumed = clipFramesPlayed / 2;  // assume 1:2 compression ratio
-    int64_t bufferFramesLeft = 0;
+    int64_t bufferFramesLeft = 0, bufferNotifyFrames = DspSimulatorState::kSkipBufferNotifyFrames;
     {
         std::lock_guard l(mSharedState.lock);
         mSharedState.bufferFramesLeft =
                 mSharedState.bufferFramesLeft > bufferFramesConsumed
                         ? mSharedState.bufferFramesLeft - bufferFramesConsumed
                         : 0;
-        bufferFramesLeft = mSharedState.bufferFramesLeft;
         int64_t framesPlayed = clipFramesPlayed;
         while (framesPlayed > 0 && !mSharedState.clipFramesLeft.empty()) {
             LOG(VERBOSE) << __func__ << ": clips: "
@@ -65,10 +64,21 @@
                 clipNotifies.emplace_back(0 /*clipFramesLeft*/, hasNextClip);
                 framesPlayed -= mSharedState.clipFramesLeft[0];
                 mSharedState.clipFramesLeft.erase(mSharedState.clipFramesLeft.begin());
+                if (!hasNextClip) {
+                    // Since it's a simulation, the buffer consumption rate it not real,
+                    // thus 'bufferFramesLeft' might still have something, need to erase it.
+                    mSharedState.bufferFramesLeft = 0;
+                }
             }
         }
+        bufferFramesLeft = mSharedState.bufferFramesLeft;
+        bufferNotifyFrames = mSharedState.bufferNotifyFrames;
+        if (bufferFramesLeft <= bufferNotifyFrames) {
+            // Suppress further notifications.
+            mSharedState.bufferNotifyFrames = DspSimulatorState::kSkipBufferNotifyFrames;
+        }
     }
-    if (bufferFramesLeft <= mSharedState.bufferNotifyFrames) {
+    if (bufferFramesLeft <= bufferNotifyFrames) {
         LOG(DEBUG) << __func__ << ": sending onBufferStateChange: " << bufferFramesLeft;
         mSharedState.callback->onBufferStateChange(bufferFramesLeft);
     }
@@ -82,9 +92,9 @@
 
 DriverOffloadStubImpl::DriverOffloadStubImpl(const StreamContext& context)
     : DriverStubImpl(context, 0 /*asyncSleepTimeUs*/),
+      mBufferNotifyFrames(static_cast<int64_t>(context.getBufferSizeInFrames()) / 2),
       mState{context.getFormat().encoding, context.getSampleRate(),
-             250 /*earlyNotifyMs*/ * context.getSampleRate() / MILLIS_PER_SECOND,
-             static_cast<int64_t>(context.getBufferSizeInFrames()) / 2},
+             250 /*earlyNotifyMs*/ * context.getSampleRate() / MILLIS_PER_SECOND},
       mDspWorker(mState) {
     LOG_IF(FATAL, !mIsAsynchronous) << "The steam must be used in asynchronous mode";
 }
@@ -111,6 +121,7 @@
             mState.clipFramesLeft.resize(1);
         }
     }
+    mState.bufferNotifyFrames = DspSimulatorState::kSkipBufferNotifyFrames;
     return ::android::OK;
 }
 
@@ -121,6 +132,7 @@
         std::lock_guard l(mState.lock);
         mState.clipFramesLeft.clear();
         mState.bufferFramesLeft = 0;
+        mState.bufferNotifyFrames = DspSimulatorState::kSkipBufferNotifyFrames;
     }
     return ::android::OK;
 }
@@ -128,6 +140,10 @@
 ::android::status_t DriverOffloadStubImpl::pause() {
     RETURN_STATUS_IF_ERROR(DriverStubImpl::pause());
     mDspWorker.pause();
+    {
+        std::lock_guard l(mState.lock);
+        mState.bufferNotifyFrames = DspSimulatorState::kSkipBufferNotifyFrames;
+    }
     return ::android::OK;
 }
 
@@ -140,6 +156,7 @@
         hasClips = !mState.clipFramesLeft.empty();
         LOG(DEBUG) << __func__
                    << ": clipFramesLeft: " << ::android::internal::ToString(mState.clipFramesLeft);
+        mState.bufferNotifyFrames = DspSimulatorState::kSkipBufferNotifyFrames;
     }
     if (hasClips) {
         mDspWorker.resume();
@@ -184,6 +201,7 @@
     {
         std::lock_guard l(mState.lock);
         mState.bufferFramesLeft = *actualFrameCount;
+        mState.bufferNotifyFrames = mBufferNotifyFrames;
     }
     mDspWorker.resume();
     return ::android::OK;
diff --git a/audio/aidl/vts/VtsHalAECTargetTest.cpp b/audio/aidl/vts/VtsHalAECTargetTest.cpp
index c007f18..2fc126e 100644
--- a/audio/aidl/vts/VtsHalAECTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAECTargetTest.cpp
@@ -140,12 +140,12 @@
 
 TEST_P(AECParamTest, SetAndGetEchoDelay) {
     addEchoDelayParam(mEchoDelay);
-    SetAndGetParameters();
+    ASSERT_NO_FATAL_FAILURE(SetAndGetParameters());
 }
 
 TEST_P(AECParamTest, SetAndGetMobileMode) {
     addMobileModeParam(mMobileMode);
-    SetAndGetParameters();
+    ASSERT_NO_FATAL_FAILURE(SetAndGetParameters());
 }
 
 std::vector<std::pair<std::shared_ptr<IFactory>, Descriptor>> kDescPair;
diff --git a/audio/aidl/vts/VtsHalAGC1TargetTest.cpp b/audio/aidl/vts/VtsHalAGC1TargetTest.cpp
index 72a2d5e..033cb9d 100644
--- a/audio/aidl/vts/VtsHalAGC1TargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAGC1TargetTest.cpp
@@ -140,17 +140,17 @@
 
 TEST_P(AGC1ParamTest, SetAndGetTargetPeakLevelParam) {
     addTargetPeakLevelParam(mTargetPeakLevel);
-    SetAndGetParameters();
+    ASSERT_NO_FATAL_FAILURE(SetAndGetParameters());
 }
 
 TEST_P(AGC1ParamTest, SetAndGetMaxCompressionGain) {
     addMaxCompressionGainParam(mMaxCompressionGain);
-    SetAndGetParameters();
+    ASSERT_NO_FATAL_FAILURE(SetAndGetParameters());
 }
 
 TEST_P(AGC1ParamTest, SetAndGetEnableLimiter) {
     addEnableLimiterParam(mEnableLimiter);
-    SetAndGetParameters();
+    ASSERT_NO_FATAL_FAILURE(SetAndGetParameters());
 }
 
 std::vector<std::pair<std::shared_ptr<IFactory>, Descriptor>> kDescPair;
diff --git a/audio/aidl/vts/VtsHalAGC2TargetTest.cpp b/audio/aidl/vts/VtsHalAGC2TargetTest.cpp
index ccac8c5..9dec383 100644
--- a/audio/aidl/vts/VtsHalAGC2TargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAGC2TargetTest.cpp
@@ -146,17 +146,17 @@
 
 TEST_P(AGC2ParamTest, SetAndGetDigitalGainParam) {
     addDigitalGainParam(mGain);
-    SetAndGetParameters();
+    ASSERT_NO_FATAL_FAILURE(SetAndGetParameters());
 }
 
 TEST_P(AGC2ParamTest, SetAndGetSaturationMargin) {
     addSaturationMarginParam(mMargin);
-    SetAndGetParameters();
+    ASSERT_NO_FATAL_FAILURE(SetAndGetParameters());
 }
 
 TEST_P(AGC2ParamTest, SetAndGetLevelEstimator) {
     addLevelEstimatorParam(mLevelEstimator);
-    SetAndGetParameters();
+    ASSERT_NO_FATAL_FAILURE(SetAndGetParameters());
 }
 
 std::vector<std::pair<std::shared_ptr<IFactory>, Descriptor>> kDescPair;
diff --git a/audio/aidl/vts/VtsHalAudioCoreConfigTargetTest.cpp b/audio/aidl/vts/VtsHalAudioCoreConfigTargetTest.cpp
index b1c5a1a..713af9a 100644
--- a/audio/aidl/vts/VtsHalAudioCoreConfigTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioCoreConfigTargetTest.cpp
@@ -522,7 +522,8 @@
         std::unordered_set<std::string> configurationNames;
         for (const AudioHalCapConfiguration& configuration : domain.configurations) {
             EXPECT_TRUE(configurationNames.insert(configuration.name).second);
-            ValidateAudioHalConfigurationRule(configuration.rule, criteria);
+            ASSERT_NO_FATAL_FAILURE(
+                    ValidateAudioHalConfigurationRule(configuration.rule, criteria));
         }
         auto domainParameters = domain.configurations[0].parameterSettings;
         for (const auto& settingParameter : domainParameters) {
@@ -597,7 +598,8 @@
             }
             EXPECT_NO_FATAL_FAILURE(ValidateAudioHalCapCriterion(criterion.value()));
         }
-        ValidateAudioHalCapDomains(capCfg.domains.value(), capCfg.criteriaV2.value());
+        ASSERT_NO_FATAL_FAILURE(
+                ValidateAudioHalCapDomains(capCfg.domains.value(), capCfg.criteriaV2.value()));
     }
 
     /**
diff --git a/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp b/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
index 21b7aff..806c93f 100644
--- a/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
@@ -1025,6 +1025,7 @@
             auto [eventSeq, event] = mEventReceiver->waitForEvent(mLastEventSeq);
             mLastEventSeq = eventSeq;
             if (event != *expEvent) {
+                // TODO: Make available as an error so it can be displayed by GTest
                 LOG(ERROR) << __func__ << ": expected event " << toString(*expEvent) << ", got "
                            << toString(event);
                 return {};
@@ -1327,7 +1328,8 @@
   public:
     // To avoid timing out the whole test suite in case no event is received
     // from the HAL, use a local timeout for event waiting.
-    static constexpr auto kEventTimeoutMs = std::chrono::milliseconds(1000);
+    // TODO: The timeout for 'onTransferReady' should depend on the buffer size.
+    static constexpr auto kEventTimeoutMs = std::chrono::milliseconds(3000);
 
     StreamEventReceiver* getEventReceiver() { return this; }
     std::tuple<int, Event> getLastEvent() const override {
@@ -4236,15 +4238,17 @@
 enum {
     NAMED_CMD_NAME,
     NAMED_CMD_MIN_INTERFACE_VERSION,
+    NAMED_CMD_FEATURE_PROPERTY,
     NAMED_CMD_DELAY_MS,
     NAMED_CMD_STREAM_TYPE,
     NAMED_CMD_CMDS,
     NAMED_CMD_VALIDATE_POS_INCREASE
 };
-enum class StreamTypeFilter { ANY, SYNC, ASYNC };
+enum class StreamTypeFilter { ANY, SYNC, ASYNC, OFFLOAD };
 using NamedCommandSequence =
-        std::tuple<std::string, int /*minInterfaceVersion*/, int /*cmdDelayMs*/, StreamTypeFilter,
-                   std::shared_ptr<StateSequence>, bool /*validatePositionIncrease*/>;
+        std::tuple<std::string, int /*minInterfaceVersion*/, std::string /*featureProperty*/,
+                   int /*cmdDelayMs*/, StreamTypeFilter, std::shared_ptr<StateSequence>,
+                   bool /*validatePositionIncrease*/>;
 enum { PARAM_MODULE_NAME, PARAM_CMD_SEQ, PARAM_SETUP_SEQ };
 using StreamIoTestParameters =
         std::tuple<std::string /*moduleName*/, NamedCommandSequence, bool /*useSetupSequence2*/>;
@@ -4255,11 +4259,24 @@
     void SetUp() override {
         ASSERT_NO_FATAL_FAILURE(SetUpImpl(std::get<PARAM_MODULE_NAME>(GetParam())));
         ASSERT_GE(aidlVersion, kAidlVersion1);
-        if (const int minVersion =
-                    std::get<NAMED_CMD_MIN_INTERFACE_VERSION>(std::get<PARAM_CMD_SEQ>(GetParam()));
-            aidlVersion < minVersion) {
+        const int minVersion =
+                std::get<NAMED_CMD_MIN_INTERFACE_VERSION>(std::get<PARAM_CMD_SEQ>(GetParam()));
+        if (aidlVersion < minVersion) {
             GTEST_SKIP() << "Skip for audio HAL version lower than " << minVersion;
         }
+        // When an associated feature property is defined, need to check that either that the HAL
+        // exposes this property, or it's of the version 'NAMED_CMD_MIN_INTERFACE_VERSION' + 1
+        // which must have this functionality implemented by default.
+        if (const std::string featureProperty =
+                    std::get<NAMED_CMD_FEATURE_PROPERTY>(std::get<PARAM_CMD_SEQ>(GetParam()));
+            !featureProperty.empty() && aidlVersion < (minVersion + 1)) {
+            std::vector<VendorParameter> parameters;
+            ScopedAStatus result = module->getVendorParameters({featureProperty}, &parameters);
+            if (!result.isOk() || parameters.size() != 1) {
+                GTEST_SKIP() << "Skip as audio HAL does not support feature \"" << featureProperty
+                             << "\"";
+            }
+        }
         ASSERT_NO_FATAL_FAILURE(SetUpModuleConfig());
     }
 
@@ -4300,10 +4317,18 @@
                             isBitPositionFlagSet(portConfig.flags.value()
                                                          .template get<AudioIoFlags::Tag::output>(),
                                                  AudioOutputFlags::NON_BLOCKING);
+            const bool isOffload =
+                    IOTraits<Stream>::is_input
+                            ? false
+                            : isBitPositionFlagSet(
+                                      portConfig.flags.value()
+                                              .template get<AudioIoFlags::Tag::output>(),
+                                      AudioOutputFlags::COMPRESS_OFFLOAD);
             if (auto streamType =
                         std::get<NAMED_CMD_STREAM_TYPE>(std::get<PARAM_CMD_SEQ>(GetParam()));
                 (isNonBlocking && streamType == StreamTypeFilter::SYNC) ||
-                (!isNonBlocking && streamType == StreamTypeFilter::ASYNC)) {
+                (!isNonBlocking && streamType == StreamTypeFilter::ASYNC) ||
+                (!isOffload && streamType == StreamTypeFilter::OFFLOAD)) {
                 continue;
             }
             WithDebugFlags delayTransientStates = WithDebugFlags::createNested(*debug);
@@ -4760,6 +4785,18 @@
 
 // TODO: Add async test cases for input once it is implemented.
 
+// Allow optional routing via the TRANSFERRING state on bursts.
+StateDag::Node makeAsyncBurstCommands(StateDag* d, size_t burstCount, StateDag::Node last) {
+    using State = StreamDescriptor::State;
+    std::reference_wrapper<std::remove_reference_t<StateDag::Node>> prev = last;
+    for (size_t i = 0; i < burstCount; ++i) {
+        StateDag::Node active = d->makeNode(State::ACTIVE, kBurstCommand, prev);
+        active.children().push_back(d->makeNode(State::TRANSFERRING, kTransferReadyEvent, prev));
+        prev = active;
+    }
+    return prev;
+}
+
 std::shared_ptr<StateSequence> makeBurstCommands(bool isSync, size_t burstCount,
                                                  bool standbyInputWhenDone) {
     using State = StreamDescriptor::State;
@@ -4776,25 +4813,21 @@
                 d->makeNodes(State::ACTIVE, kBurstCommand, burstCount, last));
         d->makeNode(State::STANDBY, kStartCommand, idle);
     } else {
-        StateDag::Node active2 = d->makeNode(State::ACTIVE, kBurstCommand, last);
-        StateDag::Node active = d->makeNode(State::ACTIVE, kBurstCommand, active2);
+        StateDag::Node active = makeAsyncBurstCommands(d.get(), burstCount, last);
         StateDag::Node idle = d->makeNode(State::IDLE, kBurstCommand, active);
-        // Allow optional routing via the TRANSFERRING state on bursts.
-        active2.children().push_back(d->makeNode(State::TRANSFERRING, kTransferReadyEvent, last));
-        active.children().push_back(d->makeNode(State::TRANSFERRING, kTransferReadyEvent, active2));
         idle.children().push_back(d->makeNode(State::TRANSFERRING, kTransferReadyEvent, active));
         d->makeNode(State::STANDBY, kStartCommand, idle);
     }
     return std::make_shared<StateSequenceFollower>(std::move(d));
 }
 static const NamedCommandSequence kReadSeq =
-        std::make_tuple(std::string("Read"), kAidlVersion1, 0, StreamTypeFilter::ANY,
+        std::make_tuple(std::string("Read"), kAidlVersion1, "", 0, StreamTypeFilter::ANY,
                         makeBurstCommands(true), true /*validatePositionIncrease*/);
 static const NamedCommandSequence kWriteSyncSeq =
-        std::make_tuple(std::string("Write"), kAidlVersion1, 0, StreamTypeFilter::SYNC,
+        std::make_tuple(std::string("Write"), kAidlVersion1, "", 0, StreamTypeFilter::SYNC,
                         makeBurstCommands(true), true /*validatePositionIncrease*/);
 static const NamedCommandSequence kWriteAsyncSeq =
-        std::make_tuple(std::string("Write"), kAidlVersion1, 0, StreamTypeFilter::ASYNC,
+        std::make_tuple(std::string("Write"), kAidlVersion1, "", 0, StreamTypeFilter::ASYNC,
                         makeBurstCommands(false), true /*validatePositionIncrease*/);
 
 std::shared_ptr<StateSequence> makeAsyncDrainCommands(bool isInput) {
@@ -4824,10 +4857,10 @@
     return std::make_shared<StateSequenceFollower>(std::move(d));
 }
 static const NamedCommandSequence kWriteDrainAsyncSeq = std::make_tuple(
-        std::string("WriteDrain"), kAidlVersion1, kStreamTransientStateTransitionDelayMs,
+        std::string("WriteDrain"), kAidlVersion1, "", kStreamTransientStateTransitionDelayMs,
         StreamTypeFilter::ASYNC, makeAsyncDrainCommands(false), false /*validatePositionIncrease*/);
 static const NamedCommandSequence kDrainInSeq =
-        std::make_tuple(std::string("Drain"), kAidlVersion1, 0, StreamTypeFilter::ANY,
+        std::make_tuple(std::string("Drain"), kAidlVersion1, "", 0, StreamTypeFilter::ANY,
                         makeAsyncDrainCommands(true), false /*validatePositionIncrease*/);
 
 std::shared_ptr<StateSequence> makeDrainOutCommands(bool isSync) {
@@ -4849,10 +4882,10 @@
     return std::make_shared<StateSequenceFollower>(std::move(d));
 }
 static const NamedCommandSequence kDrainOutSyncSeq =
-        std::make_tuple(std::string("Drain"), kAidlVersion1, 0, StreamTypeFilter::SYNC,
+        std::make_tuple(std::string("Drain"), kAidlVersion1, "", 0, StreamTypeFilter::SYNC,
                         makeDrainOutCommands(true), false /*validatePositionIncrease*/);
 static const NamedCommandSequence kDrainOutAsyncSeq =
-        std::make_tuple(std::string("Drain"), kAidlVersion3, 0, StreamTypeFilter::ASYNC,
+        std::make_tuple(std::string("Drain"), kAidlVersion3, "", 0, StreamTypeFilter::ASYNC,
                         makeDrainOutCommands(false), false /*validatePositionIncrease*/);
 
 std::shared_ptr<StateSequence> makeDrainEarlyOutCommands() {
@@ -4873,9 +4906,32 @@
     return std::make_shared<StateSequenceFollower>(std::move(d));
 }
 static const NamedCommandSequence kDrainEarlyOutAsyncSeq =
-        std::make_tuple(std::string("DrainEarly"), kAidlVersion3, 0, StreamTypeFilter::ASYNC,
+        std::make_tuple(std::string("DrainEarly"), kAidlVersion3, "", 0, StreamTypeFilter::ASYNC,
                         makeDrainEarlyOutCommands(), false /*validatePositionIncrease*/);
 
+// DRAINING_en ->(onDrainReady) DRAINING_en_sent ->(onDrainReady) IDLE | TRANSFERRING
+std::shared_ptr<StateSequence> makeDrainEarlyOffloadCommands() {
+    using State = StreamDescriptor::State;
+    auto d = std::make_unique<StateDag>();
+    StateDag::Node lastIdle = d->makeFinalNode(State::IDLE);
+    StateDag::Node lastTransferring = d->makeFinalNode(State::TRANSFERRING);
+    // The second onDrainReady event.
+    StateDag::Node continueDraining =
+            d->makeNode(State::DRAINING, kDrainReadyEvent, lastIdle, lastTransferring);
+    // The first onDrainReady event.
+    StateDag::Node draining = d->makeNode(State::DRAINING, kDrainReadyEvent, continueDraining);
+    StateDag::Node drain = d->makeNode(State::ACTIVE, kDrainOutEarlyCommand, draining);
+    StateDag::Node active = makeAsyncBurstCommands(d.get(), 10, drain);
+    StateDag::Node idle = d->makeNode(State::IDLE, kBurstCommand, active);
+    idle.children().push_back(d->makeNode(State::TRANSFERRING, kTransferReadyEvent, active));
+    d->makeNode(State::STANDBY, kStartCommand, idle);
+    return std::make_shared<StateSequenceFollower>(std::move(d));
+}
+static const NamedCommandSequence kDrainEarlyOffloadSeq =
+        std::make_tuple(std::string("DrainEarly"), kAidlVersion3, "aosp.clipTransitionSupport", 0,
+                        StreamTypeFilter::OFFLOAD, makeDrainEarlyOffloadCommands(),
+                        true /*validatePositionIncrease*/);
+
 std::shared_ptr<StateSequence> makeDrainPauseOutCommands(bool isSync) {
     using State = StreamDescriptor::State;
     auto d = std::make_unique<StateDag>();
@@ -4896,11 +4952,11 @@
     return std::make_shared<StateSequenceFollower>(std::move(d));
 }
 static const NamedCommandSequence kDrainPauseOutSyncSeq =
-        std::make_tuple(std::string("DrainPause"), kAidlVersion1,
+        std::make_tuple(std::string("DrainPause"), kAidlVersion1, "",
                         kStreamTransientStateTransitionDelayMs, StreamTypeFilter::SYNC,
                         makeDrainPauseOutCommands(true), false /*validatePositionIncrease*/);
 static const NamedCommandSequence kDrainPauseOutAsyncSeq =
-        std::make_tuple(std::string("DrainPause"), kAidlVersion1,
+        std::make_tuple(std::string("DrainPause"), kAidlVersion1, "",
                         kStreamTransientStateTransitionDelayMs, StreamTypeFilter::ASYNC,
                         makeDrainPauseOutCommands(false), false /*validatePositionIncrease*/);
 
@@ -4919,7 +4975,7 @@
     return std::make_shared<StateSequenceFollower>(std::move(d));
 }
 static const NamedCommandSequence kDrainEarlyPauseOutAsyncSeq =
-        std::make_tuple(std::string("DrainEarlyPause"), kAidlVersion3,
+        std::make_tuple(std::string("DrainEarlyPause"), kAidlVersion3, "",
                         kStreamTransientStateTransitionDelayMs, StreamTypeFilter::ASYNC,
                         makeDrainEarlyPauseOutCommands(), false /*validatePositionIncrease*/);
 
@@ -4963,13 +5019,13 @@
     return std::make_shared<StateSequenceFollower>(std::move(d));
 }
 static const NamedCommandSequence kStandbyInSeq =
-        std::make_tuple(std::string("Standby"), kAidlVersion1, 0, StreamTypeFilter::ANY,
+        std::make_tuple(std::string("Standby"), kAidlVersion1, "", 0, StreamTypeFilter::ANY,
                         makeStandbyCommands(true, false), false /*validatePositionIncrease*/);
 static const NamedCommandSequence kStandbyOutSyncSeq =
-        std::make_tuple(std::string("Standby"), kAidlVersion1, 0, StreamTypeFilter::SYNC,
+        std::make_tuple(std::string("Standby"), kAidlVersion1, "", 0, StreamTypeFilter::SYNC,
                         makeStandbyCommands(false, true), false /*validatePositionIncrease*/);
 static const NamedCommandSequence kStandbyOutAsyncSeq =
-        std::make_tuple(std::string("Standby"), kAidlVersion1,
+        std::make_tuple(std::string("Standby"), kAidlVersion1, "",
                         kStreamTransientStateTransitionDelayMs, StreamTypeFilter::ASYNC,
                         makeStandbyCommands(false, false), false /*validatePositionIncrease*/);
 
@@ -5006,15 +5062,15 @@
     return std::make_shared<StateSequenceFollower>(std::move(d));
 }
 static const NamedCommandSequence kPauseInSeq =
-        std::make_tuple(std::string("Pause"), kAidlVersion1, 0, StreamTypeFilter::ANY,
+        std::make_tuple(std::string("Pause"), kAidlVersion1, "", 0, StreamTypeFilter::ANY,
                         makePauseCommands(true, false), false /*validatePositionIncrease*/);
 static const NamedCommandSequence kPauseOutSyncSeq =
-        std::make_tuple(std::string("Pause"), kAidlVersion1, 0, StreamTypeFilter::SYNC,
+        std::make_tuple(std::string("Pause"), kAidlVersion1, "", 0, StreamTypeFilter::SYNC,
                         makePauseCommands(false, true), false /*validatePositionIncrease*/);
 static const NamedCommandSequence kPauseOutAsyncSeq =
-        std::make_tuple(std::string("Pause"), kAidlVersion3, kStreamTransientStateTransitionDelayMs,
-                        StreamTypeFilter::ASYNC, makePauseCommands(false, false),
-                        false /*validatePositionIncrease*/);
+        std::make_tuple(std::string("Pause"), kAidlVersion3, "",
+                        kStreamTransientStateTransitionDelayMs, StreamTypeFilter::ASYNC,
+                        makePauseCommands(false, false), false /*validatePositionIncrease*/);
 
 std::shared_ptr<StateSequence> makeFlushCommands(bool isInput, bool isSync) {
     using State = StreamDescriptor::State;
@@ -5042,15 +5098,15 @@
     return std::make_shared<StateSequenceFollower>(std::move(d));
 }
 static const NamedCommandSequence kFlushInSeq =
-        std::make_tuple(std::string("Flush"), kAidlVersion1, 0, StreamTypeFilter::ANY,
+        std::make_tuple(std::string("Flush"), kAidlVersion1, "", 0, StreamTypeFilter::ANY,
                         makeFlushCommands(true, false), false /*validatePositionIncrease*/);
 static const NamedCommandSequence kFlushOutSyncSeq =
-        std::make_tuple(std::string("Flush"), kAidlVersion1, 0, StreamTypeFilter::SYNC,
+        std::make_tuple(std::string("Flush"), kAidlVersion1, "", 0, StreamTypeFilter::SYNC,
                         makeFlushCommands(false, true), false /*validatePositionIncrease*/);
 static const NamedCommandSequence kFlushOutAsyncSeq =
-        std::make_tuple(std::string("Flush"), kAidlVersion1, kStreamTransientStateTransitionDelayMs,
-                        StreamTypeFilter::ASYNC, makeFlushCommands(false, false),
-                        false /*validatePositionIncrease*/);
+        std::make_tuple(std::string("Flush"), kAidlVersion1, "",
+                        kStreamTransientStateTransitionDelayMs, StreamTypeFilter::ASYNC,
+                        makeFlushCommands(false, false), false /*validatePositionIncrease*/);
 
 std::shared_ptr<StateSequence> makeDrainPauseFlushOutCommands(bool isSync) {
     using State = StreamDescriptor::State;
@@ -5070,11 +5126,11 @@
     return std::make_shared<StateSequenceFollower>(std::move(d));
 }
 static const NamedCommandSequence kDrainPauseFlushOutSyncSeq =
-        std::make_tuple(std::string("DrainPauseFlush"), kAidlVersion1,
+        std::make_tuple(std::string("DrainPauseFlush"), kAidlVersion1, "",
                         kStreamTransientStateTransitionDelayMs, StreamTypeFilter::SYNC,
                         makeDrainPauseFlushOutCommands(true), false /*validatePositionIncrease*/);
 static const NamedCommandSequence kDrainPauseFlushOutAsyncSeq =
-        std::make_tuple(std::string("DrainPauseFlush"), kAidlVersion1,
+        std::make_tuple(std::string("DrainPauseFlush"), kAidlVersion1, "",
                         kStreamTransientStateTransitionDelayMs, StreamTypeFilter::ASYNC,
                         makeDrainPauseFlushOutCommands(false), false /*validatePositionIncrease*/);
 
@@ -5087,6 +5143,8 @@
             return "Sync";
         case StreamTypeFilter::ASYNC:
             return "Async";
+        case StreamTypeFilter::OFFLOAD:
+            return "Offload";
     }
     return std::string("Unknown").append(std::to_string(static_cast<int32_t>(filter)));
 }
@@ -5119,7 +5177,8 @@
                                          kDrainPauseOutAsyncSeq, kDrainEarlyPauseOutAsyncSeq,
                                          kStandbyOutSyncSeq, kStandbyOutAsyncSeq, kPauseOutSyncSeq,
                                          kPauseOutAsyncSeq, kFlushOutSyncSeq, kFlushOutAsyncSeq,
-                                         kDrainPauseFlushOutSyncSeq, kDrainPauseFlushOutAsyncSeq),
+                                         kDrainPauseFlushOutSyncSeq, kDrainPauseFlushOutAsyncSeq,
+                                         kDrainEarlyOffloadSeq),
                          testing::Values(false, true)),
         GetStreamIoTestName);
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioStreamIoOut);
diff --git a/audio/aidl/vts/VtsHalAudioEffectFactoryTargetTest.cpp b/audio/aidl/vts/VtsHalAudioEffectFactoryTargetTest.cpp
index a19aa56..5621285 100644
--- a/audio/aidl/vts/VtsHalAudioEffectFactoryTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioEffectFactoryTargetTest.cpp
@@ -56,7 +56,7 @@
 /// Effect factory testing.
 class EffectFactoryTest : public testing::TestWithParam<std::string> {
   public:
-    void SetUp() override { connectAndGetFactory(); }
+    void SetUp() override { ASSERT_NO_FATAL_FAILURE(connectAndGetFactory()); }
 
     void TearDown() override {
         for (auto& effect : mEffects) {
@@ -253,7 +253,7 @@
     creatAndDestroyDescs(descs);
 
     restartAndGetFactory();
-    connectAndGetFactory();
+    ASSERT_NO_FATAL_FAILURE(connectAndGetFactory());
     creatAndDestroyDescs(descs);
 }
 
@@ -265,7 +265,7 @@
     std::vector<std::shared_ptr<IEffect>> effects = createWithDescs(descs);
 
     restartAndGetFactory();
-    connectAndGetFactory();
+    ASSERT_NO_FATAL_FAILURE(connectAndGetFactory());
     destroyEffects(effects, EX_ILLEGAL_ARGUMENT);
 }
 
diff --git a/audio/aidl/vts/VtsHalDownmixTargetTest.cpp b/audio/aidl/vts/VtsHalDownmixTargetTest.cpp
index 5c5be3a..720a040 100644
--- a/audio/aidl/vts/VtsHalDownmixTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalDownmixTargetTest.cpp
@@ -190,7 +190,7 @@
         std::tie(mFactory, mDescriptor) = std::get<PARAM_INSTANCE_NAME>(GetParam());
     }
 
-    void SetUp() override { SetUpDownmix(); }
+    void SetUp() override { ASSERT_NO_FATAL_FAILURE(SetUpDownmix()); }
 
     void TearDown() override { TearDownDownmix(); }
 
@@ -216,7 +216,7 @@
 
     void SetUp() override {
         SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
-        SetUpDownmix(mInputChannelLayout);
+        ASSERT_NO_FATAL_FAILURE(SetUpDownmix(mInputChannelLayout));
         if (int32_t version;
             mEffect->getInterfaceVersion(&version).isOk() && version < kMinDataTestHalVersion) {
             GTEST_SKIP() << "Skipping the data test for version: " << version << "\n";
@@ -288,7 +288,7 @@
             case AudioChannelLayout::CHANNEL_TOP_BACK_LEFT:
             case AudioChannelLayout::CHANNEL_FRONT_WIDE_LEFT:
             case AudioChannelLayout::CHANNEL_TOP_SIDE_LEFT:
-                checkAtLeft(position);
+                ASSERT_NO_FATAL_FAILURE(checkAtLeft(position));
                 break;
 
             case AudioChannelLayout::CHANNEL_FRONT_RIGHT:
@@ -300,7 +300,7 @@
             case AudioChannelLayout::CHANNEL_FRONT_WIDE_RIGHT:
             case AudioChannelLayout::CHANNEL_TOP_SIDE_RIGHT:
             case AudioChannelLayout::CHANNEL_LOW_FREQUENCY_2:
-                checkAtRight(position);
+                ASSERT_NO_FATAL_FAILURE(checkAtRight(position));
                 break;
 
             case AudioChannelLayout::CHANNEL_FRONT_CENTER:
@@ -311,17 +311,17 @@
             case AudioChannelLayout::CHANNEL_FRONT_RIGHT_OF_CENTER:
             case AudioChannelLayout::CHANNEL_TOP_CENTER:
             case AudioChannelLayout::CHANNEL_TOP_BACK_CENTER:
-                checkAtCenter(position);
+                ASSERT_NO_FATAL_FAILURE(checkAtCenter(position));
                 break;
 
             case AudioChannelLayout::CHANNEL_LOW_FREQUENCY:
                 // If CHANNEL_LOW_FREQUENCY_2 is supported
                 if (mInputChannelLayout & AudioChannelLayout::CHANNEL_LOW_FREQUENCY_2) {
                     // Validate that only Left channel has audio
-                    checkAtLeft(position);
+                    ASSERT_NO_FATAL_FAILURE(checkAtLeft(position));
                 } else {
                     // Validate that both channels have audio
-                    checkAtCenter(position);
+                    ASSERT_NO_FATAL_FAILURE(checkAtCenter(position));
                 }
                 break;
         }
@@ -371,7 +371,7 @@
     }
 
     void SetUp() override {
-        SetUpDownmix(mInputChannelLayout);
+        ASSERT_NO_FATAL_FAILURE(SetUpDownmix(mInputChannelLayout));
         if (int32_t version;
             mEffect->getInterfaceVersion(&version).isOk() && version < kMinDataTestHalVersion) {
             GTEST_SKIP() << "Skipping the data test for version: " << version << "\n";
@@ -406,7 +406,7 @@
                         mInputChannelCount /*channelCount*/, kMaxDownmixSample);
     ASSERT_NO_FATAL_FAILURE(
             processAndWriteToOutput(mInputBuffer, mOutputBuffer, mEffect, &mOpenEffectReturn));
-    validateOutput();
+    ASSERT_NO_FATAL_FAILURE(validateOutput());
 }
 
 INSTANTIATE_TEST_SUITE_P(
diff --git a/audio/aidl/vts/VtsHalDynamicsProcessingTest.cpp b/audio/aidl/vts/VtsHalDynamicsProcessingTest.cpp
index 2bb0a72..2ce7b51 100644
--- a/audio/aidl/vts/VtsHalDynamicsProcessingTest.cpp
+++ b/audio/aidl/vts/VtsHalDynamicsProcessingTest.cpp
@@ -39,6 +39,8 @@
 using aidl::android::hardware::audio::effect::Parameter;
 using android::hardware::audio::common::testing::detail::TestExecutionTracer;
 
+constexpr int32_t kMinDataTestHalVersion = 3;
+
 /**
  * Here we focus on specific parameter checking, general IEffect interfaces testing performed in
  * VtsAudioEffectTargetTest.
@@ -139,6 +141,8 @@
     void addLimiterConfig(const std::vector<DynamicsProcessing::LimiterConfig>& cfg);
     void addInputGain(const std::vector<DynamicsProcessing::InputGain>& inputGain);
 
+    void checkHalVersion();
+
     static constexpr float kPreferredProcessingDurationMs = 10.0f;
     static constexpr int kBandCount = 5;
     static constexpr int kSamplingFrequency = 44100;
@@ -548,6 +552,13 @@
     mTags.push_back({DynamicsProcessing::inputGain, dp});
 }
 
+void DynamicsProcessingTestHelper::checkHalVersion() {
+    if (int32_t version;
+        mEffect->getInterfaceVersion(&version).isOk() && version < kMinDataTestHalVersion) {
+        GTEST_SKIP() << "Skipping the data test for version: " << version << "\n";
+    }
+}
+
 void fillLimiterConfig(std::vector<DynamicsProcessing::LimiterConfig>& limiterConfigList,
                        int channelIndex, bool enable, int linkGroup, float attackTime,
                        float releaseTime, float ratio, float threshold, float postGain) {
@@ -585,10 +596,10 @@
 }
 
 DynamicsProcessing::EqBandConfig creatEqBandConfig(int channel, int band, float cutOffFreqHz,
-                                                   float gainDb) {
+                                                   float gainDb, bool enable) {
     return DynamicsProcessing::EqBandConfig{.channel = channel,
                                             .band = band,
-                                            .enable = true,
+                                            .enable = enable,
                                             .cutoffFrequencyHz = cutOffFreqHz,
                                             .gainDb = gainDb};
 }
@@ -624,7 +635,7 @@
         fillEngineArchConfig(mCfg, GetParam());
     };
 
-    void SetUp() override { SetUpDynamicsProcessingEffect(); }
+    void SetUp() override { ASSERT_NO_FATAL_FAILURE(SetUpDynamicsProcessingEffect()); }
 
     void TearDown() override { TearDownDynamicsProcessingEffect(); }
 
@@ -676,7 +687,7 @@
         : DynamicsProcessingTestHelper(std::get<INPUT_GAIN_INSTANCE_NAME>(GetParam())),
           mInputGain(std::get<INPUT_GAIN_PARAM>(GetParam())) {};
 
-    void SetUp() override { SetUpDynamicsProcessingEffect(); }
+    void SetUp() override { ASSERT_NO_FATAL_FAILURE(SetUpDynamicsProcessingEffect()); }
 
     void TearDown() override { TearDownDynamicsProcessingEffect(); }
 
@@ -715,7 +726,10 @@
         mInput.resize(kFrameCount * mChannelCount);
     }
 
-    void SetUp() override { setUpDataTest({static_cast<int>(kInputFrequency)}, kSineFullScaleDb); }
+    void SetUp() override {
+        ASSERT_NO_FATAL_FAILURE(
+                setUpDataTest({static_cast<int>(kInputFrequency)}, kSineFullScaleDb));
+    }
 
     void TearDown() override { TearDownDynamicsProcessingEffect(); }
 
@@ -793,7 +807,7 @@
         fillLimiterConfig(mLimiterConfigList, GetParam());
     }
 
-    void SetUp() override { SetUpDynamicsProcessingEffect(); }
+    void SetUp() override { ASSERT_NO_FATAL_FAILURE(SetUpDynamicsProcessingEffect()); }
 
     void TearDown() override { TearDownDynamicsProcessingEffect(); }
 
@@ -843,7 +857,10 @@
         mInput.resize(mBufferSize);
     }
 
-    void SetUp() override { setUpDataTest({static_cast<int>(kInputFrequency)}, kSineFullScaleDb); }
+    void SetUp() override {
+        ASSERT_NO_FATAL_FAILURE(
+                setUpDataTest({static_cast<int>(kInputFrequency)}, kSineFullScaleDb));
+    }
 
     void TearDown() override { TearDownDynamicsProcessingEffect(); }
 
@@ -1011,7 +1028,7 @@
         : DynamicsProcessingTestHelper(std::get<BAND_CHANNEL_TEST_INSTANCE_NAME>(GetParam())),
           mCfg(std::get<BAND_CHANNEL_TEST_CHANNEL_CONFIG>(GetParam())) {}
 
-    void SetUp() override { SetUpDynamicsProcessingEffect(); }
+    void SetUp() override { ASSERT_NO_FATAL_FAILURE(SetUpDynamicsProcessingEffect()); }
 
     void TearDown() override { TearDownDynamicsProcessingEffect(); }
 
@@ -1075,7 +1092,8 @@
     int bandCount = cutOffFreqs.size();
     for (int i = 0; i < bandCount; i++) {
         cfgs.push_back(creatEqBandConfig(std::get<EQ_BAND_CHANNEL>(params), cutOffFreqs[i].first,
-                                         cutOffFreqs[i].second, std::get<EQ_BAND_GAIN>(params)));
+                                         cutOffFreqs[i].second, std::get<EQ_BAND_GAIN>(params),
+                                         true));
     }
 }
 
@@ -1087,7 +1105,7 @@
         fillEqBandConfig(mCfgs, GetParam());
     }
 
-    void SetUp() override { SetUpDynamicsProcessingEffect(); }
+    void SetUp() override { ASSERT_NO_FATAL_FAILURE(SetUpDynamicsProcessingEffect()); }
 
     void TearDown() override { TearDownDynamicsProcessingEffect(); }
 
@@ -1223,15 +1241,16 @@
     }
 
     void fillEqBandConfig(std::vector<DynamicsProcessing::EqBandConfig>& cfgs, int channelIndex,
-                          int bandIndex, int cutOffFreqHz, float gainDb) {
+                          int bandIndex, int cutOffFreqHz, float gainDb, bool enable) {
         cfgs.push_back(creatEqBandConfig(channelIndex, bandIndex, static_cast<float>(cutOffFreqHz),
-                                         gainDb));
+                                         gainDb, enable));
     }
 
-    void validateOutput(const std::vector<float>& output, float gainDb, size_t bandIndex) {
+    void validateOutput(const std::vector<float>& output, float gainDb, size_t bandIndex,
+                        bool enable) {
         std::vector<float> outputMag(mBinOffsets.size());
         EXPECT_NO_FATAL_FAILURE(getMagnitudeValue(output, outputMag));
-        if (gainDb == 0) {
+        if (gainDb == 0 || !enable) {
             EXPECT_NO_FATAL_FAILURE(checkInputAndOutputEquality(outputMag));
         } else if (gainDb > 0) {
             // For positive gain, current band's magnitude is greater than the other band's
@@ -1243,19 +1262,19 @@
         }
     }
 
-    void analyseMultiBandOutput(float gainDb, bool isPreEq) {
+    void analyseMultiBandOutput(float gainDb, bool isPreEq, bool enable = true) {
         std::vector<float> output(mInput.size());
         roundToFreqCenteredToFftBin(mMultitoneTestFrequencies, mBinOffsets, kBinWidth);
         // Set Equalizer values for two bands
         for (size_t i = 0; i < kCutoffFreqHz.size(); i++) {
             for (int channelIndex = 0; channelIndex < mChannelCount; channelIndex++) {
-                fillEqBandConfig(mCfgs, channelIndex, i, kCutoffFreqHz[i], gainDb);
-                fillEqBandConfig(mCfgs, channelIndex, i ^ 1, kCutoffFreqHz[i ^ 1], 0);
+                fillEqBandConfig(mCfgs, channelIndex, i, kCutoffFreqHz[i], gainDb, enable);
+                fillEqBandConfig(mCfgs, channelIndex, i ^ 1, kCutoffFreqHz[i ^ 1], 0, enable);
             }
             ASSERT_NO_FATAL_FAILURE(setEqParamAndProcess(output, isPreEq));
 
             if (isAllParamsValid()) {
-                ASSERT_NO_FATAL_FAILURE(validateOutput(output, gainDb, i));
+                ASSERT_NO_FATAL_FAILURE(validateOutput(output, gainDb, i, enable));
             }
             cleanUpEqConfig();
         }
@@ -1291,6 +1310,16 @@
     }
 }
 
+TEST_P(DynamicsProcessingEqBandConfigDataTest, PreEqEnableDisable) {
+    ASSERT_NO_FATAL_FAILURE(analyseMultiBandOutput(10 /*gain dB*/, true /*pre-equalizer*/,
+                                                   false /*disable equalizer*/));
+}
+
+TEST_P(DynamicsProcessingEqBandConfigDataTest, PostEqEnableDisable) {
+    ASSERT_NO_FATAL_FAILURE(analyseMultiBandOutput(10 /*gain dB*/, false /*post-equalizer*/,
+                                                   false /*disable equalizer*/));
+}
+
 INSTANTIATE_TEST_SUITE_P(DynamicsProcessingTest, DynamicsProcessingEqBandConfigDataTest,
                          testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
                                  IFactory::descriptor, getEffectTypeUuidDynamicsProcessing())),
@@ -1368,7 +1397,7 @@
         fillMbcBandConfig(mCfgs, GetParam());
     }
 
-    void SetUp() override { SetUpDynamicsProcessingEffect(); }
+    void SetUp() override { ASSERT_NO_FATAL_FAILURE(SetUpDynamicsProcessingEffect()); }
 
     void TearDown() override { TearDownDynamicsProcessingEffect(); }
 
@@ -1541,6 +1570,51 @@
     }
 }
 
+TEST_P(DynamicsProcessingMbcBandConfigDataTest, IncreasingPreGain) {
+    /*
+    Depending on the pregain values, samples undergo either compression or expansion process.
+    At -6 dB input,
+    - Expansion is expected at -60 dB,
+    - Compression at 10, 34 and 60 dB
+    - No compression or expansion at -34, -10, -1 dB.
+     */
+    std::vector<float> preGainDbValues = {-60, -34, -10, -1, 10, 34, 60};
+    std::vector<float> output(mInput.size());
+    float thresholdDb = -7;
+    float noiseGateDb = -40;
+    std::vector<float> ratioValues = {1, 1.5, 2, 2.5, 3};
+    for (float ratio : ratioValues) {
+        for (float preGainDb : preGainDbValues) {
+            float expectedOutputDb;
+            float inputWithPreGain = mInputDb + preGainDb;
+            if (inputWithPreGain > thresholdDb) {
+                SCOPED_TRACE("Compressor ratio: " + std::to_string(ratio));
+                expectedOutputDb =
+                        (inputWithPreGain - thresholdDb) / ratio + thresholdDb - preGainDb;
+            } else if (inputWithPreGain < noiseGateDb) {
+                SCOPED_TRACE("Expander ratio: " + std::to_string(ratio));
+                expectedOutputDb =
+                        (inputWithPreGain - noiseGateDb) * ratio + noiseGateDb - preGainDb;
+            } else {
+                expectedOutputDb = mInputDb;
+            }
+            cleanUpMbcConfig();
+            for (int i = 0; i < mChannelCount; i++) {
+                fillMbcBandConfig(mCfgs, i, thresholdDb, ratio /*compressor ratio*/, noiseGateDb,
+                                  ratio /*expander ratio*/, 0 /*band index*/,
+                                  2000 /*cutoffFrequency*/, preGainDb, kDefaultPostGainDb);
+            }
+            EXPECT_NO_FATAL_FAILURE(setMbcParamsAndProcess(output));
+            if (!isAllParamsValid()) {
+                continue;
+            }
+            float outputDb = calculateDb(output, kStartIndex);
+            EXPECT_NEAR(outputDb, expectedOutputDb, kToleranceDb)
+                    << "PreGain: " << preGainDb << ", OutputDb: " << outputDb;
+        }
+    }
+}
+
 INSTANTIATE_TEST_SUITE_P(DynamicsProcessingTest, DynamicsProcessingMbcBandConfigDataTest,
                          testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
                                  IFactory::descriptor, getEffectTypeUuidDynamicsProcessing())),
diff --git a/audio/aidl/vts/VtsHalEnvironmentalReverbTargetTest.cpp b/audio/aidl/vts/VtsHalEnvironmentalReverbTargetTest.cpp
index 0222923..9b1a3b3 100644
--- a/audio/aidl/vts/VtsHalEnvironmentalReverbTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalEnvironmentalReverbTargetTest.cpp
@@ -305,7 +305,7 @@
         : EnvironmentalReverbHelper(std::get<DESCRIPTOR_INDEX>(GetParam())) {
         std::tie(mTag, mParamValue) = std::get<TAG_VALUE_PAIR>(GetParam());
     }
-    void SetUp() override { SetUpReverb(); }
+    void SetUp() override { ASSERT_NO_FATAL_FAILURE(SetUpReverb()); }
     void TearDown() override { TearDownReverb(); }
 
     EnvironmentalReverb::Tag mTag;
@@ -350,7 +350,7 @@
         SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
         ASSERT_NO_FATAL_FAILURE(
                 generateSineWave(kInputFrequency, mInput, 1.0, kSamplingFrequency, mChannelLayout));
-        SetUpReverb();
+        ASSERT_NO_FATAL_FAILURE(SetUpReverb());
     }
     void TearDown() override {
         SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
@@ -387,11 +387,11 @@
 };
 
 TEST_P(EnvironmentalReverbDataTest, IncreasingParamValue) {
-    assertEnergyIncreasingWithParameter(false);
+    ASSERT_NO_FATAL_FAILURE(assertEnergyIncreasingWithParameter(false));
 }
 
 TEST_P(EnvironmentalReverbDataTest, WithBypassEnabled) {
-    assertZeroEnergyWithBypass(true);
+    ASSERT_NO_FATAL_FAILURE(assertZeroEnergyWithBypass(true));
 }
 
 INSTANTIATE_TEST_SUITE_P(
@@ -420,7 +420,7 @@
     }
     void SetUp() override {
         SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
-        SetUpReverb();
+        ASSERT_NO_FATAL_FAILURE(SetUpReverb());
         createEnvParam(EnvironmentalReverb::roomLevelMb, kMinRoomLevel);
         ASSERT_NO_FATAL_FAILURE(
                 setAndVerifyParam(EX_NONE, mEnvParam, EnvironmentalReverb::roomLevelMb));
@@ -478,7 +478,7 @@
         SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
         ASSERT_NO_FATAL_FAILURE(
                 generateSineWave(kInputFrequency, mInput, 1.0, kSamplingFrequency, mChannelLayout));
-        SetUpReverb();
+        ASSERT_NO_FATAL_FAILURE(SetUpReverb());
     }
     void TearDown() override {
         SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
@@ -559,7 +559,7 @@
             ASSERT_NO_FATAL_FAILURE(generateSineWave(kInputFrequency, mInput, 1.0,
                                                      kSamplingFrequency, mChannelLayout));
         }
-        SetUpReverb();
+        ASSERT_NO_FATAL_FAILURE(SetUpReverb());
     }
     void TearDown() override {
         SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
diff --git a/audio/aidl/vts/VtsHalEqualizerTargetTest.cpp b/audio/aidl/vts/VtsHalEqualizerTargetTest.cpp
index 0c931ff..86177fc 100644
--- a/audio/aidl/vts/VtsHalEqualizerTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalEqualizerTargetTest.cpp
@@ -18,10 +18,10 @@
 #include <string>
 #include <vector>
 
+#define LOG_TAG "VtsHalEqualizerTest"
 #include <aidl/Gtest.h>
 #include <aidl/android/hardware/audio/effect/IEffect.h>
 #include <aidl/android/hardware/audio/effect/IFactory.h>
-#define LOG_TAG "VtsHalEqualizerTest"
 #include <android-base/logging.h>
 #include <android-base/properties.h>
 #include <android/binder_interface_utils.h>
@@ -48,8 +48,8 @@
  */
 
 enum ParamName { PARAM_INSTANCE_NAME, PARAM_PRESET, PARAM_BAND_LEVEL };
-using EqualizerParamTestParam = std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int,
-                                           std::vector<Equalizer::BandLevel>>;
+using EqualizerTestParam = std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int,
+                                      std::vector<Equalizer::BandLevel>>;
 
 /*
 Testing parameter range, assuming the parameter supported by effect is in this range.
@@ -58,38 +58,34 @@
 */
 const std::vector<int> kBandLevels = {0, -10, 10};  // needs update with implementation
 
-class EqualizerTest : public ::testing::TestWithParam<EqualizerParamTestParam>,
-                      public EffectHelper {
+class EqualizerTestHelper : public EffectHelper {
   public:
-    EqualizerTest()
-        : mPresetIndex(std::get<PARAM_PRESET>(GetParam())),
-          mBandLevel(std::get<PARAM_BAND_LEVEL>(GetParam())) {
-        std::tie(mFactory, mDescriptor) = std::get<PARAM_INSTANCE_NAME>(GetParam());
+    EqualizerTestHelper(std::pair<std::shared_ptr<IFactory>, Descriptor> descPair,
+                        int presetIndex = 0,
+                        std::vector<Equalizer::BandLevel> bandLevel =
+                                std::vector<Equalizer::BandLevel>{
+                                        Equalizer::BandLevel({.index = 0, .levelMb = 0})})
+        : mFactory(descPair.first), mPresetIndex(presetIndex), mBandLevel(bandLevel) {
+        mDescriptor = descPair.second;
     }
 
-    void SetUp() override {
+    void SetUpEqualizer() {
         ASSERT_NE(nullptr, mFactory);
         ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
 
         Parameter::Common common = createParamCommon(
                 0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */,
                 kInputFrameCount /* iFrameCount */, kOutputFrameCount /* oFrameCount */);
-        IEffect::OpenEffectReturn ret;
-        ASSERT_NO_FATAL_FAILURE(open(mEffect, common, std::nullopt, &ret, EX_NONE));
+        ASSERT_NO_FATAL_FAILURE(open(mEffect, common, std::nullopt, &mOpenEffectReturn, EX_NONE));
         ASSERT_NE(nullptr, mEffect);
     }
-    void TearDown() override {
+
+    void TearDownEqualizer() {
         ASSERT_NO_FATAL_FAILURE(close(mEffect));
         ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
+        mOpenEffectReturn = IEffect::OpenEffectReturn{};
     }
 
-    static const long kInputFrameCount = 0x100, kOutputFrameCount = 0x100;
-    std::shared_ptr<IFactory> mFactory;
-    std::shared_ptr<IEffect> mEffect;
-    Descriptor mDescriptor;
-    int mPresetIndex;
-    std::vector<Equalizer::BandLevel> mBandLevel;
-
     void SetAndGetEqualizerParameters() {
         ASSERT_NE(nullptr, mEffect);
         for (auto& it : mTags) {
@@ -167,26 +163,45 @@
         mTags.push_back({Equalizer::preset, Equalizer::make<Equalizer::preset>(preset)});
     }
 
-    void addBandLevelsParam(std::vector<Equalizer::BandLevel>& bandLevels) {
+    void addBandLevelsParam(const std::vector<Equalizer::BandLevel>& bandLevels) {
         mTags.push_back(
                 {Equalizer::bandLevels, Equalizer::make<Equalizer::bandLevels>(bandLevels)});
     }
 
+    static const long kInputFrameCount = 0x100, kOutputFrameCount = 0x100;
+    const std::shared_ptr<IFactory> mFactory;
+    const int mPresetIndex;
+    const std::vector<Equalizer::BandLevel> mBandLevel;
+    std::shared_ptr<IEffect> mEffect;
+    IEffect::OpenEffectReturn mOpenEffectReturn;
+
   private:
     std::vector<std::pair<Equalizer::Tag, Equalizer>> mTags;
-
     void CleanUp() { mTags.clear(); }
 };
 
-TEST_P(EqualizerTest, SetAndGetParams) {
+class EqualizerParamTest : public ::testing::TestWithParam<EqualizerTestParam>,
+                           public EqualizerTestHelper {
+  public:
+    EqualizerParamTest()
+        : EqualizerTestHelper(std::get<PARAM_INSTANCE_NAME>(GetParam()),
+                              std::get<PARAM_PRESET>(GetParam()),
+                              std::get<PARAM_BAND_LEVEL>(GetParam())) {}
+
+    void SetUp() override { ASSERT_NO_FATAL_FAILURE(SetUpEqualizer()); }
+
+    void TearDown() override { ASSERT_NO_FATAL_FAILURE(TearDownEqualizer()); }
+};
+
+TEST_P(EqualizerParamTest, SetAndGetParams) {
     addBandLevelsParam(mBandLevel);
     addPresetParam(mPresetIndex);
-    EXPECT_NO_FATAL_FAILURE(SetAndGetEqualizerParameters());
+    ASSERT_NO_FATAL_FAILURE(SetAndGetEqualizerParameters());
 }
 
 std::vector<std::pair<std::shared_ptr<IFactory>, Descriptor>> kDescPair;
 INSTANTIATE_TEST_SUITE_P(
-        EqualizerTest, EqualizerTest,
+        EqualizerParamTest, EqualizerParamTest,
         ::testing::Combine(
                 testing::ValuesIn(kDescPair = EffectFactoryHelper::getAllEffectDescriptors(
                                           IFactory::descriptor, getEffectTypeUuidEqualizer())),
@@ -200,7 +215,7 @@
                                 [](std::set<std::vector<Equalizer::BandLevel>>& bandLevels) {
                                     return bandLevels;
                                 }))),
-        [](const testing::TestParamInfo<EqualizerTest::ParamType>& info) {
+        [](const testing::TestParamInfo<EqualizerParamTest::ParamType>& info) {
             auto descriptor = std::get<PARAM_INSTANCE_NAME>(info.param).second;
             std::string bandLevel =
                     ::android::internal::ToString(std::get<PARAM_BAND_LEVEL>(info.param));
@@ -211,7 +226,7 @@
                     name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
             return name;
         });
-GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EqualizerTest);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EqualizerParamTest);
 
 int main(int argc, char** argv) {
     ::testing::InitGoogleTest(&argc, argv);
diff --git a/audio/aidl/vts/VtsHalLoudnessEnhancerTargetTest.cpp b/audio/aidl/vts/VtsHalLoudnessEnhancerTargetTest.cpp
index 255d2f0..a263bff 100644
--- a/audio/aidl/vts/VtsHalLoudnessEnhancerTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalLoudnessEnhancerTargetTest.cpp
@@ -135,7 +135,7 @@
         std::tie(mFactory, mDescriptor) = std::get<PARAM_INSTANCE_NAME>(GetParam());
     }
 
-    void SetUp() override { SetUpLoudnessEnhancer(); }
+    void SetUp() override { ASSERT_NO_FATAL_FAILURE(SetUpLoudnessEnhancer()); }
     void TearDown() override { TearDownLoudnessEnhancer(); }
     int mParamGainMb = 0;
 };
@@ -166,7 +166,7 @@
 
     void SetUp() override {
         SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
-        SetUpLoudnessEnhancer();
+        ASSERT_NO_FATAL_FAILURE(SetUpLoudnessEnhancer());
 
         // Creating AidlMessageQueues
         mStatusMQ = std::make_unique<EffectHelper::StatusMQ>(mOpenEffectReturn.statusMQ);
@@ -261,13 +261,13 @@
 TEST_P(LoudnessEnhancerDataTest, IncreasingGains) {
     static const std::vector<int> kIncreasingGains = {50, 100};
 
-    assertSequentialGains(kIncreasingGains, true /*isIncreasing*/);
+    ASSERT_NO_FATAL_FAILURE(assertSequentialGains(kIncreasingGains, true /*isIncreasing*/));
 }
 
 TEST_P(LoudnessEnhancerDataTest, DecreasingGains) {
     static const std::vector<int> kDecreasingGains = {-50, -100};
 
-    assertSequentialGains(kDecreasingGains, false /*isIncreasing*/);
+    ASSERT_NO_FATAL_FAILURE(assertSequentialGains(kDecreasingGains, false /*isIncreasing*/));
 }
 
 TEST_P(LoudnessEnhancerDataTest, MinimumGain) {
diff --git a/audio/aidl/vts/VtsHalNSTargetTest.cpp b/audio/aidl/vts/VtsHalNSTargetTest.cpp
index c5a9bad..0618048 100644
--- a/audio/aidl/vts/VtsHalNSTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalNSTargetTest.cpp
@@ -141,12 +141,12 @@
 
 TEST_P(NSParamTest, SetAndGetLevel) {
     addLevelParam(mLevel);
-    SetAndGetParameters();
+    ASSERT_NO_FATAL_FAILURE(SetAndGetParameters());
 }
 
 TEST_P(NSParamTest, SetAndGetType) {
     addLevelParam(mLevel);
-    SetAndGetParameters();
+    ASSERT_NO_FATAL_FAILURE(SetAndGetParameters());
 }
 
 INSTANTIATE_TEST_SUITE_P(
diff --git a/audio/aidl/vts/VtsHalPresetReverbTargetTest.cpp b/audio/aidl/vts/VtsHalPresetReverbTargetTest.cpp
index f127c81..3fbda96 100644
--- a/audio/aidl/vts/VtsHalPresetReverbTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalPresetReverbTargetTest.cpp
@@ -187,13 +187,13 @@
     std::vector<PresetReverb::Presets> roomPresets = {PresetReverb::Presets::LARGEROOM,
                                                       PresetReverb::Presets::MEDIUMROOM,
                                                       PresetReverb::Presets::SMALLROOM};
-    validateIncreasingEnergy(roomPresets);
+    ASSERT_NO_FATAL_FAILURE(validateIncreasingEnergy(roomPresets));
 }
 
 TEST_P(PresetReverbProcessTest, DecreasingHallSize) {
     std::vector<PresetReverb::Presets> hallPresets = {PresetReverb::Presets::LARGEHALL,
                                                       PresetReverb::Presets::MEDIUMHALL};
-    validateIncreasingEnergy(hallPresets);
+    ASSERT_NO_FATAL_FAILURE(validateIncreasingEnergy(hallPresets));
 }
 
 TEST_P(PresetReverbProcessTest, PresetPlate) {
diff --git a/audio/aidl/vts/VtsHalVisualizerTargetTest.cpp b/audio/aidl/vts/VtsHalVisualizerTargetTest.cpp
index f019e2a..586ed67 100644
--- a/audio/aidl/vts/VtsHalVisualizerTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalVisualizerTargetTest.cpp
@@ -183,7 +183,7 @@
         generateInputBuffer(mInputBuffer, 0, true, mChannelCount, kMaxAudioSampleValue);
     }
 
-    void SetUp() override { SetUpVisualizer(); }
+    void SetUp() override { ASSERT_NO_FATAL_FAILURE(SetUpVisualizer()); }
 
     void TearDown() override { TearDownVisualizer(); }
 
@@ -252,7 +252,7 @@
                                std::get<PARAM_SCALING_MODE>(GetParam()),
                                std::get<PARAM_MEASUREMENT_MODE>(GetParam())) {}
 
-    void SetUp() override { SetUpVisualizer(); }
+    void SetUp() override { ASSERT_NO_FATAL_FAILURE(SetUpVisualizer()); }
 
     void TearDown() override { TearDownVisualizer(); }
 };
diff --git a/compatibility_matrices/compatibility_matrix.202504.xml b/compatibility_matrices/compatibility_matrix.202504.xml
index 8d5a50a..85702e2 100644
--- a/compatibility_matrices/compatibility_matrix.202504.xml
+++ b/compatibility_matrices/compatibility_matrix.202504.xml
@@ -523,6 +523,14 @@
             <instance>default</instance>
         </interface>
     </hal>
+    <hal format="aidl" exclusive-to="virtual-machine">
+        <name>android.hardware.security.see.storage</name>
+        <version>1</version>
+        <interface>
+            <name>ISecureStorage</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
     <hal format="aidl" updatable-via-apex="true">
         <name>android.hardware.security.secureclock</name>
         <version>1</version>
diff --git a/compatibility_matrices/compatibility_matrix.202604.xml b/compatibility_matrices/compatibility_matrix.202604.xml
index 793b166..46b04c9 100644
--- a/compatibility_matrices/compatibility_matrix.202604.xml
+++ b/compatibility_matrices/compatibility_matrix.202604.xml
@@ -523,6 +523,14 @@
             <instance>default</instance>
         </interface>
     </hal>
+    <hal format="aidl" exclusive-to="virtual-machine">
+        <name>android.hardware.security.see.storage</name>
+        <version>1</version>
+        <interface>
+            <name>ISecureStorage</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
     <hal format="aidl" updatable-via-apex="true">
         <name>android.hardware.security.secureclock</name>
         <version>1</version>
diff --git a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp
index 4f2ed2f..7810213 100644
--- a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp
+++ b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp
@@ -58,12 +58,6 @@
         for (const auto& display : mAllDisplays) {
             // explicitly disable vsync
             EXPECT_TRUE(mComposerClient->setVsync(display.getDisplayId(), /*enable*/ false).isOk());
-
-            DisplayProperties& displayProperties = mDisplayProperties.at(display.getDisplayId());
-            if (ReadbackHelper::readbackSupported(displayProperties.pixelFormat,
-                                                  displayProperties.dataspace)) {
-                mDisplaysWithReadbackBuffers.push_back(&display);
-            }
         }
 
         mComposerClient->setVsyncAllowed(/*isAllowed*/ false);
@@ -150,12 +144,35 @@
             DisplayProperties displayProperties(displayId, testColorModes,
                                                 std::move(testRenderEngine),
                                                 std::move(clientCompositionDisplaySettings),
-                                                std::move(readBackBufferAttributes));
+                                                std::move(readBackBufferAttributes.format));
 
             mDisplayProperties.emplace(displayId, std::move(displayProperties));
         }
     }
 
+    // Get the dataspace and check if readback is supported given the default pixel format and the
+    // current dataspace. Dataspace can get updated after calls to
+    // ComposerClientWrapper::setColorMode so it's essential to get the latest dataspace.
+    std::pair<common::Dataspace, bool> GetDataspaceAndIfReadBackSupported(int64_t displayId) {
+        auto [status, readBackBufferAttributes] =
+                mComposerClient->getReadbackBufferAttributes(displayId);
+        if (status.isOk()) {
+            auto dataspace = readBackBufferAttributes.dataspace;
+
+            // We are making an assumption that Pixel Format never changes, so assert for this
+            // assumption. If this is not the case on any display, then we should stop caching it.
+            // The cached format is used in initializing TestRenderEngine.
+            assertPixelFormatConsistency(displayId, readBackBufferAttributes.format);
+
+            return std::make_pair(std::move(dataspace),
+                                  ReadbackHelper::readbackSupported(
+                                          mDisplayProperties.at(displayId).pixelFormat, dataspace));
+        }
+        EXPECT_NO_FATAL_FAILURE(
+                assertServiceSpecificError(status, IComposerClient::EX_UNSUPPORTED));
+        return {common::Dataspace::UNKNOWN, false};
+    }
+
     int64_t getInvalidDisplayId() const { return mComposerClient->getInvalidDisplayId(); }
 
     void assertServiceSpecificError(const ScopedAStatus& status, int32_t serviceSpecificError) {
@@ -163,6 +180,10 @@
         ASSERT_EQ(status.getServiceSpecificError(), serviceSpecificError);
     }
 
+    void assertPixelFormatConsistency(int64_t displayId, common::PixelFormat currentPixelFormat) {
+        ASSERT_EQ(mDisplayProperties.at(displayId).pixelFormat, currentPixelFormat);
+    }
+
     std::pair<bool, ::android::sp<::android::GraphicBuffer>> allocateBuffer(
             const DisplayWrapper& display, uint32_t usage) {
         const auto width = static_cast<uint32_t>(display.getDisplayWidth());
@@ -201,10 +222,9 @@
         DisplayProperties(int64_t displayId, std::vector<ColorMode> testColorModes,
                           std::unique_ptr<TestRenderEngine> testRenderEngine,
                           ::android::renderengine::DisplaySettings clientCompositionDisplaySettings,
-                          ReadbackBufferAttributes readBackBufferAttributes)
+                          common::PixelFormat pixelFormat)
             : testColorModes(testColorModes),
-              pixelFormat(readBackBufferAttributes.format),
-              dataspace(readBackBufferAttributes.dataspace),
+              pixelFormat(pixelFormat),
               testRenderEngine(std::move(testRenderEngine)),
               clientCompositionDisplaySettings(std::move(clientCompositionDisplaySettings)),
               writer(displayId),
@@ -212,7 +232,6 @@
 
         std::vector<ColorMode> testColorModes = {};
         common::PixelFormat pixelFormat = common::PixelFormat::UNSPECIFIED;
-        common::Dataspace dataspace = common::Dataspace::UNKNOWN;
         std::unique_ptr<TestRenderEngine> testRenderEngine = nullptr;
         ::android::renderengine::DisplaySettings clientCompositionDisplaySettings = {};
         ComposerClientWriter writer;
@@ -221,7 +240,6 @@
 
     std::shared_ptr<ComposerClientWrapper> mComposerClient;
     std::vector<DisplayWrapper> mAllDisplays;
-    std::vector<const DisplayWrapper*> mDisplaysWithReadbackBuffers;
     std::unordered_map<int64_t, DisplayProperties> mDisplayProperties;
 
     static constexpr uint32_t kClientTargetSlotCount = 64;
@@ -234,19 +252,25 @@
 };
 
 TEST_P(GraphicsCompositionTest, SingleSolidColorLayer) {
-    for (const DisplayWrapper* display : mDisplaysWithReadbackBuffers) {
-        auto& testColorModes = mDisplayProperties.at(display->getDisplayId()).testColorModes;
+    for (const DisplayWrapper display : mAllDisplays) {
+        auto& testColorModes = mDisplayProperties.at(display.getDisplayId()).testColorModes;
         for (ColorMode mode : testColorModes) {
-            EXPECT_TRUE(mComposerClient
-                                ->setColorMode(display->getDisplayId(), mode,
-                                               RenderIntent::COLORIMETRIC)
-                                .isOk());
+            EXPECT_TRUE(
+                    mComposerClient
+                            ->setColorMode(display.getDisplayId(), mode, RenderIntent::COLORIMETRIC)
+                            .isOk());
+
+            auto [dataspace, readbackSupported] =
+                    GetDataspaceAndIfReadBackSupported(display.getDisplayId());
+            if (!readbackSupported) {
+                continue;
+            }
 
             auto layer = std::make_shared<TestColorLayer>(
-                    mComposerClient, display->getDisplayId(),
-                    mDisplayProperties.at(display->getDisplayId()).writer);
+                    mComposerClient, display.getDisplayId(),
+                    mDisplayProperties.at(display.getDisplayId()).writer);
             common::Rect coloredSquare(
-                    {0, 0, display->getDisplayWidth(), display->getDisplayHeight()});
+                    {0, 0, display.getDisplayWidth(), display.getDisplayHeight()});
             layer->setColor(BLUE);
             layer->setDisplayFrame(coloredSquare);
             layer->setZOrder(10);
@@ -255,40 +279,38 @@
 
             // expected color for each pixel
             std::vector<Color> expectedColors(
-                    static_cast<size_t>(display->getDisplayWidth() * display->getDisplayHeight()));
-            ReadbackHelper::fillColorsArea(expectedColors, display->getDisplayWidth(),
-                                           coloredSquare, BLUE);
+                    static_cast<size_t>(display.getDisplayWidth() * display.getDisplayHeight()));
+            ReadbackHelper::fillColorsArea(expectedColors, display.getDisplayWidth(), coloredSquare,
+                                           BLUE);
 
-            ReadbackBuffer readbackBuffer(
-                    display->getDisplayId(), mComposerClient, display->getDisplayWidth(),
-                    display->getDisplayHeight(),
-                    mDisplayProperties.at(display->getDisplayId()).pixelFormat,
-                    mDisplayProperties.at(display->getDisplayId()).dataspace);
+            ReadbackBuffer readbackBuffer(display.getDisplayId(), mComposerClient,
+                                          display.getDisplayWidth(), display.getDisplayHeight(),
+                                          mDisplayProperties.at(display.getDisplayId()).pixelFormat,
+                                          dataspace);
             ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
 
-            writeLayers(layers, display->getDisplayId());
-            ASSERT_TRUE(mDisplayProperties.at(display->getDisplayId()).reader.takeErrors().empty());
-            mDisplayProperties.at(display->getDisplayId())
-                    .writer.validateDisplay(display->getDisplayId(),
+            writeLayers(layers, display.getDisplayId());
+            ASSERT_TRUE(mDisplayProperties.at(display.getDisplayId()).reader.takeErrors().empty());
+            mDisplayProperties.at(display.getDisplayId())
+                    .writer.validateDisplay(display.getDisplayId(),
                                             ComposerClientWriter::kNoTimestamp,
                                             ComposerClientWrapper::kNoFrameIntervalNs);
-            execute(display->getDisplayId());
+            execute(display.getDisplayId());
             // if hwc cannot handle and asks for composition change, just skip the test on this
             // display->
-            if (!mDisplayProperties.at(display->getDisplayId())
-                         .reader.takeChangedCompositionTypes(display->getDisplayId())
+            if (!mDisplayProperties.at(display.getDisplayId())
+                         .reader.takeChangedCompositionTypes(display.getDisplayId())
                          .empty()) {
                 continue;
             }
-            ASSERT_TRUE(mDisplayProperties.at(display->getDisplayId()).reader.takeErrors().empty());
-            mDisplayProperties.at(display->getDisplayId())
-                    .writer.presentDisplay(display->getDisplayId());
-            execute(display->getDisplayId());
-            ASSERT_TRUE(mDisplayProperties.at(display->getDisplayId()).reader.takeErrors().empty());
+            ASSERT_TRUE(mDisplayProperties.at(display.getDisplayId()).reader.takeErrors().empty());
+            mDisplayProperties.at(display.getDisplayId())
+                    .writer.presentDisplay(display.getDisplayId());
+            execute(display.getDisplayId());
+            ASSERT_TRUE(mDisplayProperties.at(display.getDisplayId()).reader.takeErrors().empty());
 
             ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
-            auto& testRenderEngine =
-                    mDisplayProperties.at(display->getDisplayId()).testRenderEngine;
+            auto& testRenderEngine = mDisplayProperties.at(display.getDisplayId()).testRenderEngine;
             testRenderEngine->setRenderLayers(layers);
             ASSERT_NO_FATAL_FAILURE(testRenderEngine->drawLayers());
             ASSERT_NO_FATAL_FAILURE(testRenderEngine->checkColorBuffer(expectedColors));
@@ -297,71 +319,74 @@
 }
 
 TEST_P(GraphicsCompositionTest, SetLayerBuffer) {
-    for (const DisplayWrapper* display : mDisplaysWithReadbackBuffers) {
-        auto& testColorModes = mDisplayProperties.at(display->getDisplayId()).testColorModes;
+    for (const DisplayWrapper display : mAllDisplays) {
+        auto& testColorModes = mDisplayProperties.at(display.getDisplayId()).testColorModes;
         for (ColorMode mode : testColorModes) {
-            EXPECT_TRUE(mComposerClient
-                                ->setColorMode(display->getDisplayId(), mode,
-                                               RenderIntent::COLORIMETRIC)
-                                .isOk());
+            EXPECT_TRUE(
+                    mComposerClient
+                            ->setColorMode(display.getDisplayId(), mode, RenderIntent::COLORIMETRIC)
+                            .isOk());
 
-            ReadbackBuffer readbackBuffer(
-                    display->getDisplayId(), mComposerClient, display->getDisplayWidth(),
-                    display->getDisplayHeight(),
-                    mDisplayProperties.at(display->getDisplayId()).pixelFormat,
-                    mDisplayProperties.at(display->getDisplayId()).dataspace);
+            auto [dataspace, readbackSupported] =
+                    GetDataspaceAndIfReadBackSupported(display.getDisplayId());
+            if (!readbackSupported) {
+                continue;
+            }
+
+            ReadbackBuffer readbackBuffer(display.getDisplayId(), mComposerClient,
+                                          display.getDisplayWidth(), display.getDisplayHeight(),
+                                          mDisplayProperties.at(display.getDisplayId()).pixelFormat,
+                                          dataspace);
             ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
             std::vector<Color> expectedColors(
-                    static_cast<size_t>(display->getDisplayWidth() * display->getDisplayHeight()));
+                    static_cast<size_t>(display.getDisplayWidth() * display.getDisplayHeight()));
             ReadbackHelper::fillColorsArea(
-                    expectedColors, display->getDisplayWidth(),
-                    {0, 0, display->getDisplayWidth(), display->getDisplayHeight() / 4}, RED);
+                    expectedColors, display.getDisplayWidth(),
+                    {0, 0, display.getDisplayWidth(), display.getDisplayHeight() / 4}, RED);
             ReadbackHelper::fillColorsArea(
-                    expectedColors, display->getDisplayWidth(),
-                    {0, display->getDisplayHeight() / 4, display->getDisplayWidth(),
-                     display->getDisplayHeight() / 2},
+                    expectedColors, display.getDisplayWidth(),
+                    {0, display.getDisplayHeight() / 4, display.getDisplayWidth(),
+                     display.getDisplayHeight() / 2},
                     GREEN);
-            ReadbackHelper::fillColorsArea(
-                    expectedColors, display->getDisplayWidth(),
-                    {0, display->getDisplayHeight() / 2, display->getDisplayWidth(),
-                     display->getDisplayHeight()},
-                    BLUE);
+            ReadbackHelper::fillColorsArea(expectedColors, display.getDisplayWidth(),
+                                           {0, display.getDisplayHeight() / 2,
+                                            display.getDisplayWidth(), display.getDisplayHeight()},
+                                           BLUE);
 
             auto layer = std::make_shared<TestBufferLayer>(
                     mComposerClient,
-                    *mDisplayProperties.at(display->getDisplayId()).testRenderEngine,
-                    display->getDisplayId(), display->getDisplayWidth(),
-                    display->getDisplayHeight(), common::PixelFormat::RGBA_8888,
-                    mDisplayProperties.at(display->getDisplayId()).writer);
-            layer->setDisplayFrame({0, 0, display->getDisplayWidth(), display->getDisplayHeight()});
+                    *mDisplayProperties.at(display.getDisplayId()).testRenderEngine,
+                    display.getDisplayId(), display.getDisplayWidth(), display.getDisplayHeight(),
+                    common::PixelFormat::RGBA_8888,
+                    mDisplayProperties.at(display.getDisplayId()).writer);
+            layer->setDisplayFrame({0, 0, display.getDisplayWidth(), display.getDisplayHeight()});
             layer->setZOrder(10);
             layer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode));
             ASSERT_NO_FATAL_FAILURE(layer->setBuffer(expectedColors));
 
             std::vector<std::shared_ptr<TestLayer>> layers = {layer};
 
-            writeLayers(layers, display->getDisplayId());
-            ASSERT_TRUE(mDisplayProperties.at(display->getDisplayId()).reader.takeErrors().empty());
-            mDisplayProperties.at(display->getDisplayId())
-                    .writer.validateDisplay(display->getDisplayId(),
+            writeLayers(layers, display.getDisplayId());
+            ASSERT_TRUE(mDisplayProperties.at(display.getDisplayId()).reader.takeErrors().empty());
+            mDisplayProperties.at(display.getDisplayId())
+                    .writer.validateDisplay(display.getDisplayId(),
                                             ComposerClientWriter::kNoTimestamp,
                                             ComposerClientWrapper::kNoFrameIntervalNs);
-            execute(display->getDisplayId());
+            execute(display.getDisplayId());
 
-            if (!mDisplayProperties.at(display->getDisplayId())
-                         .reader.takeChangedCompositionTypes(display->getDisplayId())
+            if (!mDisplayProperties.at(display.getDisplayId())
+                         .reader.takeChangedCompositionTypes(display.getDisplayId())
                          .empty()) {
                 continue;
             }
-            ASSERT_TRUE(mDisplayProperties.at(display->getDisplayId()).reader.takeErrors().empty());
-            mDisplayProperties.at(display->getDisplayId())
-                    .writer.presentDisplay(display->getDisplayId());
-            execute(display->getDisplayId());
-            ASSERT_TRUE(mDisplayProperties.at(display->getDisplayId()).reader.takeErrors().empty());
+            ASSERT_TRUE(mDisplayProperties.at(display.getDisplayId()).reader.takeErrors().empty());
+            mDisplayProperties.at(display.getDisplayId())
+                    .writer.presentDisplay(display.getDisplayId());
+            execute(display.getDisplayId());
+            ASSERT_TRUE(mDisplayProperties.at(display.getDisplayId()).reader.takeErrors().empty());
 
             ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
-            auto& testRenderEngine =
-                    mDisplayProperties.at(display->getDisplayId()).testRenderEngine;
+            auto& testRenderEngine = mDisplayProperties.at(display.getDisplayId()).testRenderEngine;
             testRenderEngine->setRenderLayers(layers);
             ASSERT_NO_FATAL_FAILURE(testRenderEngine->drawLayers());
             ASSERT_NO_FATAL_FAILURE(testRenderEngine->checkColorBuffer(expectedColors));
@@ -370,64 +395,69 @@
 }
 
 TEST_P(GraphicsCompositionTest, SetLayerBufferNoEffect) {
-    for (const DisplayWrapper* display : mDisplaysWithReadbackBuffers) {
-        auto& testColorModes = mDisplayProperties.at(display->getDisplayId()).testColorModes;
+    for (const DisplayWrapper display : mAllDisplays) {
+        auto& testColorModes = mDisplayProperties.at(display.getDisplayId()).testColorModes;
         for (ColorMode mode : testColorModes) {
-            EXPECT_TRUE(mComposerClient
-                                ->setColorMode(display->getDisplayId(), mode,
-                                               RenderIntent::COLORIMETRIC)
-                                .isOk());
+            EXPECT_TRUE(
+                    mComposerClient
+                            ->setColorMode(display.getDisplayId(), mode, RenderIntent::COLORIMETRIC)
+                            .isOk());
 
-            auto& writer = mDisplayProperties.at(display->getDisplayId()).writer;
-            auto layer = std::make_shared<TestColorLayer>(mComposerClient, display->getDisplayId(),
+            auto [dataspace, readbackSupported] =
+                    GetDataspaceAndIfReadBackSupported(display.getDisplayId());
+            if (!readbackSupported) {
+                continue;
+            }
+
+            auto& writer = mDisplayProperties.at(display.getDisplayId()).writer;
+            auto layer = std::make_shared<TestColorLayer>(mComposerClient, display.getDisplayId(),
                                                           writer);
             common::Rect coloredSquare(
-                    {0, 0, display->getDisplayWidth(), display->getDisplayHeight()});
+                    {0, 0, display.getDisplayWidth(), display.getDisplayHeight()});
             layer->setColor(BLUE);
             layer->setDisplayFrame(coloredSquare);
             layer->setZOrder(10);
-            layer->write(mDisplayProperties.at(display->getDisplayId()).writer);
+            layer->write(mDisplayProperties.at(display.getDisplayId()).writer);
 
             // This following buffer call should have no effect
             const auto usage = static_cast<uint32_t>(common::BufferUsage::CPU_WRITE_OFTEN) |
                                static_cast<uint32_t>(common::BufferUsage::CPU_READ_OFTEN);
-            const auto& [graphicBufferStatus, graphicBuffer] = allocateBuffer(*display, usage);
+            const auto& [graphicBufferStatus, graphicBuffer] = allocateBuffer(display, usage);
             ASSERT_TRUE(graphicBufferStatus);
             const auto& buffer = graphicBuffer->handle;
-            mDisplayProperties.at(display->getDisplayId())
-                    .writer.setLayerBuffer(display->getDisplayId(), layer->getLayer(), /*slot*/ 0,
+            mDisplayProperties.at(display.getDisplayId())
+                    .writer.setLayerBuffer(display.getDisplayId(), layer->getLayer(), /*slot*/ 0,
                                            buffer,
                                            /*acquireFence*/ -1);
 
             // expected color for each pixel
             std::vector<Color> expectedColors(
-                    static_cast<size_t>(display->getDisplayWidth() * display->getDisplayHeight()));
-            ReadbackHelper::fillColorsArea(expectedColors, display->getDisplayWidth(),
-                                           coloredSquare, BLUE);
+                    static_cast<size_t>(display.getDisplayWidth() * display.getDisplayHeight()));
+            ReadbackHelper::fillColorsArea(expectedColors, display.getDisplayWidth(), coloredSquare,
+                                           BLUE);
 
-            ReadbackBuffer readbackBuffer(
-                    display->getDisplayId(), mComposerClient, display->getDisplayWidth(),
-                    display->getDisplayHeight(),
-                    mDisplayProperties.at(display->getDisplayId()).pixelFormat,
-                    mDisplayProperties.at(display->getDisplayId()).dataspace);
+            ReadbackBuffer readbackBuffer(display.getDisplayId(), mComposerClient,
+                                          display.getDisplayWidth(), display.getDisplayHeight(),
+                                          mDisplayProperties.at(display.getDisplayId()).pixelFormat,
+                                          dataspace);
             ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
 
-            mDisplayProperties.at(display->getDisplayId())
-                    .writer.validateDisplay(display->getDisplayId(),
+            mDisplayProperties.at(display.getDisplayId())
+                    .writer.validateDisplay(display.getDisplayId(),
                                             ComposerClientWriter::kNoTimestamp,
                                             ComposerClientWrapper::kNoFrameIntervalNs);
-            execute(display->getDisplayId());
+            execute(display.getDisplayId());
 
-            if (!mDisplayProperties.at(display->getDisplayId())
-                         .reader.takeChangedCompositionTypes(display->getDisplayId())
+            if (!mDisplayProperties.at(display.getDisplayId())
+                         .reader.takeChangedCompositionTypes(display.getDisplayId())
                          .empty()) {
                 continue;
             }
-            ASSERT_TRUE(mDisplayProperties.at(display->getDisplayId()).reader.takeErrors().empty());
-            mDisplayProperties.at(display->getDisplayId())
-                    .writer.presentDisplay(display->getDisplayId());
-            execute(display->getDisplayId());
-            ASSERT_TRUE(mDisplayProperties.at(display->getDisplayId()).reader.takeErrors().empty());
+            ASSERT_TRUE(mDisplayProperties.at(display.getDisplayId()).reader.takeErrors().empty());
+            mDisplayProperties.at(display.getDisplayId())
+                    .writer.presentDisplay(display.getDisplayId());
+            execute(display.getDisplayId());
+            ASSERT_TRUE(mDisplayProperties.at(display.getDisplayId()).reader.takeErrors().empty());
 
             ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
         }
@@ -435,20 +465,31 @@
 }
 
 TEST_P(GraphicsCompositionTest, SetReadbackBuffer) {
-    for (const DisplayWrapper* display : mDisplaysWithReadbackBuffers) {
-        ReadbackBuffer readbackBuffer(display->getDisplayId(), mComposerClient,
-                                      display->getDisplayWidth(), display->getDisplayHeight(),
-                                      mDisplayProperties.at(display->getDisplayId()).pixelFormat,
-                                      mDisplayProperties.at(display->getDisplayId()).dataspace);
+    for (const DisplayWrapper display : mAllDisplays) {
+        auto [dataspace, readbackSupported] =
+                GetDataspaceAndIfReadBackSupported(display.getDisplayId());
+        if (!readbackSupported) {
+            continue;
+        }
+
+        ReadbackBuffer readbackBuffer(display.getDisplayId(), mComposerClient,
+                                      display.getDisplayWidth(), display.getDisplayHeight(),
+                                      mDisplayProperties.at(display.getDisplayId()).pixelFormat,
+                                      dataspace);
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
     }
 }
 
 TEST_P(GraphicsCompositionTest, SetReadbackBuffer_BadDisplay) {
-    for (const DisplayWrapper* display : mDisplaysWithReadbackBuffers) {
+    for (const DisplayWrapper display : mAllDisplays) {
+        auto [_, readbackSupported] = GetDataspaceAndIfReadBackSupported(display.getDisplayId());
+        if (!readbackSupported) {
+            continue;
+        }
+
         const auto usage = static_cast<uint32_t>(common::BufferUsage::CPU_WRITE_OFTEN) |
                            static_cast<uint32_t>(common::BufferUsage::CPU_READ_OFTEN);
-        const auto& [graphicBufferStatus, graphicBuffer] = allocateBuffer(*display, usage);
+        const auto& [graphicBufferStatus, graphicBuffer] = allocateBuffer(display, usage);
         ASSERT_TRUE(graphicBufferStatus);
         const auto& bufferHandle = graphicBuffer->handle;
         ::ndk::ScopedFileDescriptor fence = ::ndk::ScopedFileDescriptor(-1);
@@ -463,10 +504,15 @@
 }
 
 TEST_P(GraphicsCompositionTest, SetReadbackBuffer_BadParameter) {
-    for (const DisplayWrapper* display : mDisplaysWithReadbackBuffers) {
+    for (const DisplayWrapper display : mAllDisplays) {
+        auto [_, readbackSupported] = GetDataspaceAndIfReadBackSupported(display.getDisplayId());
+        if (!readbackSupported) {
+            continue;
+        }
+
         const native_handle_t bufferHandle{};
         ndk::ScopedFileDescriptor releaseFence = ndk::ScopedFileDescriptor(-1);
-        const auto status = mComposerClient->setReadbackBuffer(display->getDisplayId(),
+        const auto status = mComposerClient->setReadbackBuffer(display.getDisplayId(),
                                                                &bufferHandle, releaseFence);
 
         EXPECT_FALSE(status.isOk());
@@ -476,9 +522,13 @@
 }
 
 TEST_P(GraphicsCompositionTest, GetReadbackBufferFenceInactive) {
-    for (const DisplayWrapper* display : mDisplaysWithReadbackBuffers) {
+    for (const DisplayWrapper display : mAllDisplays) {
+        auto [_, readbackSupported] = GetDataspaceAndIfReadBackSupported(display.getDisplayId());
+        if (!readbackSupported) {
+            continue;
+        }
         const auto& [status, releaseFence] =
-                mComposerClient->getReadbackBufferFence(display->getDisplayId());
+                mComposerClient->getReadbackBufferFence(display.getDisplayId());
 
         EXPECT_FALSE(status.isOk());
         EXPECT_NO_FATAL_FAILURE(
@@ -488,64 +538,67 @@
 }
 
 TEST_P(GraphicsCompositionTest, ClientComposition) {
-    for (const DisplayWrapper* display : mDisplaysWithReadbackBuffers) {
+    for (const DisplayWrapper display : mAllDisplays) {
         EXPECT_TRUE(
                 mComposerClient
-                        ->setClientTargetSlotCount(display->getDisplayId(), kClientTargetSlotCount)
+                        ->setClientTargetSlotCount(display.getDisplayId(), kClientTargetSlotCount)
                         .isOk());
 
-        for (ColorMode mode : mDisplayProperties.at(display->getDisplayId()).testColorModes) {
-            EXPECT_TRUE(mComposerClient
-                                ->setColorMode(display->getDisplayId(), mode,
-                                               RenderIntent::COLORIMETRIC)
-                                .isOk());
+        for (ColorMode mode : mDisplayProperties.at(display.getDisplayId()).testColorModes) {
+            EXPECT_TRUE(
+                    mComposerClient
+                            ->setColorMode(display.getDisplayId(), mode, RenderIntent::COLORIMETRIC)
+                            .isOk());
+
+            auto [dataspace, readbackSupported] =
+                    GetDataspaceAndIfReadBackSupported(display.getDisplayId());
+            if (!readbackSupported) {
+                continue;
+            }
 
             std::vector<Color> expectedColors(
-                    static_cast<size_t>(display->getDisplayWidth() * display->getDisplayHeight()));
+                    static_cast<size_t>(display.getDisplayWidth() * display.getDisplayHeight()));
             ReadbackHelper::fillColorsArea(
-                    expectedColors, display->getDisplayWidth(),
-                    {0, 0, display->getDisplayWidth(), display->getDisplayHeight() / 4}, RED);
+                    expectedColors, display.getDisplayWidth(),
+                    {0, 0, display.getDisplayWidth(), display.getDisplayHeight() / 4}, RED);
             ReadbackHelper::fillColorsArea(
-                    expectedColors, display->getDisplayWidth(),
-                    {0, display->getDisplayHeight() / 4, display->getDisplayWidth(),
-                     display->getDisplayHeight() / 2},
+                    expectedColors, display.getDisplayWidth(),
+                    {0, display.getDisplayHeight() / 4, display.getDisplayWidth(),
+                     display.getDisplayHeight() / 2},
                     GREEN);
-            ReadbackHelper::fillColorsArea(
-                    expectedColors, display->getDisplayWidth(),
-                    {0, display->getDisplayHeight() / 2, display->getDisplayWidth(),
-                     display->getDisplayHeight()},
-                    BLUE);
+            ReadbackHelper::fillColorsArea(expectedColors, display.getDisplayWidth(),
+                                           {0, display.getDisplayHeight() / 2,
+                                            display.getDisplayWidth(), display.getDisplayHeight()},
+                                           BLUE);
 
             auto layer = std::make_shared<TestBufferLayer>(
                     mComposerClient,
-                    *mDisplayProperties.at(display->getDisplayId()).testRenderEngine,
-                    display->getDisplayId(), display->getDisplayWidth(),
-                    display->getDisplayHeight(), PixelFormat::RGBA_8888,
-                    mDisplayProperties.at(display->getDisplayId()).writer);
-            layer->setDisplayFrame({0, 0, display->getDisplayWidth(), display->getDisplayHeight()});
+                    *mDisplayProperties.at(display.getDisplayId()).testRenderEngine,
+                    display.getDisplayId(), display.getDisplayWidth(), display.getDisplayHeight(),
+                    PixelFormat::RGBA_8888, mDisplayProperties.at(display.getDisplayId()).writer);
+            layer->setDisplayFrame({0, 0, display.getDisplayWidth(), display.getDisplayHeight()});
             layer->setZOrder(10);
             layer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode));
 
             std::vector<std::shared_ptr<TestLayer>> layers = {layer};
 
-            ReadbackBuffer readbackBuffer(
-                    display->getDisplayId(), mComposerClient, display->getDisplayWidth(),
-                    display->getDisplayHeight(),
-                    mDisplayProperties.at(display->getDisplayId()).pixelFormat,
-                    mDisplayProperties.at(display->getDisplayId()).dataspace);
+            ReadbackBuffer readbackBuffer(display.getDisplayId(), mComposerClient,
+                                          display.getDisplayWidth(), display.getDisplayHeight(),
+                                          mDisplayProperties.at(display.getDisplayId()).pixelFormat,
+                                          dataspace);
             ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
 
-            writeLayers(layers, display->getDisplayId());
-            ASSERT_TRUE(mDisplayProperties.at(display->getDisplayId()).reader.takeErrors().empty());
-            mDisplayProperties.at(display->getDisplayId())
-                    .writer.validateDisplay(display->getDisplayId(),
+            writeLayers(layers, display.getDisplayId());
+            ASSERT_TRUE(mDisplayProperties.at(display.getDisplayId()).reader.takeErrors().empty());
+            mDisplayProperties.at(display.getDisplayId())
+                    .writer.validateDisplay(display.getDisplayId(),
                                             ComposerClientWriter::kNoTimestamp,
                                             ComposerClientWrapper::kNoFrameIntervalNs);
-            execute(display->getDisplayId());
+            execute(display.getDisplayId());
 
             auto changedCompositionTypes =
-                    mDisplayProperties.at(display->getDisplayId())
-                            .reader.takeChangedCompositionTypes(display->getDisplayId());
+                    mDisplayProperties.at(display.getDisplayId())
+                            .reader.takeChangedCompositionTypes(display.getDisplayId());
             if (!changedCompositionTypes.empty()) {
                 ASSERT_EQ(1, changedCompositionTypes.size());
                 ASSERT_EQ(Composition::CLIENT, changedCompositionTypes[0].composition);
@@ -556,11 +609,11 @@
                         static_cast<uint32_t>(common::BufferUsage::CPU_WRITE_OFTEN) |
                         static_cast<uint32_t>(common::BufferUsage::COMPOSER_CLIENT_TARGET));
                 Dataspace clientDataspace = ReadbackHelper::getDataspaceForColorMode(mode);
-                common::Rect damage{0, 0, display->getDisplayWidth(), display->getDisplayHeight()};
+                common::Rect damage{0, 0, display.getDisplayWidth(), display.getDisplayHeight()};
 
                 // create client target buffer
                 const auto& [graphicBufferStatus, graphicBuffer] =
-                        allocateBuffer(*display, clientUsage);
+                        allocateBuffer(display, clientUsage);
                 ASSERT_TRUE(graphicBufferStatus);
                 const auto& buffer = graphicBuffer->handle;
                 void* clientBufData;
@@ -576,29 +629,28 @@
                 int32_t clientFence;
                 const auto unlockStatus = graphicBuffer->unlockAsync(&clientFence);
                 ASSERT_EQ(::android::OK, unlockStatus);
-                mDisplayProperties.at(display->getDisplayId())
-                        .writer.setClientTarget(display->getDisplayId(), /*slot*/ 0, buffer,
+                mDisplayProperties.at(display.getDisplayId())
+                        .writer.setClientTarget(display.getDisplayId(), /*slot*/ 0, buffer,
                                                 clientFence, clientDataspace,
                                                 std::vector<common::Rect>(1, damage), 1.f);
-                layer->setToClientComposition(
-                        mDisplayProperties.at(display->getDisplayId()).writer);
-                mDisplayProperties.at(display->getDisplayId())
-                        .writer.validateDisplay(display->getDisplayId(),
+                layer->setToClientComposition(mDisplayProperties.at(display.getDisplayId()).writer);
+                mDisplayProperties.at(display.getDisplayId())
+                        .writer.validateDisplay(display.getDisplayId(),
                                                 ComposerClientWriter::kNoTimestamp,
                                                 ComposerClientWrapper::kNoFrameIntervalNs);
-                execute(display->getDisplayId());
+                execute(display.getDisplayId());
                 changedCompositionTypes =
-                        mDisplayProperties.at(display->getDisplayId())
-                                .reader.takeChangedCompositionTypes(display->getDisplayId());
+                        mDisplayProperties.at(display.getDisplayId())
+                                .reader.takeChangedCompositionTypes(display.getDisplayId());
                 ASSERT_TRUE(changedCompositionTypes.empty());
             }
-            ASSERT_TRUE(mDisplayProperties.at(display->getDisplayId()).reader.takeErrors().empty());
+            ASSERT_TRUE(mDisplayProperties.at(display.getDisplayId()).reader.takeErrors().empty());
 
-            mDisplayProperties.at(display->getDisplayId())
-                    .writer.presentDisplay(display->getDisplayId());
-            execute(display->getDisplayId());
+            mDisplayProperties.at(display.getDisplayId())
+                    .writer.presentDisplay(display.getDisplayId());
+            execute(display.getDisplayId());
 
-            ASSERT_TRUE(mDisplayProperties.at(display->getDisplayId()).reader.takeErrors().empty());
+            ASSERT_TRUE(mDisplayProperties.at(display.getDisplayId()).reader.takeErrors().empty());
 
             ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
         }
@@ -634,12 +686,12 @@
         GTEST_SKIP();
     }
 
-    for (const DisplayWrapper* display : mDisplaysWithReadbackBuffers) {
+    for (const DisplayWrapper display : mAllDisplays) {
         ASSERT_TRUE(
                 mComposerClient
-                        ->setClientTargetSlotCount(display->getDisplayId(), kClientTargetSlotCount)
+                        ->setClientTargetSlotCount(display.getDisplayId(), kClientTargetSlotCount)
                         .isOk());
-        auto& testColorModes = mDisplayProperties.at(display->getDisplayId()).testColorModes;
+        auto& testColorModes = mDisplayProperties.at(display.getDisplayId()).testColorModes;
 
         for (const auto& lutProperties : *properties.lutProperties) {
             if (!lutProperties) {
@@ -650,25 +702,31 @@
             for (const auto& key : l.samplingKeys) {
                 for (ColorMode mode : testColorModes) {
                     EXPECT_TRUE(mComposerClient
-                                        ->setColorMode(display->getDisplayId(), mode,
+                                        ->setColorMode(display.getDisplayId(), mode,
                                                        RenderIntent::COLORIMETRIC)
                                         .isOk());
 
+                    auto [dataspace, readbackSupported] =
+                            GetDataspaceAndIfReadBackSupported(display.getDisplayId());
+                    if (!readbackSupported) {
+                        continue;
+                    }
+
                     common::Rect coloredSquare(
-                            {0, 0, display->getDisplayWidth(), display->getDisplayHeight()});
+                            {0, 0, display.getDisplayWidth(), display.getDisplayHeight()});
 
                     // expected color for each pixel
                     std::vector<Color> expectedColors(static_cast<size_t>(
-                            display->getDisplayWidth() * display->getDisplayHeight()));
-                    ReadbackHelper::fillColorsArea(expectedColors, display->getDisplayWidth(),
+                            display.getDisplayWidth() * display.getDisplayHeight()));
+                    ReadbackHelper::fillColorsArea(expectedColors, display.getDisplayWidth(),
                                                    coloredSquare, WHITE);
 
                     auto layer = std::make_shared<TestBufferLayer>(
                             mComposerClient,
-                            *mDisplayProperties.at(display->getDisplayId()).testRenderEngine,
-                            display->getDisplayId(), display->getDisplayWidth(),
-                            display->getDisplayHeight(), PixelFormat::RGBA_8888,
-                            mDisplayProperties.at(display->getDisplayId()).writer);
+                            *mDisplayProperties.at(display.getDisplayId()).testRenderEngine,
+                            display.getDisplayId(), display.getDisplayWidth(),
+                            display.getDisplayHeight(), PixelFormat::RGBA_8888,
+                            mDisplayProperties.at(display.getDisplayId()).writer);
                     layer->setDisplayFrame(coloredSquare);
                     layer->setZOrder(10);
                     layer->setDataspace(Dataspace::SRGB);
@@ -682,46 +740,45 @@
                     std::vector<std::shared_ptr<TestLayer>> layers = {layer};
 
                     ReadbackBuffer readbackBuffer(
-                            display->getDisplayId(), mComposerClient, display->getDisplayWidth(),
-                            display->getDisplayHeight(),
-                            mDisplayProperties.at(display->getDisplayId()).pixelFormat,
-                            mDisplayProperties.at(display->getDisplayId()).dataspace);
+                            display.getDisplayId(), mComposerClient, display.getDisplayWidth(),
+                            display.getDisplayHeight(),
+                            mDisplayProperties.at(display.getDisplayId()).pixelFormat, dataspace);
                     ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
 
-                    writeLayers(layers, display->getDisplayId());
-                    ASSERT_TRUE(mDisplayProperties.at(display->getDisplayId())
+                    writeLayers(layers, display.getDisplayId());
+                    ASSERT_TRUE(mDisplayProperties.at(display.getDisplayId())
                                         .reader.takeErrors()
                                         .empty());
-                    mDisplayProperties.at(display->getDisplayId())
-                            .writer.validateDisplay(display->getDisplayId(),
+                    mDisplayProperties.at(display.getDisplayId())
+                            .writer.validateDisplay(display.getDisplayId(),
                                                     ComposerClientWriter::kNoTimestamp,
                                                     ComposerClientWrapper::kNoFrameIntervalNs);
-                    execute(display->getDisplayId());
-                    if (!mDisplayProperties.at(display->getDisplayId())
-                                 .reader.takeChangedCompositionTypes(display->getDisplayId())
+                    execute(display.getDisplayId());
+                    if (!mDisplayProperties.at(display.getDisplayId())
+                                 .reader.takeChangedCompositionTypes(display.getDisplayId())
                                  .empty()) {
                         continue;
                     }
 
                     auto changedCompositionTypes =
-                            mDisplayProperties.at(display->getDisplayId())
-                                    .reader.takeChangedCompositionTypes(display->getDisplayId());
+                            mDisplayProperties.at(display.getDisplayId())
+                                    .reader.takeChangedCompositionTypes(display.getDisplayId());
                     ASSERT_TRUE(changedCompositionTypes.empty());
 
-                    mDisplayProperties.at(display->getDisplayId())
-                            .writer.presentDisplay(display->getDisplayId());
-                    execute(display->getDisplayId());
-                    ASSERT_TRUE(mDisplayProperties.at(display->getDisplayId())
+                    mDisplayProperties.at(display.getDisplayId())
+                            .writer.presentDisplay(display.getDisplayId());
+                    execute(display.getDisplayId());
+                    ASSERT_TRUE(mDisplayProperties.at(display.getDisplayId())
                                         .reader.takeErrors()
                                         .empty());
 
                     ReadbackHelper::fillColorsArea(
-                            expectedColors, display->getDisplayWidth(), coloredSquare,
+                            expectedColors, display.getDisplayWidth(), coloredSquare,
                             {188.f / 255.f, 188.f / 255.f, 188.f / 255.f, 1.0f});
 
                     ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
                     auto& testRenderEngine =
-                            mDisplayProperties.at(display->getDisplayId()).testRenderEngine;
+                            mDisplayProperties.at(display.getDisplayId()).testRenderEngine;
                     testRenderEngine->setRenderLayers(layers);
                     ASSERT_NO_FATAL_FAILURE(testRenderEngine->drawLayers());
                     ASSERT_NO_FATAL_FAILURE(testRenderEngine->checkColorBuffer(expectedColors));
@@ -744,27 +801,33 @@
         GTEST_SKIP();
     }
 
-    for (const DisplayWrapper* display : mDisplaysWithReadbackBuffers) {
+    for (const DisplayWrapper display : mAllDisplays) {
         ASSERT_TRUE(
                 mComposerClient
-                        ->setClientTargetSlotCount(display->getDisplayId(), kClientTargetSlotCount)
+                        ->setClientTargetSlotCount(display.getDisplayId(), kClientTargetSlotCount)
                         .isOk());
 
-        for (ColorMode mode : mDisplayProperties.at(display->getDisplayId()).testColorModes) {
-            EXPECT_TRUE(mComposerClient
-                                ->setColorMode(display->getDisplayId(), mode,
-                                               RenderIntent::COLORIMETRIC)
-                                .isOk());
+        for (ColorMode mode : mDisplayProperties.at(display.getDisplayId()).testColorModes) {
+            EXPECT_TRUE(
+                    mComposerClient
+                            ->setColorMode(display.getDisplayId(), mode, RenderIntent::COLORIMETRIC)
+                            .isOk());
+
+            auto [dataspace, readbackSupported] =
+                    GetDataspaceAndIfReadBackSupported(display.getDisplayId());
+            if (!readbackSupported) {
+                continue;
+            }
 
             // sRGB layer
             auto srgbLayer = std::make_shared<TestBufferLayer>(
                     mComposerClient,
-                    *mDisplayProperties.at(display->getDisplayId()).testRenderEngine,
-                    display->getDisplayId(), display->getDisplayWidth(),
-                    display->getDisplayHeight() / 2, PixelFormat::RGBA_8888,
-                    mDisplayProperties.at(display->getDisplayId()).writer);
+                    *mDisplayProperties.at(display.getDisplayId()).testRenderEngine,
+                    display.getDisplayId(), display.getDisplayWidth(),
+                    display.getDisplayHeight() / 2, PixelFormat::RGBA_8888,
+                    mDisplayProperties.at(display.getDisplayId()).writer);
             std::vector<Color> sRgbDeviceColors(srgbLayer->getWidth() * srgbLayer->getHeight());
-            ReadbackHelper::fillColorsArea(sRgbDeviceColors, display->getDisplayWidth(),
+            ReadbackHelper::fillColorsArea(sRgbDeviceColors, display.getDisplayWidth(),
                                            {0, 0, static_cast<int32_t>(srgbLayer->getWidth()),
                                             static_cast<int32_t>(srgbLayer->getHeight())},
                                            GREEN);
@@ -777,86 +840,90 @@
             // display P3 layer
             auto displayP3Layer = std::make_shared<TestBufferLayer>(
                     mComposerClient,
-                    *mDisplayProperties.at(display->getDisplayId()).testRenderEngine,
-                    display->getDisplayId(), display->getDisplayWidth(),
-                    display->getDisplayHeight() / 2, PixelFormat::RGBA_8888,
-                    mDisplayProperties.at(display->getDisplayId()).writer);
+                    *mDisplayProperties.at(display.getDisplayId()).testRenderEngine,
+                    display.getDisplayId(), display.getDisplayWidth(),
+                    display.getDisplayHeight() / 2, PixelFormat::RGBA_8888,
+                    mDisplayProperties.at(display.getDisplayId()).writer);
             std::vector<Color> displayP3DeviceColors(
                     static_cast<size_t>(displayP3Layer->getWidth() * displayP3Layer->getHeight()));
-            ReadbackHelper::fillColorsArea(displayP3DeviceColors, display->getDisplayWidth(),
+            ReadbackHelper::fillColorsArea(displayP3DeviceColors, display.getDisplayWidth(),
                                            {0, 0, static_cast<int32_t>(displayP3Layer->getWidth()),
                                             static_cast<int32_t>(displayP3Layer->getHeight())},
                                            RED);
-            displayP3Layer->setDisplayFrame({0, display->getDisplayHeight() / 2,
-                                             display->getDisplayWidth(),
-                                             display->getDisplayHeight()});
+            displayP3Layer->setDisplayFrame({0, display.getDisplayHeight() / 2,
+                                             display.getDisplayWidth(),
+                                             display.getDisplayHeight()});
             displayP3Layer->setZOrder(10);
             displayP3Layer->setDataspace(Dataspace::DISPLAY_P3);
             ASSERT_NO_FATAL_FAILURE(displayP3Layer->setBuffer(displayP3DeviceColors));
 
-            writeLayers({srgbLayer, displayP3Layer}, display->getDisplayId());
+            writeLayers({srgbLayer, displayP3Layer}, display.getDisplayId());
 
-            mDisplayProperties.at(display->getDisplayId())
-                    .writer.validateDisplay(display->getDisplayId(),
+            mDisplayProperties.at(display.getDisplayId())
+                    .writer.validateDisplay(display.getDisplayId(),
                                             ComposerClientWriter::kNoTimestamp,
                                             ComposerClientWrapper::kNoFrameIntervalNs);
-            execute(display->getDisplayId());
+            execute(display.getDisplayId());
 
             auto changedCompositionTypes =
-                    mDisplayProperties.at(display->getDisplayId())
-                            .reader.takeChangedCompositionTypes(display->getDisplayId());
+                    mDisplayProperties.at(display.getDisplayId())
+                            .reader.takeChangedCompositionTypes(display.getDisplayId());
             ASSERT_TRUE(changedCompositionTypes.empty());
 
-            mDisplayProperties.at(display->getDisplayId())
-                    .writer.presentDisplay(display->getDisplayId());
-            execute(display->getDisplayId());
-            ASSERT_TRUE(mDisplayProperties.at(display->getDisplayId()).reader.takeErrors().empty());
+            mDisplayProperties.at(display.getDisplayId())
+                    .writer.presentDisplay(display.getDisplayId());
+            execute(display.getDisplayId());
+            ASSERT_TRUE(mDisplayProperties.at(display.getDisplayId()).reader.takeErrors().empty());
             changedCompositionTypes =
-                    mDisplayProperties.at(display->getDisplayId())
-                            .reader.takeChangedCompositionTypes(display->getDisplayId());
+                    mDisplayProperties.at(display.getDisplayId())
+                            .reader.takeChangedCompositionTypes(display.getDisplayId());
             ASSERT_TRUE(changedCompositionTypes.empty());
-            ASSERT_TRUE(mDisplayProperties.at(display->getDisplayId()).reader.takeErrors().empty());
+            ASSERT_TRUE(mDisplayProperties.at(display.getDisplayId()).reader.takeErrors().empty());
         }
     }
 }
 
 TEST_P(GraphicsCompositionTest, DeviceAndClientComposition) {
-    for (const DisplayWrapper* display : mDisplaysWithReadbackBuffers) {
+    for (const DisplayWrapper display : mAllDisplays) {
         ASSERT_TRUE(
                 mComposerClient
-                        ->setClientTargetSlotCount(display->getDisplayId(), kClientTargetSlotCount)
+                        ->setClientTargetSlotCount(display.getDisplayId(), kClientTargetSlotCount)
                         .isOk());
 
-        for (ColorMode mode : mDisplayProperties.at(display->getDisplayId()).testColorModes) {
-            EXPECT_TRUE(mComposerClient
-                                ->setColorMode(display->getDisplayId(), mode,
-                                               RenderIntent::COLORIMETRIC)
-                                .isOk());
+        for (ColorMode mode : mDisplayProperties.at(display.getDisplayId()).testColorModes) {
+            EXPECT_TRUE(
+                    mComposerClient
+                            ->setColorMode(display.getDisplayId(), mode, RenderIntent::COLORIMETRIC)
+                            .isOk());
+
+            auto [dataspace, readbackSupported] =
+                    GetDataspaceAndIfReadBackSupported(display.getDisplayId());
+            if (!readbackSupported) {
+                continue;
+            }
 
             std::vector<Color> expectedColors(
-                    static_cast<size_t>(display->getDisplayWidth() * display->getDisplayHeight()));
+                    static_cast<size_t>(display.getDisplayWidth() * display.getDisplayHeight()));
             ReadbackHelper::fillColorsArea(
-                    expectedColors, display->getDisplayWidth(),
-                    {0, 0, display->getDisplayWidth(), display->getDisplayHeight() / 2}, GREEN);
-            ReadbackHelper::fillColorsArea(
-                    expectedColors, display->getDisplayWidth(),
-                    {0, display->getDisplayHeight() / 2, display->getDisplayWidth(),
-                     display->getDisplayHeight()},
-                    RED);
+                    expectedColors, display.getDisplayWidth(),
+                    {0, 0, display.getDisplayWidth(), display.getDisplayHeight() / 2}, GREEN);
+            ReadbackHelper::fillColorsArea(expectedColors, display.getDisplayWidth(),
+                                           {0, display.getDisplayHeight() / 2,
+                                            display.getDisplayWidth(), display.getDisplayHeight()},
+                                           RED);
 
-            ReadbackBuffer readbackBuffer(
-                    display->getDisplayId(), mComposerClient, display->getDisplayWidth(),
-                    display->getDisplayHeight(),
-                    mDisplayProperties.at(display->getDisplayId()).pixelFormat,
-                    mDisplayProperties.at(display->getDisplayId()).dataspace);
+            ReadbackBuffer readbackBuffer(display.getDisplayId(), mComposerClient,
+                                          display.getDisplayWidth(), display.getDisplayHeight(),
+                                          mDisplayProperties.at(display.getDisplayId()).pixelFormat,
+                                          dataspace);
             ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
 
             auto deviceLayer = std::make_shared<TestBufferLayer>(
                     mComposerClient,
-                    *mDisplayProperties.at(display->getDisplayId()).testRenderEngine,
-                    display->getDisplayId(), display->getDisplayWidth(),
-                    display->getDisplayHeight() / 2, PixelFormat::RGBA_8888,
-                    mDisplayProperties.at(display->getDisplayId()).writer);
+                    *mDisplayProperties.at(display.getDisplayId()).testRenderEngine,
+                    display.getDisplayId(), display.getDisplayWidth(),
+                    display.getDisplayHeight() / 2, PixelFormat::RGBA_8888,
+                    mDisplayProperties.at(display.getDisplayId()).writer);
             std::vector<Color> deviceColors(deviceLayer->getWidth() * deviceLayer->getHeight());
             ReadbackHelper::fillColorsArea(deviceColors,
                                            static_cast<int32_t>(deviceLayer->getWidth()),
@@ -868,7 +935,7 @@
             deviceLayer->setZOrder(10);
             deviceLayer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode));
             ASSERT_NO_FATAL_FAILURE(deviceLayer->setBuffer(deviceColors));
-            deviceLayer->write(mDisplayProperties.at(display->getDisplayId()).writer);
+            deviceLayer->write(mDisplayProperties.at(display.getDisplayId()).writer);
 
             PixelFormat clientFormat = PixelFormat::RGBA_8888;
             auto clientUsage = static_cast<uint32_t>(
@@ -876,35 +943,34 @@
                     static_cast<uint32_t>(common::BufferUsage::CPU_WRITE_OFTEN) |
                     static_cast<uint32_t>(common::BufferUsage::COMPOSER_CLIENT_TARGET));
             Dataspace clientDataspace = ReadbackHelper::getDataspaceForColorMode(mode);
-            int32_t clientWidth = display->getDisplayWidth();
-            int32_t clientHeight = display->getDisplayHeight() / 2;
+            int32_t clientWidth = display.getDisplayWidth();
+            int32_t clientHeight = display.getDisplayHeight() / 2;
 
             auto clientLayer = std::make_shared<TestBufferLayer>(
                     mComposerClient,
-                    *mDisplayProperties.at(display->getDisplayId()).testRenderEngine,
-                    display->getDisplayId(), clientWidth, clientHeight, PixelFormat::RGBA_FP16,
-                    mDisplayProperties.at(display->getDisplayId()).writer, Composition::DEVICE);
-            common::Rect clientFrame = {0, display->getDisplayHeight() / 2,
-                                        display->getDisplayWidth(), display->getDisplayHeight()};
+                    *mDisplayProperties.at(display.getDisplayId()).testRenderEngine,
+                    display.getDisplayId(), clientWidth, clientHeight, PixelFormat::RGBA_FP16,
+                    mDisplayProperties.at(display.getDisplayId()).writer, Composition::DEVICE);
+            common::Rect clientFrame = {0, display.getDisplayHeight() / 2,
+                                        display.getDisplayWidth(), display.getDisplayHeight()};
             clientLayer->setDisplayFrame(clientFrame);
             clientLayer->setZOrder(0);
-            clientLayer->write(mDisplayProperties.at(display->getDisplayId()).writer);
-            mDisplayProperties.at(display->getDisplayId())
-                    .writer.validateDisplay(display->getDisplayId(),
+            clientLayer->write(mDisplayProperties.at(display.getDisplayId()).writer);
+            mDisplayProperties.at(display.getDisplayId())
+                    .writer.validateDisplay(display.getDisplayId(),
                                             ComposerClientWriter::kNoTimestamp,
                                             ComposerClientWrapper::kNoFrameIntervalNs);
-            execute(display->getDisplayId());
+            execute(display.getDisplayId());
 
             auto changedCompositionTypes =
-                    mDisplayProperties.at(display->getDisplayId())
-                            .reader.takeChangedCompositionTypes(display->getDisplayId());
+                    mDisplayProperties.at(display.getDisplayId())
+                            .reader.takeChangedCompositionTypes(display.getDisplayId());
             if (changedCompositionTypes.size() != 1) {
                 continue;
             }
             // create client target buffer
             ASSERT_EQ(Composition::CLIENT, changedCompositionTypes[0].composition);
-            const auto& [graphicBufferStatus, graphicBuffer] =
-                    allocateBuffer(*display, clientUsage);
+            const auto& [graphicBufferStatus, graphicBuffer] = allocateBuffer(display, clientUsage);
             ASSERT_TRUE(graphicBufferStatus);
             const auto& buffer = graphicBuffer->handle;
 
@@ -912,131 +978,133 @@
             int bytesPerPixel = -1;
             int bytesPerStride = -1;
             graphicBuffer->lock(clientUsage,
-                                {0, 0, display->getDisplayWidth(), display->getDisplayHeight()},
+                                {0, 0, display.getDisplayWidth(), display.getDisplayHeight()},
                                 &clientBufData, &bytesPerPixel, &bytesPerStride);
 
             std::vector<Color> clientColors(
-                    static_cast<size_t>(display->getDisplayWidth() * display->getDisplayHeight()));
-            ReadbackHelper::fillColorsArea(clientColors, display->getDisplayWidth(), clientFrame,
+                    static_cast<size_t>(display.getDisplayWidth() * display.getDisplayHeight()));
+            ReadbackHelper::fillColorsArea(clientColors, display.getDisplayWidth(), clientFrame,
                                            RED);
             ASSERT_NO_FATAL_FAILURE(ReadbackHelper::fillBuffer(
-                    static_cast<uint32_t>(display->getDisplayWidth()),
-                    static_cast<uint32_t>(display->getDisplayHeight()), graphicBuffer->getStride(),
+                    static_cast<uint32_t>(display.getDisplayWidth()),
+                    static_cast<uint32_t>(display.getDisplayHeight()), graphicBuffer->getStride(),
                     bytesPerPixel, clientBufData, clientFormat, clientColors));
             int32_t clientFence;
             const auto unlockStatus = graphicBuffer->unlockAsync(&clientFence);
             ASSERT_EQ(::android::OK, unlockStatus);
-            mDisplayProperties.at(display->getDisplayId())
-                    .writer.setClientTarget(display->getDisplayId(), /*slot*/ 0, buffer,
-                                            clientFence, clientDataspace,
+            mDisplayProperties.at(display.getDisplayId())
+                    .writer.setClientTarget(display.getDisplayId(), /*slot*/ 0, buffer, clientFence,
+                                            clientDataspace,
                                             std::vector<common::Rect>(1, clientFrame), 1.f);
             clientLayer->setToClientComposition(
-                    mDisplayProperties.at(display->getDisplayId()).writer);
-            mDisplayProperties.at(display->getDisplayId())
-                    .writer.validateDisplay(display->getDisplayId(),
+                    mDisplayProperties.at(display.getDisplayId()).writer);
+            mDisplayProperties.at(display.getDisplayId())
+                    .writer.validateDisplay(display.getDisplayId(),
                                             ComposerClientWriter::kNoTimestamp,
                                             ComposerClientWrapper::kNoFrameIntervalNs);
-            execute(display->getDisplayId());
+            execute(display.getDisplayId());
             changedCompositionTypes =
-                    mDisplayProperties.at(display->getDisplayId())
-                            .reader.takeChangedCompositionTypes(display->getDisplayId());
+                    mDisplayProperties.at(display.getDisplayId())
+                            .reader.takeChangedCompositionTypes(display.getDisplayId());
             ASSERT_TRUE(changedCompositionTypes.empty());
-            ASSERT_TRUE(mDisplayProperties.at(display->getDisplayId()).reader.takeErrors().empty());
+            ASSERT_TRUE(mDisplayProperties.at(display.getDisplayId()).reader.takeErrors().empty());
 
-            mDisplayProperties.at(display->getDisplayId())
-                    .writer.presentDisplay(display->getDisplayId());
-            execute(display->getDisplayId());
-            ASSERT_TRUE(mDisplayProperties.at(display->getDisplayId()).reader.takeErrors().empty());
+            mDisplayProperties.at(display.getDisplayId())
+                    .writer.presentDisplay(display.getDisplayId());
+            execute(display.getDisplayId());
+            ASSERT_TRUE(mDisplayProperties.at(display.getDisplayId()).reader.takeErrors().empty());
             ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
         }
     }
 }
 
 TEST_P(GraphicsCompositionTest, SetLayerDamage) {
-    for (const DisplayWrapper* display : mDisplaysWithReadbackBuffers) {
-        for (ColorMode mode : mDisplayProperties.at(display->getDisplayId()).testColorModes) {
-            EXPECT_TRUE(mComposerClient
-                                ->setColorMode(display->getDisplayId(), mode,
-                                               RenderIntent::COLORIMETRIC)
-                                .isOk());
+    for (const DisplayWrapper display : mAllDisplays) {
+        for (ColorMode mode : mDisplayProperties.at(display.getDisplayId()).testColorModes) {
+            EXPECT_TRUE(
+                    mComposerClient
+                            ->setColorMode(display.getDisplayId(), mode, RenderIntent::COLORIMETRIC)
+                            .isOk());
 
-            common::Rect redRect = {0, 0, display->getDisplayWidth() / 4,
-                                    display->getDisplayHeight() / 4};
+            auto [dataspace, readbackSupported] =
+                    GetDataspaceAndIfReadBackSupported(display.getDisplayId());
+            if (!readbackSupported) {
+                continue;
+            }
+
+            common::Rect redRect = {0, 0, display.getDisplayWidth() / 4,
+                                    display.getDisplayHeight() / 4};
 
             std::vector<Color> expectedColors(
-                    static_cast<size_t>(display->getDisplayWidth() * display->getDisplayHeight()));
-            ReadbackHelper::fillColorsArea(expectedColors, display->getDisplayWidth(), redRect,
-                                           RED);
+                    static_cast<size_t>(display.getDisplayWidth() * display.getDisplayHeight()));
+            ReadbackHelper::fillColorsArea(expectedColors, display.getDisplayWidth(), redRect, RED);
 
             auto layer = std::make_shared<TestBufferLayer>(
                     mComposerClient,
-                    *mDisplayProperties.at(display->getDisplayId()).testRenderEngine,
-                    display->getDisplayId(), display->getDisplayWidth(),
-                    display->getDisplayHeight(), PixelFormat::RGBA_8888,
-                    mDisplayProperties.at(display->getDisplayId()).writer);
-            layer->setDisplayFrame({0, 0, display->getDisplayWidth(), display->getDisplayHeight()});
+                    *mDisplayProperties.at(display.getDisplayId()).testRenderEngine,
+                    display.getDisplayId(), display.getDisplayWidth(), display.getDisplayHeight(),
+                    PixelFormat::RGBA_8888, mDisplayProperties.at(display.getDisplayId()).writer);
+            layer->setDisplayFrame({0, 0, display.getDisplayWidth(), display.getDisplayHeight()});
             layer->setZOrder(10);
             layer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode));
             ASSERT_NO_FATAL_FAILURE(layer->setBuffer(expectedColors));
 
             std::vector<std::shared_ptr<TestLayer>> layers = {layer};
 
-            ReadbackBuffer readbackBuffer(
-                    display->getDisplayId(), mComposerClient, display->getDisplayWidth(),
-                    display->getDisplayHeight(),
-                    mDisplayProperties.at(display->getDisplayId()).pixelFormat,
-                    mDisplayProperties.at(display->getDisplayId()).dataspace);
+            ReadbackBuffer readbackBuffer(display.getDisplayId(), mComposerClient,
+                                          display.getDisplayWidth(), display.getDisplayHeight(),
+                                          mDisplayProperties.at(display.getDisplayId()).pixelFormat,
+                                          dataspace);
             ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
 
-            writeLayers(layers, display->getDisplayId());
-            ASSERT_TRUE(mDisplayProperties.at(display->getDisplayId()).reader.takeErrors().empty());
-            mDisplayProperties.at(display->getDisplayId())
-                    .writer.validateDisplay(display->getDisplayId(),
+            writeLayers(layers, display.getDisplayId());
+            ASSERT_TRUE(mDisplayProperties.at(display.getDisplayId()).reader.takeErrors().empty());
+            mDisplayProperties.at(display.getDisplayId())
+                    .writer.validateDisplay(display.getDisplayId(),
                                             ComposerClientWriter::kNoTimestamp,
                                             ComposerClientWrapper::kNoFrameIntervalNs);
-            execute(display->getDisplayId());
-            if (!mDisplayProperties.at(display->getDisplayId())
-                         .reader.takeChangedCompositionTypes(display->getDisplayId())
+            execute(display.getDisplayId());
+            if (!mDisplayProperties.at(display.getDisplayId())
+                         .reader.takeChangedCompositionTypes(display.getDisplayId())
                          .empty()) {
                 continue;
             }
-            ASSERT_TRUE(mDisplayProperties.at(display->getDisplayId()).reader.takeErrors().empty());
-            mDisplayProperties.at(display->getDisplayId())
-                    .writer.presentDisplay(display->getDisplayId());
-            execute(display->getDisplayId());
-            ASSERT_TRUE(mDisplayProperties.at(display->getDisplayId()).reader.takeErrors().empty());
+            ASSERT_TRUE(mDisplayProperties.at(display.getDisplayId()).reader.takeErrors().empty());
+            mDisplayProperties.at(display.getDisplayId())
+                    .writer.presentDisplay(display.getDisplayId());
+            execute(display.getDisplayId());
+            ASSERT_TRUE(mDisplayProperties.at(display.getDisplayId()).reader.takeErrors().empty());
 
             ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
 
             // update surface damage and recheck
-            redRect = {display->getDisplayWidth() / 4, display->getDisplayHeight() / 4,
-                       display->getDisplayWidth() / 2, display->getDisplayHeight() / 2};
-            ReadbackHelper::clearColors(expectedColors, display->getDisplayWidth(),
-                                        display->getDisplayHeight(), display->getDisplayWidth());
-            ReadbackHelper::fillColorsArea(expectedColors, display->getDisplayWidth(), redRect,
-                                           RED);
+            redRect = {display.getDisplayWidth() / 4, display.getDisplayHeight() / 4,
+                       display.getDisplayWidth() / 2, display.getDisplayHeight() / 2};
+            ReadbackHelper::clearColors(expectedColors, display.getDisplayWidth(),
+                                        display.getDisplayHeight(), display.getDisplayWidth());
+            ReadbackHelper::fillColorsArea(expectedColors, display.getDisplayWidth(), redRect, RED);
 
             ASSERT_NO_FATAL_FAILURE(layer->fillBuffer(expectedColors));
             layer->setSurfaceDamage(std::vector<common::Rect>(
-                    1, {0, 0, display->getDisplayWidth() / 2, display->getDisplayWidth() / 2}));
+                    1, {0, 0, display.getDisplayWidth() / 2, display.getDisplayWidth() / 2}));
 
             ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
 
-            writeLayers(layers, display->getDisplayId());
-            ASSERT_TRUE(mDisplayProperties.at(display->getDisplayId()).reader.takeErrors().empty());
-            mDisplayProperties.at(display->getDisplayId())
-                    .writer.validateDisplay(display->getDisplayId(),
+            writeLayers(layers, display.getDisplayId());
+            ASSERT_TRUE(mDisplayProperties.at(display.getDisplayId()).reader.takeErrors().empty());
+            mDisplayProperties.at(display.getDisplayId())
+                    .writer.validateDisplay(display.getDisplayId(),
                                             ComposerClientWriter::kNoTimestamp,
                                             ComposerClientWrapper::kNoFrameIntervalNs);
-            execute(display->getDisplayId());
-            ASSERT_TRUE(mDisplayProperties.at(display->getDisplayId()).reader.takeErrors().empty());
-            ASSERT_TRUE(mDisplayProperties.at(display->getDisplayId())
-                                .reader.takeChangedCompositionTypes(display->getDisplayId())
+            execute(display.getDisplayId());
+            ASSERT_TRUE(mDisplayProperties.at(display.getDisplayId()).reader.takeErrors().empty());
+            ASSERT_TRUE(mDisplayProperties.at(display.getDisplayId())
+                                .reader.takeChangedCompositionTypes(display.getDisplayId())
                                 .empty());
-            mDisplayProperties.at(display->getDisplayId())
-                    .writer.presentDisplay(display->getDisplayId());
-            execute(display->getDisplayId());
-            ASSERT_TRUE(mDisplayProperties.at(display->getDisplayId()).reader.takeErrors().empty());
+            mDisplayProperties.at(display.getDisplayId())
+                    .writer.presentDisplay(display.getDisplayId());
+            execute(display.getDisplayId());
+            ASSERT_TRUE(mDisplayProperties.at(display.getDisplayId()).reader.takeErrors().empty());
 
             ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
         }
@@ -1044,56 +1112,60 @@
 }
 
 TEST_P(GraphicsCompositionTest, SetLayerPlaneAlpha) {
-    for (const DisplayWrapper* display : mDisplaysWithReadbackBuffers) {
-        for (ColorMode mode : mDisplayProperties.at(display->getDisplayId()).testColorModes) {
-            EXPECT_TRUE(mComposerClient
-                                ->setColorMode(display->getDisplayId(), mode,
-                                               RenderIntent::COLORIMETRIC)
-                                .isOk());
+    for (const DisplayWrapper display : mAllDisplays) {
+        for (ColorMode mode : mDisplayProperties.at(display.getDisplayId()).testColorModes) {
+            EXPECT_TRUE(
+                    mComposerClient
+                            ->setColorMode(display.getDisplayId(), mode, RenderIntent::COLORIMETRIC)
+                            .isOk());
+
+            auto [dataspace, readbackSupported] =
+                    GetDataspaceAndIfReadBackSupported(display.getDisplayId());
+            if (!readbackSupported) {
+                continue;
+            }
 
             auto layer = std::make_shared<TestColorLayer>(
-                    mComposerClient, display->getDisplayId(),
-                    mDisplayProperties.at(display->getDisplayId()).writer);
+                    mComposerClient, display.getDisplayId(),
+                    mDisplayProperties.at(display.getDisplayId()).writer);
             layer->setColor(RED);
-            layer->setDisplayFrame({0, 0, display->getDisplayWidth(), display->getDisplayHeight()});
+            layer->setDisplayFrame({0, 0, display.getDisplayWidth(), display.getDisplayHeight()});
             layer->setZOrder(10);
             layer->setAlpha(0);
             layer->setBlendMode(BlendMode::PREMULTIPLIED);
 
             std::vector<std::shared_ptr<TestLayer>> layers = {layer};
 
-            ReadbackBuffer readbackBuffer(
-                    display->getDisplayId(), mComposerClient, display->getDisplayWidth(),
-                    display->getDisplayHeight(),
-                    mDisplayProperties.at(display->getDisplayId()).pixelFormat,
-                    mDisplayProperties.at(display->getDisplayId()).dataspace);
+            ReadbackBuffer readbackBuffer(display.getDisplayId(), mComposerClient,
+                                          display.getDisplayWidth(), display.getDisplayHeight(),
+                                          mDisplayProperties.at(display.getDisplayId()).pixelFormat,
+                                          dataspace);
 
             ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
 
-            writeLayers(layers, display->getDisplayId());
-            ASSERT_TRUE(mDisplayProperties.at(display->getDisplayId()).reader.takeErrors().empty());
-            mDisplayProperties.at(display->getDisplayId())
-                    .writer.validateDisplay(display->getDisplayId(),
+            writeLayers(layers, display.getDisplayId());
+            ASSERT_TRUE(mDisplayProperties.at(display.getDisplayId()).reader.takeErrors().empty());
+            mDisplayProperties.at(display.getDisplayId())
+                    .writer.validateDisplay(display.getDisplayId(),
                                             ComposerClientWriter::kNoTimestamp,
                                             ComposerClientWrapper::kNoFrameIntervalNs);
-            execute(display->getDisplayId());
-            if (!mDisplayProperties.at(display->getDisplayId())
-                         .reader.takeChangedCompositionTypes(display->getDisplayId())
+            execute(display.getDisplayId());
+            if (!mDisplayProperties.at(display.getDisplayId())
+                         .reader.takeChangedCompositionTypes(display.getDisplayId())
                          .empty()) {
                 continue;
             }
-            ASSERT_TRUE(mDisplayProperties.at(display->getDisplayId()).reader.takeErrors().empty());
-            mDisplayProperties.at(display->getDisplayId())
-                    .writer.presentDisplay(display->getDisplayId());
-            execute(display->getDisplayId());
-            ASSERT_TRUE(mDisplayProperties.at(display->getDisplayId()).reader.takeErrors().empty());
+            ASSERT_TRUE(mDisplayProperties.at(display.getDisplayId()).reader.takeErrors().empty());
+            mDisplayProperties.at(display.getDisplayId())
+                    .writer.presentDisplay(display.getDisplayId());
+            execute(display.getDisplayId());
+            ASSERT_TRUE(mDisplayProperties.at(display.getDisplayId()).reader.takeErrors().empty());
 
             std::vector<Color> expectedColors(
-                    static_cast<size_t>(display->getDisplayWidth() * display->getDisplayHeight()));
+                    static_cast<size_t>(display.getDisplayWidth() * display.getDisplayHeight()));
 
             ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
-            auto& testRenderEngine =
-                    mDisplayProperties.at(display->getDisplayId()).testRenderEngine;
+            auto& testRenderEngine = mDisplayProperties.at(display.getDisplayId()).testRenderEngine;
             testRenderEngine->setRenderLayers(layers);
             ASSERT_NO_FATAL_FAILURE(testRenderEngine->drawLayers());
             ASSERT_NO_FATAL_FAILURE(testRenderEngine->checkColorBuffer(expectedColors));
@@ -1102,70 +1174,72 @@
 }
 
 TEST_P(GraphicsCompositionTest, SetLayerSourceCrop) {
-    for (const DisplayWrapper* display : mDisplaysWithReadbackBuffers) {
-        for (ColorMode mode : mDisplayProperties.at(display->getDisplayId()).testColorModes) {
-            EXPECT_TRUE(mComposerClient
-                                ->setColorMode(display->getDisplayId(), mode,
-                                               RenderIntent::COLORIMETRIC)
-                                .isOk());
+    for (const DisplayWrapper display : mAllDisplays) {
+        for (ColorMode mode : mDisplayProperties.at(display.getDisplayId()).testColorModes) {
+            EXPECT_TRUE(
+                    mComposerClient
+                            ->setColorMode(display.getDisplayId(), mode, RenderIntent::COLORIMETRIC)
+                            .isOk());
+
+            auto [dataspace, readbackSupported] =
+                    GetDataspaceAndIfReadBackSupported(display.getDisplayId());
+            if (!readbackSupported) {
+                continue;
+            }
 
             std::vector<Color> expectedColors(
-                    static_cast<size_t>(display->getDisplayWidth() * display->getDisplayHeight()));
+                    static_cast<size_t>(display.getDisplayWidth() * display.getDisplayHeight()));
             ReadbackHelper::fillColorsArea(
-                    expectedColors, display->getDisplayWidth(),
-                    {0, 0, display->getDisplayWidth(), display->getDisplayHeight() / 4}, RED);
-            ReadbackHelper::fillColorsArea(
-                    expectedColors, display->getDisplayWidth(),
-                    {0, display->getDisplayHeight() / 2, display->getDisplayWidth(),
-                     display->getDisplayHeight()},
-                    BLUE);
+                    expectedColors, display.getDisplayWidth(),
+                    {0, 0, display.getDisplayWidth(), display.getDisplayHeight() / 4}, RED);
+            ReadbackHelper::fillColorsArea(expectedColors, display.getDisplayWidth(),
+                                           {0, display.getDisplayHeight() / 2,
+                                            display.getDisplayWidth(), display.getDisplayHeight()},
+                                           BLUE);
 
             auto layer = std::make_shared<TestBufferLayer>(
                     mComposerClient,
-                    *mDisplayProperties.at(display->getDisplayId()).testRenderEngine,
-                    display->getDisplayId(), display->getDisplayWidth(),
-                    display->getDisplayHeight(), PixelFormat::RGBA_8888,
-                    mDisplayProperties.at(display->getDisplayId()).writer);
-            layer->setDisplayFrame({0, 0, display->getDisplayWidth(), display->getDisplayHeight()});
+                    *mDisplayProperties.at(display.getDisplayId()).testRenderEngine,
+                    display.getDisplayId(), display.getDisplayWidth(), display.getDisplayHeight(),
+                    PixelFormat::RGBA_8888, mDisplayProperties.at(display.getDisplayId()).writer);
+            layer->setDisplayFrame({0, 0, display.getDisplayWidth(), display.getDisplayHeight()});
             layer->setZOrder(10);
             layer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode));
-            layer->setSourceCrop({0, static_cast<float>(display->getDisplayHeight() / 2),
-                                  static_cast<float>(display->getDisplayWidth()),
-                                  static_cast<float>(display->getDisplayHeight())});
+            layer->setSourceCrop({0, static_cast<float>(display.getDisplayHeight() / 2),
+                                  static_cast<float>(display.getDisplayWidth()),
+                                  static_cast<float>(display.getDisplayHeight())});
             ASSERT_NO_FATAL_FAILURE(layer->setBuffer(expectedColors));
 
             std::vector<std::shared_ptr<TestLayer>> layers = {layer};
 
             // update expected colors to match crop
             ReadbackHelper::fillColorsArea(
-                    expectedColors, display->getDisplayWidth(),
-                    {0, 0, display->getDisplayWidth(), display->getDisplayHeight()}, BLUE);
-            ReadbackBuffer readbackBuffer(
-                    display->getDisplayId(), mComposerClient, display->getDisplayWidth(),
-                    display->getDisplayHeight(),
-                    mDisplayProperties.at(display->getDisplayId()).pixelFormat,
-                    mDisplayProperties.at(display->getDisplayId()).dataspace);
+                    expectedColors, display.getDisplayWidth(),
+                    {0, 0, display.getDisplayWidth(), display.getDisplayHeight()}, BLUE);
+            ReadbackBuffer readbackBuffer(display.getDisplayId(), mComposerClient,
+                                          display.getDisplayWidth(), display.getDisplayHeight(),
+                                          mDisplayProperties.at(display.getDisplayId()).pixelFormat,
+                                          dataspace);
             ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
-            writeLayers(layers, display->getDisplayId());
-            ASSERT_TRUE(mDisplayProperties.at(display->getDisplayId()).reader.takeErrors().empty());
-            mDisplayProperties.at(display->getDisplayId())
-                    .writer.validateDisplay(display->getDisplayId(),
+            writeLayers(layers, display.getDisplayId());
+            ASSERT_TRUE(mDisplayProperties.at(display.getDisplayId()).reader.takeErrors().empty());
+            mDisplayProperties.at(display.getDisplayId())
+                    .writer.validateDisplay(display.getDisplayId(),
                                             ComposerClientWriter::kNoTimestamp,
                                             ComposerClientWrapper::kNoFrameIntervalNs);
-            execute(display->getDisplayId());
-            if (!mDisplayProperties.at(display->getDisplayId())
-                         .reader.takeChangedCompositionTypes(display->getDisplayId())
+            execute(display.getDisplayId());
+            if (!mDisplayProperties.at(display.getDisplayId())
+                         .reader.takeChangedCompositionTypes(display.getDisplayId())
                          .empty()) {
                 continue;
             }
-            ASSERT_TRUE(mDisplayProperties.at(display->getDisplayId()).reader.takeErrors().empty());
-            mDisplayProperties.at(display->getDisplayId())
-                    .writer.presentDisplay(display->getDisplayId());
-            execute(display->getDisplayId());
-            ASSERT_TRUE(mDisplayProperties.at(display->getDisplayId()).reader.takeErrors().empty());
+            ASSERT_TRUE(mDisplayProperties.at(display.getDisplayId()).reader.takeErrors().empty());
+            mDisplayProperties.at(display.getDisplayId())
+                    .writer.presentDisplay(display.getDisplayId());
+            execute(display.getDisplayId());
+            ASSERT_TRUE(mDisplayProperties.at(display.getDisplayId()).reader.takeErrors().empty());
             ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
-            auto& testRenderEngine =
-                    mDisplayProperties.at(display->getDisplayId()).testRenderEngine;
+            auto& testRenderEngine = mDisplayProperties.at(display.getDisplayId()).testRenderEngine;
             testRenderEngine->setRenderLayers(layers);
             ASSERT_NO_FATAL_FAILURE(testRenderEngine->drawLayers());
             ASSERT_NO_FATAL_FAILURE(testRenderEngine->checkColorBuffer(expectedColors));
@@ -1174,98 +1248,100 @@
 }
 
 TEST_P(GraphicsCompositionTest, SetLayerZOrder) {
-    for (const DisplayWrapper* display : mDisplaysWithReadbackBuffers) {
-        for (ColorMode mode : mDisplayProperties.at(display->getDisplayId()).testColorModes) {
-            EXPECT_TRUE(mComposerClient
-                                ->setColorMode(display->getDisplayId(), mode,
-                                               RenderIntent::COLORIMETRIC)
-                                .isOk());
+    for (const DisplayWrapper display : mAllDisplays) {
+        for (ColorMode mode : mDisplayProperties.at(display.getDisplayId()).testColorModes) {
+            EXPECT_TRUE(
+                    mComposerClient
+                            ->setColorMode(display.getDisplayId(), mode, RenderIntent::COLORIMETRIC)
+                            .isOk());
 
-            common::Rect redRect = {0, 0, display->getDisplayWidth(),
-                                    display->getDisplayHeight() / 2};
-            common::Rect blueRect = {0, display->getDisplayHeight() / 4, display->getDisplayWidth(),
-                                     display->getDisplayHeight()};
+            auto [dataspace, readbackSupported] =
+                    GetDataspaceAndIfReadBackSupported(display.getDisplayId());
+            if (!readbackSupported) {
+                continue;
+            }
+
+            common::Rect redRect = {0, 0, display.getDisplayWidth(),
+                                    display.getDisplayHeight() / 2};
+            common::Rect blueRect = {0, display.getDisplayHeight() / 4, display.getDisplayWidth(),
+                                     display.getDisplayHeight()};
             auto redLayer = std::make_shared<TestColorLayer>(
-                    mComposerClient, display->getDisplayId(),
-                    mDisplayProperties.at(display->getDisplayId()).writer);
+                    mComposerClient, display.getDisplayId(),
+                    mDisplayProperties.at(display.getDisplayId()).writer);
             redLayer->setColor(RED);
             redLayer->setDisplayFrame(redRect);
 
             auto blueLayer = std::make_shared<TestColorLayer>(
-                    mComposerClient, display->getDisplayId(),
-                    mDisplayProperties.at(display->getDisplayId()).writer);
+                    mComposerClient, display.getDisplayId(),
+                    mDisplayProperties.at(display.getDisplayId()).writer);
             blueLayer->setColor(BLUE);
             blueLayer->setDisplayFrame(blueRect);
             blueLayer->setZOrder(5);
 
             std::vector<std::shared_ptr<TestLayer>> layers = {redLayer, blueLayer};
             std::vector<Color> expectedColors(
-                    static_cast<size_t>(display->getDisplayWidth() * display->getDisplayHeight()));
+                    static_cast<size_t>(display.getDisplayWidth() * display.getDisplayHeight()));
 
             // red in front of blue
             redLayer->setZOrder(10);
 
             // fill blue first so that red will overwrite on overlap
-            ReadbackHelper::fillColorsArea(expectedColors, display->getDisplayWidth(), blueRect,
+            ReadbackHelper::fillColorsArea(expectedColors, display.getDisplayWidth(), blueRect,
                                            BLUE);
-            ReadbackHelper::fillColorsArea(expectedColors, display->getDisplayWidth(), redRect,
-                                           RED);
+            ReadbackHelper::fillColorsArea(expectedColors, display.getDisplayWidth(), redRect, RED);
 
-            ReadbackBuffer readbackBuffer(
-                    display->getDisplayId(), mComposerClient, display->getDisplayWidth(),
-                    display->getDisplayHeight(),
-                    mDisplayProperties.at(display->getDisplayId()).pixelFormat,
-                    mDisplayProperties.at(display->getDisplayId()).dataspace);
+            ReadbackBuffer readbackBuffer(display.getDisplayId(), mComposerClient,
+                                          display.getDisplayWidth(), display.getDisplayHeight(),
+                                          mDisplayProperties.at(display.getDisplayId()).pixelFormat,
+                                          dataspace);
             ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
 
-            writeLayers(layers, display->getDisplayId());
-            ASSERT_TRUE(mDisplayProperties.at(display->getDisplayId()).reader.takeErrors().empty());
-            mDisplayProperties.at(display->getDisplayId())
-                    .writer.validateDisplay(display->getDisplayId(),
+            writeLayers(layers, display.getDisplayId());
+            ASSERT_TRUE(mDisplayProperties.at(display.getDisplayId()).reader.takeErrors().empty());
+            mDisplayProperties.at(display.getDisplayId())
+                    .writer.validateDisplay(display.getDisplayId(),
                                             ComposerClientWriter::kNoTimestamp,
                                             ComposerClientWrapper::kNoFrameIntervalNs);
-            execute(display->getDisplayId());
-            if (!mDisplayProperties.at(display->getDisplayId())
-                         .reader.takeChangedCompositionTypes(display->getDisplayId())
+            execute(display.getDisplayId());
+            if (!mDisplayProperties.at(display.getDisplayId())
+                         .reader.takeChangedCompositionTypes(display.getDisplayId())
                          .empty()) {
                 continue;
             }
-            mDisplayProperties.at(display->getDisplayId())
-                    .writer.presentDisplay(display->getDisplayId());
-            execute(display->getDisplayId());
-            ASSERT_TRUE(mDisplayProperties.at(display->getDisplayId()).reader.takeErrors().empty());
+            mDisplayProperties.at(display.getDisplayId())
+                    .writer.presentDisplay(display.getDisplayId());
+            execute(display.getDisplayId());
+            ASSERT_TRUE(mDisplayProperties.at(display.getDisplayId()).reader.takeErrors().empty());
 
             ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
 
             redLayer->setZOrder(1);
-            ReadbackHelper::clearColors(expectedColors, display->getDisplayWidth(),
-                                        display->getDisplayHeight(), display->getDisplayWidth());
-            ReadbackHelper::fillColorsArea(expectedColors, display->getDisplayWidth(), redRect,
-                                           RED);
-            ReadbackHelper::fillColorsArea(expectedColors, display->getDisplayWidth(), blueRect,
+            ReadbackHelper::clearColors(expectedColors, display.getDisplayWidth(),
+                                        display.getDisplayHeight(), display.getDisplayWidth());
+            ReadbackHelper::fillColorsArea(expectedColors, display.getDisplayWidth(), redRect, RED);
+            ReadbackHelper::fillColorsArea(expectedColors, display.getDisplayWidth(), blueRect,
                                            BLUE);
 
             ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
 
-            writeLayers(layers, display->getDisplayId());
-            ASSERT_TRUE(mDisplayProperties.at(display->getDisplayId()).reader.takeErrors().empty());
-            mDisplayProperties.at(display->getDisplayId())
-                    .writer.validateDisplay(display->getDisplayId(),
+            writeLayers(layers, display.getDisplayId());
+            ASSERT_TRUE(mDisplayProperties.at(display.getDisplayId()).reader.takeErrors().empty());
+            mDisplayProperties.at(display.getDisplayId())
+                    .writer.validateDisplay(display.getDisplayId(),
                                             ComposerClientWriter::kNoTimestamp,
                                             ComposerClientWrapper::kNoFrameIntervalNs);
-            execute(display->getDisplayId());
-            ASSERT_TRUE(mDisplayProperties.at(display->getDisplayId())
-                                .reader.takeChangedCompositionTypes(display->getDisplayId())
+            execute(display.getDisplayId());
+            ASSERT_TRUE(mDisplayProperties.at(display.getDisplayId())
+                                .reader.takeChangedCompositionTypes(display.getDisplayId())
                                 .empty());
-            ASSERT_TRUE(mDisplayProperties.at(display->getDisplayId()).reader.takeErrors().empty());
-            mDisplayProperties.at(display->getDisplayId())
-                    .writer.presentDisplay(display->getDisplayId());
-            execute(display->getDisplayId());
-            ASSERT_TRUE(mDisplayProperties.at(display->getDisplayId()).reader.takeErrors().empty());
+            ASSERT_TRUE(mDisplayProperties.at(display.getDisplayId()).reader.takeErrors().empty());
+            mDisplayProperties.at(display.getDisplayId())
+                    .writer.presentDisplay(display.getDisplayId());
+            execute(display.getDisplayId());
+            ASSERT_TRUE(mDisplayProperties.at(display.getDisplayId()).reader.takeErrors().empty());
 
             ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
-            auto& testRenderEngine =
-                    mDisplayProperties.at(display->getDisplayId()).testRenderEngine;
+            auto& testRenderEngine = mDisplayProperties.at(display.getDisplayId()).testRenderEngine;
             testRenderEngine->setRenderLayers(layers);
             ASSERT_NO_FATAL_FAILURE(testRenderEngine->drawLayers());
             ASSERT_NO_FATAL_FAILURE(testRenderEngine->checkColorBuffer(expectedColors));
@@ -1274,32 +1350,38 @@
 }
 
 TEST_P(GraphicsCompositionTest, SetLayerBrightnessDims) {
-    for (const DisplayWrapper* display : mDisplaysWithReadbackBuffers) {
-        for (ColorMode mode : mDisplayProperties.at(display->getDisplayId()).testColorModes) {
-            EXPECT_TRUE(mComposerClient
-                                ->setColorMode(display->getDisplayId(), mode,
-                                               RenderIntent::COLORIMETRIC)
-                                .isOk());
+    for (const DisplayWrapper display : mAllDisplays) {
+        for (ColorMode mode : mDisplayProperties.at(display.getDisplayId()).testColorModes) {
+            EXPECT_TRUE(
+                    mComposerClient
+                            ->setColorMode(display.getDisplayId(), mode, RenderIntent::COLORIMETRIC)
+                            .isOk());
 
-            const common::Rect redRect = {0, 0, display->getDisplayWidth(),
-                                          display->getDisplayHeight() / 2};
-            const common::Rect dimmerRedRect = {0, display->getDisplayHeight() / 2,
-                                                display->getDisplayWidth(),
-                                                display->getDisplayHeight()};
+            auto [dataspace, readbackSupported] =
+                    GetDataspaceAndIfReadBackSupported(display.getDisplayId());
+            if (!readbackSupported) {
+                continue;
+            }
+
+            const common::Rect redRect = {0, 0, display.getDisplayWidth(),
+                                          display.getDisplayHeight() / 2};
+            const common::Rect dimmerRedRect = {0, display.getDisplayHeight() / 2,
+                                                display.getDisplayWidth(),
+                                                display.getDisplayHeight()};
 
             static constexpr float kMaxBrightnessNits = 300.f;
 
             const auto redLayer = std::make_shared<TestColorLayer>(
-                    mComposerClient, display->getDisplayId(),
-                    mDisplayProperties.at(display->getDisplayId()).writer);
+                    mComposerClient, display.getDisplayId(),
+                    mDisplayProperties.at(display.getDisplayId()).writer);
             redLayer->setColor(RED);
             redLayer->setDisplayFrame(redRect);
             redLayer->setWhitePointNits(kMaxBrightnessNits);
             redLayer->setBrightness(1.f);
 
             const auto dimmerRedLayer = std::make_shared<TestColorLayer>(
-                    mComposerClient, display->getDisplayId(),
-                    mDisplayProperties.at(display->getDisplayId()).writer);
+                    mComposerClient, display.getDisplayId(),
+                    mDisplayProperties.at(display.getDisplayId()).writer);
             dimmerRedLayer->setColor(RED);
             dimmerRedLayer->setDisplayFrame(dimmerRedRect);
             // Intentionally use a small dimming ratio as some implementations may be more likely
@@ -1310,42 +1392,39 @@
 
             const std::vector<std::shared_ptr<TestLayer>> layers = {redLayer, dimmerRedLayer};
             std::vector<Color> expectedColors(
-                    static_cast<size_t>(display->getDisplayWidth() * display->getDisplayHeight()));
+                    static_cast<size_t>(display.getDisplayWidth() * display.getDisplayHeight()));
 
-            ReadbackHelper::fillColorsArea(expectedColors, display->getDisplayWidth(), redRect,
-                                           RED);
-            ReadbackHelper::fillColorsArea(expectedColors, display->getDisplayWidth(),
-                                           dimmerRedRect, DIM_RED);
+            ReadbackHelper::fillColorsArea(expectedColors, display.getDisplayWidth(), redRect, RED);
+            ReadbackHelper::fillColorsArea(expectedColors, display.getDisplayWidth(), dimmerRedRect,
+                                           DIM_RED);
 
-            ReadbackBuffer readbackBuffer(
-                    display->getDisplayId(), mComposerClient, display->getDisplayWidth(),
-                    display->getDisplayHeight(),
-                    mDisplayProperties.at(display->getDisplayId()).pixelFormat,
-                    mDisplayProperties.at(display->getDisplayId()).dataspace);
+            ReadbackBuffer readbackBuffer(display.getDisplayId(), mComposerClient,
+                                          display.getDisplayWidth(), display.getDisplayHeight(),
+                                          mDisplayProperties.at(display.getDisplayId()).pixelFormat,
+                                          dataspace);
             ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
 
-            writeLayers(layers, display->getDisplayId());
-            ASSERT_TRUE(mDisplayProperties.at(display->getDisplayId()).reader.takeErrors().empty());
-            mDisplayProperties.at(display->getDisplayId())
-                    .writer.validateDisplay(display->getDisplayId(),
+            writeLayers(layers, display.getDisplayId());
+            ASSERT_TRUE(mDisplayProperties.at(display.getDisplayId()).reader.takeErrors().empty());
+            mDisplayProperties.at(display.getDisplayId())
+                    .writer.validateDisplay(display.getDisplayId(),
                                             ComposerClientWriter::kNoTimestamp,
                                             ComposerClientWrapper::kNoFrameIntervalNs);
-            execute(display->getDisplayId());
-            if (!mDisplayProperties.at(display->getDisplayId())
-                         .reader.takeChangedCompositionTypes(display->getDisplayId())
+            execute(display.getDisplayId());
+            if (!mDisplayProperties.at(display.getDisplayId())
+                         .reader.takeChangedCompositionTypes(display.getDisplayId())
                          .empty()) {
                 ALOGI(" Readback verification not supported for GPU composition for color mode %d",
                       mode);
                 continue;
             }
-            mDisplayProperties.at(display->getDisplayId())
-                    .writer.presentDisplay(display->getDisplayId());
-            execute(display->getDisplayId());
-            ASSERT_TRUE(mDisplayProperties.at(display->getDisplayId()).reader.takeErrors().empty());
+            mDisplayProperties.at(display.getDisplayId())
+                    .writer.presentDisplay(display.getDisplayId());
+            execute(display.getDisplayId());
+            ASSERT_TRUE(mDisplayProperties.at(display.getDisplayId()).reader.takeErrors().empty());
 
             ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
-            auto& testRenderEngine =
-                    mDisplayProperties.at(display->getDisplayId()).testRenderEngine;
+            auto& testRenderEngine = mDisplayProperties.at(display.getDisplayId()).testRenderEngine;
             testRenderEngine->setRenderLayers(layers);
             ASSERT_NO_FATAL_FAILURE(testRenderEngine->drawLayers());
             ASSERT_NO_FATAL_FAILURE(testRenderEngine->checkColorBuffer(expectedColors));
@@ -1462,49 +1541,53 @@
 };
 
 TEST_P(GraphicsBlendModeCompositionTest, None) {
-    for (const DisplayWrapper* display : mDisplaysWithReadbackBuffers) {
-        for (ColorMode mode : mDisplayProperties.at(display->getDisplayId()).testColorModes) {
-            EXPECT_TRUE(mComposerClient
-                                ->setColorMode(display->getDisplayId(), mode,
-                                               RenderIntent::COLORIMETRIC)
-                                .isOk());
+    for (const DisplayWrapper display : mAllDisplays) {
+        for (ColorMode mode : mDisplayProperties.at(display.getDisplayId()).testColorModes) {
+            EXPECT_TRUE(
+                    mComposerClient
+                            ->setColorMode(display.getDisplayId(), mode, RenderIntent::COLORIMETRIC)
+                            .isOk());
+
+            auto [dataspace, readbackSupported] =
+                    GetDataspaceAndIfReadBackSupported(display.getDisplayId());
+            if (!readbackSupported) {
+                continue;
+            }
 
             std::vector<Color> expectedColors(
-                    static_cast<size_t>(display->getDisplayWidth() * display->getDisplayHeight()));
+                    static_cast<size_t>(display.getDisplayWidth() * display.getDisplayHeight()));
 
-            setBackgroundColor(display->getDisplayId(), BLACK);
-            setTopLayerColor(display->getDisplayId(), TRANSLUCENT_RED);
-            setUpLayers(*display, BlendMode::NONE);
-            setExpectedColors(*display, expectedColors);
+            setBackgroundColor(display.getDisplayId(), BLACK);
+            setTopLayerColor(display.getDisplayId(), TRANSLUCENT_RED);
+            setUpLayers(display, BlendMode::NONE);
+            setExpectedColors(display, expectedColors);
 
-            ReadbackBuffer readbackBuffer(
-                    display->getDisplayId(), mComposerClient, display->getDisplayWidth(),
-                    display->getDisplayHeight(),
-                    mDisplayProperties.at(display->getDisplayId()).pixelFormat,
-                    mDisplayProperties.at(display->getDisplayId()).dataspace);
+            ReadbackBuffer readbackBuffer(display.getDisplayId(), mComposerClient,
+                                          display.getDisplayWidth(), display.getDisplayHeight(),
+                                          mDisplayProperties.at(display.getDisplayId()).pixelFormat,
+                                          dataspace);
             ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
-            auto& layers = mDisplayGfx[display->getDisplayId()].layers;
-            writeLayers(layers, display->getDisplayId());
-            ASSERT_TRUE(mDisplayProperties.at(display->getDisplayId()).reader.takeErrors().empty());
-            mDisplayProperties.at(display->getDisplayId())
-                    .writer.validateDisplay(display->getDisplayId(),
+            auto& layers = mDisplayGfx[display.getDisplayId()].layers;
+            writeLayers(layers, display.getDisplayId());
+            ASSERT_TRUE(mDisplayProperties.at(display.getDisplayId()).reader.takeErrors().empty());
+            mDisplayProperties.at(display.getDisplayId())
+                    .writer.validateDisplay(display.getDisplayId(),
                                             ComposerClientWriter::kNoTimestamp,
                                             ComposerClientWrapper::kNoFrameIntervalNs);
-            execute(display->getDisplayId());
-            if (!mDisplayProperties.at(display->getDisplayId())
-                         .reader.takeChangedCompositionTypes(display->getDisplayId())
+            execute(display.getDisplayId());
+            if (!mDisplayProperties.at(display.getDisplayId())
+                         .reader.takeChangedCompositionTypes(display.getDisplayId())
                          .empty()) {
                 continue;
             }
-            ASSERT_TRUE(mDisplayProperties.at(display->getDisplayId()).reader.takeErrors().empty());
-            mDisplayProperties.at(display->getDisplayId())
-                    .writer.presentDisplay(display->getDisplayId());
-            execute(display->getDisplayId());
-            ASSERT_TRUE(mDisplayProperties.at(display->getDisplayId()).reader.takeErrors().empty());
+            ASSERT_TRUE(mDisplayProperties.at(display.getDisplayId()).reader.takeErrors().empty());
+            mDisplayProperties.at(display.getDisplayId())
+                    .writer.presentDisplay(display.getDisplayId());
+            execute(display.getDisplayId());
+            ASSERT_TRUE(mDisplayProperties.at(display.getDisplayId()).reader.takeErrors().empty());
 
             ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
-            auto& testRenderEngine =
-                    mDisplayProperties.at(display->getDisplayId()).testRenderEngine;
+            auto& testRenderEngine = mDisplayProperties.at(display.getDisplayId()).testRenderEngine;
             testRenderEngine->setRenderLayers(layers);
             ASSERT_NO_FATAL_FAILURE(testRenderEngine->drawLayers());
             ASSERT_NO_FATAL_FAILURE(testRenderEngine->checkColorBuffer(expectedColors));
@@ -1513,94 +1596,103 @@
 }
 
 TEST_P(GraphicsBlendModeCompositionTest, Coverage) {
-    for (const DisplayWrapper* display : mDisplaysWithReadbackBuffers) {
-        for (ColorMode mode : mDisplayProperties.at(display->getDisplayId()).testColorModes) {
-            EXPECT_TRUE(mComposerClient
-                                ->setColorMode(display->getDisplayId(), mode,
-                                               RenderIntent::COLORIMETRIC)
-                                .isOk());
+    for (const DisplayWrapper display : mAllDisplays) {
+        for (ColorMode mode : mDisplayProperties.at(display.getDisplayId()).testColorModes) {
+            EXPECT_TRUE(
+                    mComposerClient
+                            ->setColorMode(display.getDisplayId(), mode, RenderIntent::COLORIMETRIC)
+                            .isOk());
+
+            auto [dataspace, readbackSupported] =
+                    GetDataspaceAndIfReadBackSupported(display.getDisplayId());
+            if (!readbackSupported) {
+                continue;
+            }
 
             std::vector<Color> expectedColors(
-                    static_cast<size_t>(display->getDisplayWidth() * display->getDisplayHeight()));
+                    static_cast<size_t>(display.getDisplayWidth() * display.getDisplayHeight()));
 
-            setBackgroundColor(display->getDisplayId(), BLACK);
-            setTopLayerColor(display->getDisplayId(), TRANSLUCENT_RED);
+            setBackgroundColor(display.getDisplayId(), BLACK);
+            setTopLayerColor(display.getDisplayId(), TRANSLUCENT_RED);
 
-            setUpLayers(*display, BlendMode::COVERAGE);
-            setExpectedColors(*display, expectedColors);
+            setUpLayers(display, BlendMode::COVERAGE);
+            setExpectedColors(display, expectedColors);
 
-            ReadbackBuffer readbackBuffer(
-                    display->getDisplayId(), mComposerClient, display->getDisplayWidth(),
-                    display->getDisplayHeight(),
-                    mDisplayProperties.at(display->getDisplayId()).pixelFormat,
-                    mDisplayProperties.at(display->getDisplayId()).dataspace);
+            ReadbackBuffer readbackBuffer(display.getDisplayId(), mComposerClient,
+                                          display.getDisplayWidth(), display.getDisplayHeight(),
+                                          mDisplayProperties.at(display.getDisplayId()).pixelFormat,
+                                          dataspace);
             ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
-            auto& layers = mDisplayGfx[display->getDisplayId()].layers;
-            writeLayers(layers, display->getDisplayId());
-            ASSERT_TRUE(mDisplayProperties.at(display->getDisplayId()).reader.takeErrors().empty());
-            mDisplayProperties.at(display->getDisplayId())
-                    .writer.validateDisplay(display->getDisplayId(),
+            auto& layers = mDisplayGfx[display.getDisplayId()].layers;
+            writeLayers(layers, display.getDisplayId());
+            ASSERT_TRUE(mDisplayProperties.at(display.getDisplayId()).reader.takeErrors().empty());
+            mDisplayProperties.at(display.getDisplayId())
+                    .writer.validateDisplay(display.getDisplayId(),
                                             ComposerClientWriter::kNoTimestamp,
                                             ComposerClientWrapper::kNoFrameIntervalNs);
-            execute(display->getDisplayId());
-            if (!mDisplayProperties.at(display->getDisplayId())
-                         .reader.takeChangedCompositionTypes(display->getDisplayId())
+            execute(display.getDisplayId());
+            if (!mDisplayProperties.at(display.getDisplayId())
+                         .reader.takeChangedCompositionTypes(display.getDisplayId())
                          .empty()) {
                 continue;
             }
-            ASSERT_TRUE(mDisplayProperties.at(display->getDisplayId()).reader.takeErrors().empty());
-            mDisplayProperties.at(display->getDisplayId())
-                    .writer.presentDisplay(display->getDisplayId());
-            execute(display->getDisplayId());
-            ASSERT_TRUE(mDisplayProperties.at(display->getDisplayId()).reader.takeErrors().empty());
+            ASSERT_TRUE(mDisplayProperties.at(display.getDisplayId()).reader.takeErrors().empty());
+            mDisplayProperties.at(display.getDisplayId())
+                    .writer.presentDisplay(display.getDisplayId());
+            execute(display.getDisplayId());
+            ASSERT_TRUE(mDisplayProperties.at(display.getDisplayId()).reader.takeErrors().empty());
             ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
         }
     }
 }
 
 TEST_P(GraphicsBlendModeCompositionTest, Premultiplied) {
-    for (const DisplayWrapper* display : mDisplaysWithReadbackBuffers) {
-        for (ColorMode mode : mDisplayProperties.at(display->getDisplayId()).testColorModes) {
-            EXPECT_TRUE(mComposerClient
-                                ->setColorMode(display->getDisplayId(), mode,
-                                               RenderIntent::COLORIMETRIC)
-                                .isOk());
+    for (const DisplayWrapper display : mAllDisplays) {
+        for (ColorMode mode : mDisplayProperties.at(display.getDisplayId()).testColorModes) {
+            EXPECT_TRUE(
+                    mComposerClient
+                            ->setColorMode(display.getDisplayId(), mode, RenderIntent::COLORIMETRIC)
+                            .isOk());
+
+            auto [dataspace, readbackSupported] =
+                    GetDataspaceAndIfReadBackSupported(display.getDisplayId());
+            if (!readbackSupported) {
+                continue;
+            }
 
             std::vector<Color> expectedColors(
-                    static_cast<size_t>(display->getDisplayWidth() * display->getDisplayHeight()));
+                    static_cast<size_t>(display.getDisplayWidth() * display.getDisplayHeight()));
 
-            setBackgroundColor(display->getDisplayId(), BLACK);
-            setTopLayerColor(display->getDisplayId(), TRANSLUCENT_RED);
-            setUpLayers(*display, BlendMode::PREMULTIPLIED);
-            setExpectedColors(*display, expectedColors);
+            setBackgroundColor(display.getDisplayId(), BLACK);
+            setTopLayerColor(display.getDisplayId(), TRANSLUCENT_RED);
+            setUpLayers(display, BlendMode::PREMULTIPLIED);
+            setExpectedColors(display, expectedColors);
 
-            ReadbackBuffer readbackBuffer(
-                    display->getDisplayId(), mComposerClient, display->getDisplayWidth(),
-                    display->getDisplayHeight(),
-                    mDisplayProperties.at(display->getDisplayId()).pixelFormat,
-                    mDisplayProperties.at(display->getDisplayId()).dataspace);
+            ReadbackBuffer readbackBuffer(display.getDisplayId(), mComposerClient,
+                                          display.getDisplayWidth(), display.getDisplayHeight(),
+                                          mDisplayProperties.at(display.getDisplayId()).pixelFormat,
+                                          dataspace);
             ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
-            auto& layers = mDisplayGfx[display->getDisplayId()].layers;
-            writeLayers(layers, display->getDisplayId());
-            ASSERT_TRUE(mDisplayProperties.at(display->getDisplayId()).reader.takeErrors().empty());
-            mDisplayProperties.at(display->getDisplayId())
-                    .writer.validateDisplay(display->getDisplayId(),
+            auto& layers = mDisplayGfx[display.getDisplayId()].layers;
+            writeLayers(layers, display.getDisplayId());
+            ASSERT_TRUE(mDisplayProperties.at(display.getDisplayId()).reader.takeErrors().empty());
+            mDisplayProperties.at(display.getDisplayId())
+                    .writer.validateDisplay(display.getDisplayId(),
                                             ComposerClientWriter::kNoTimestamp,
                                             ComposerClientWrapper::kNoFrameIntervalNs);
-            execute(display->getDisplayId());
-            if (!mDisplayProperties.at(display->getDisplayId())
-                         .reader.takeChangedCompositionTypes(display->getDisplayId())
+            execute(display.getDisplayId());
+            if (!mDisplayProperties.at(display.getDisplayId())
+                         .reader.takeChangedCompositionTypes(display.getDisplayId())
                          .empty()) {
                 continue;
             }
-            ASSERT_TRUE(mDisplayProperties.at(display->getDisplayId()).reader.takeErrors().empty());
-            mDisplayProperties.at(display->getDisplayId())
-                    .writer.presentDisplay(display->getDisplayId());
-            execute(display->getDisplayId());
-            ASSERT_TRUE(mDisplayProperties.at(display->getDisplayId()).reader.takeErrors().empty());
+            ASSERT_TRUE(mDisplayProperties.at(display.getDisplayId()).reader.takeErrors().empty());
+            mDisplayProperties.at(display.getDisplayId())
+                    .writer.presentDisplay(display.getDisplayId());
+            execute(display.getDisplayId());
+            ASSERT_TRUE(mDisplayProperties.at(display.getDisplayId()).reader.takeErrors().empty());
             ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
-            auto& testRenderEngine =
-                    mDisplayProperties.at(display->getDisplayId()).testRenderEngine;
+            auto& testRenderEngine = mDisplayProperties.at(display.getDisplayId()).testRenderEngine;
             testRenderEngine->setRenderLayers(layers);
             ASSERT_NO_FATAL_FAILURE(testRenderEngine->drawLayers());
             ASSERT_NO_FATAL_FAILURE(testRenderEngine->checkColorBuffer(expectedColors));
@@ -1658,58 +1750,63 @@
 };
 
 TEST_P(GraphicsTransformCompositionTest, FLIP_H) {
-    for (const DisplayWrapper* display : mDisplaysWithReadbackBuffers) {
-        for (ColorMode mode : mDisplayProperties.at(display->getDisplayId()).testColorModes) {
-            auto status = mComposerClient->setColorMode(display->getDisplayId(), mode,
+    for (const DisplayWrapper display : mAllDisplays) {
+        for (ColorMode mode : mDisplayProperties.at(display.getDisplayId()).testColorModes) {
+            auto status = mComposerClient->setColorMode(display.getDisplayId(), mode,
                                                         RenderIntent::COLORIMETRIC);
+
+            auto [dataspace, readbackSupported] =
+                    GetDataspaceAndIfReadBackSupported(display.getDisplayId());
+            if (!readbackSupported) {
+                continue;
+            }
+
             if (!status.isOk() && status.getExceptionCode() == EX_SERVICE_SPECIFIC &&
                 (status.getServiceSpecificError() == IComposerClient::EX_UNSUPPORTED ||
                  status.getServiceSpecificError() == IComposerClient::EX_BAD_PARAMETER)) {
                 ALOGI("ColorMode not supported on Display %" PRId64 " for ColorMode %d",
-                      display->getDisplayId(), mode);
+                      display.getDisplayId(), mode);
                 continue;
             }
 
-            ReadbackBuffer readbackBuffer(
-                    display->getDisplayId(), mComposerClient, display->getDisplayWidth(),
-                    display->getDisplayHeight(),
-                    mDisplayProperties.at(display->getDisplayId()).pixelFormat,
-                    mDisplayProperties.at(display->getDisplayId()).dataspace);
+            ReadbackBuffer readbackBuffer(display.getDisplayId(), mComposerClient,
+                                          display.getDisplayWidth(), display.getDisplayHeight(),
+                                          mDisplayProperties.at(display.getDisplayId()).pixelFormat,
+                                          dataspace);
             ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
-            auto& bufferLayer = mDisplayGfx[display->getDisplayId()].bufferLayer;
+            auto& bufferLayer = mDisplayGfx[display.getDisplayId()].bufferLayer;
             bufferLayer->setTransform(Transform::FLIP_H);
             bufferLayer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode));
 
             std::vector<Color> expectedColors(
-                    static_cast<size_t>(display->getDisplayWidth() * display->getDisplayHeight()));
-            int& sideLength = mDisplayGfx[display->getDisplayId()].sideLength;
-            ReadbackHelper::fillColorsArea(expectedColors, display->getDisplayWidth(),
+                    static_cast<size_t>(display.getDisplayWidth() * display.getDisplayHeight()));
+            int& sideLength = mDisplayGfx[display.getDisplayId()].sideLength;
+            ReadbackHelper::fillColorsArea(expectedColors, display.getDisplayWidth(),
                                            {sideLength / 2, 0, sideLength, sideLength / 2}, RED);
-            ReadbackHelper::fillColorsArea(expectedColors, display->getDisplayWidth(),
+            ReadbackHelper::fillColorsArea(expectedColors, display.getDisplayWidth(),
                                            {0, sideLength / 2, sideLength / 2, sideLength}, BLUE);
 
-            auto& layers = mDisplayGfx[display->getDisplayId()].layers;
-            writeLayers(layers, display->getDisplayId());
-            ASSERT_TRUE(mDisplayProperties.at(display->getDisplayId()).reader.takeErrors().empty());
-            mDisplayProperties.at(display->getDisplayId())
-                    .writer.validateDisplay(display->getDisplayId(),
+            auto& layers = mDisplayGfx[display.getDisplayId()].layers;
+            writeLayers(layers, display.getDisplayId());
+            ASSERT_TRUE(mDisplayProperties.at(display.getDisplayId()).reader.takeErrors().empty());
+            mDisplayProperties.at(display.getDisplayId())
+                    .writer.validateDisplay(display.getDisplayId(),
                                             ComposerClientWriter::kNoTimestamp,
                                             ComposerClientWrapper::kNoFrameIntervalNs);
-            execute(display->getDisplayId());
-            if (!mDisplayProperties.at(display->getDisplayId())
-                         .reader.takeChangedCompositionTypes(display->getDisplayId())
+            execute(display.getDisplayId());
+            if (!mDisplayProperties.at(display.getDisplayId())
+                         .reader.takeChangedCompositionTypes(display.getDisplayId())
                          .empty()) {
                 continue;
             }
-            ASSERT_TRUE(mDisplayProperties.at(display->getDisplayId()).reader.takeErrors().empty());
-            mDisplayProperties.at(display->getDisplayId())
-                    .writer.presentDisplay(display->getDisplayId());
-            execute(display->getDisplayId());
-            ASSERT_TRUE(mDisplayProperties.at(display->getDisplayId()).reader.takeErrors().empty());
+            ASSERT_TRUE(mDisplayProperties.at(display.getDisplayId()).reader.takeErrors().empty());
+            mDisplayProperties.at(display.getDisplayId())
+                    .writer.presentDisplay(display.getDisplayId());
+            execute(display.getDisplayId());
+            ASSERT_TRUE(mDisplayProperties.at(display.getDisplayId()).reader.takeErrors().empty());
 
             ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
-            auto& testRenderEngine =
-                    mDisplayProperties.at(display->getDisplayId()).testRenderEngine;
+            auto& testRenderEngine = mDisplayProperties.at(display.getDisplayId()).testRenderEngine;
             testRenderEngine->setRenderLayers(layers);
             ASSERT_NO_FATAL_FAILURE(testRenderEngine->drawLayers());
             ASSERT_NO_FATAL_FAILURE(testRenderEngine->checkColorBuffer(expectedColors));
@@ -1718,53 +1815,57 @@
 }
 
 TEST_P(GraphicsTransformCompositionTest, FLIP_V) {
-    for (const DisplayWrapper* display : mDisplaysWithReadbackBuffers) {
-        for (ColorMode mode : mDisplayProperties.at(display->getDisplayId()).testColorModes) {
-            EXPECT_TRUE(mComposerClient
-                                ->setColorMode(display->getDisplayId(), mode,
-                                               RenderIntent::COLORIMETRIC)
-                                .isOk());
+    for (const DisplayWrapper display : mAllDisplays) {
+        for (ColorMode mode : mDisplayProperties.at(display.getDisplayId()).testColorModes) {
+            EXPECT_TRUE(
+                    mComposerClient
+                            ->setColorMode(display.getDisplayId(), mode, RenderIntent::COLORIMETRIC)
+                            .isOk());
 
-            ReadbackBuffer readbackBuffer(
-                    display->getDisplayId(), mComposerClient, display->getDisplayWidth(),
-                    display->getDisplayHeight(),
-                    mDisplayProperties.at(display->getDisplayId()).pixelFormat,
-                    mDisplayProperties.at(display->getDisplayId()).dataspace);
+            auto [dataspace, readbackSupported] =
+                    GetDataspaceAndIfReadBackSupported(display.getDisplayId());
+            if (!readbackSupported) {
+                continue;
+            }
+
+            ReadbackBuffer readbackBuffer(display.getDisplayId(), mComposerClient,
+                                          display.getDisplayWidth(), display.getDisplayHeight(),
+                                          mDisplayProperties.at(display.getDisplayId()).pixelFormat,
+                                          dataspace);
             ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
 
-            auto& bufferLayer = mDisplayGfx[display->getDisplayId()].bufferLayer;
+            auto& bufferLayer = mDisplayGfx[display.getDisplayId()].bufferLayer;
             bufferLayer->setTransform(Transform::FLIP_V);
             bufferLayer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode));
 
             std::vector<Color> expectedColors(
-                    static_cast<size_t>(display->getDisplayWidth() * display->getDisplayHeight()));
-            int& sideLength = mDisplayGfx[display->getDisplayId()].sideLength;
-            ReadbackHelper::fillColorsArea(expectedColors, display->getDisplayWidth(),
+                    static_cast<size_t>(display.getDisplayWidth() * display.getDisplayHeight()));
+            int& sideLength = mDisplayGfx[display.getDisplayId()].sideLength;
+            ReadbackHelper::fillColorsArea(expectedColors, display.getDisplayWidth(),
                                            {0, sideLength / 2, sideLength / 2, sideLength}, RED);
-            ReadbackHelper::fillColorsArea(expectedColors, display->getDisplayWidth(),
+            ReadbackHelper::fillColorsArea(expectedColors, display.getDisplayWidth(),
                                            {sideLength / 2, 0, sideLength, sideLength / 2}, BLUE);
 
-            auto& layers = mDisplayGfx[display->getDisplayId()].layers;
-            writeLayers(layers, display->getDisplayId());
-            ASSERT_TRUE(mDisplayProperties.at(display->getDisplayId()).reader.takeErrors().empty());
-            mDisplayProperties.at(display->getDisplayId())
-                    .writer.validateDisplay(display->getDisplayId(),
+            auto& layers = mDisplayGfx[display.getDisplayId()].layers;
+            writeLayers(layers, display.getDisplayId());
+            ASSERT_TRUE(mDisplayProperties.at(display.getDisplayId()).reader.takeErrors().empty());
+            mDisplayProperties.at(display.getDisplayId())
+                    .writer.validateDisplay(display.getDisplayId(),
                                             ComposerClientWriter::kNoTimestamp,
                                             ComposerClientWrapper::kNoFrameIntervalNs);
-            execute(display->getDisplayId());
-            if (!mDisplayProperties.at(display->getDisplayId())
-                         .reader.takeChangedCompositionTypes(display->getDisplayId())
+            execute(display.getDisplayId());
+            if (!mDisplayProperties.at(display.getDisplayId())
+                         .reader.takeChangedCompositionTypes(display.getDisplayId())
                          .empty()) {
                 continue;
             }
-            ASSERT_TRUE(mDisplayProperties.at(display->getDisplayId()).reader.takeErrors().empty());
-            mDisplayProperties.at(display->getDisplayId())
-                    .writer.presentDisplay(display->getDisplayId());
-            execute(display->getDisplayId());
-            ASSERT_TRUE(mDisplayProperties.at(display->getDisplayId()).reader.takeErrors().empty());
+            ASSERT_TRUE(mDisplayProperties.at(display.getDisplayId()).reader.takeErrors().empty());
+            mDisplayProperties.at(display.getDisplayId())
+                    .writer.presentDisplay(display.getDisplayId());
+            execute(display.getDisplayId());
+            ASSERT_TRUE(mDisplayProperties.at(display.getDisplayId()).reader.takeErrors().empty());
             ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
-            auto& testRenderEngine =
-                    mDisplayProperties.at(display->getDisplayId()).testRenderEngine;
+            auto& testRenderEngine = mDisplayProperties.at(display.getDisplayId()).testRenderEngine;
             testRenderEngine->setRenderLayers(layers);
             ASSERT_NO_FATAL_FAILURE(testRenderEngine->drawLayers());
             ASSERT_NO_FATAL_FAILURE(testRenderEngine->checkColorBuffer(expectedColors));
@@ -1773,55 +1874,59 @@
 }
 
 TEST_P(GraphicsTransformCompositionTest, ROT_180) {
-    for (const DisplayWrapper* display : mDisplaysWithReadbackBuffers) {
-        for (ColorMode mode : mDisplayProperties.at(display->getDisplayId()).testColorModes) {
-            EXPECT_TRUE(mComposerClient
-                                ->setColorMode(display->getDisplayId(), mode,
-                                               RenderIntent::COLORIMETRIC)
-                                .isOk());
+    for (const DisplayWrapper display : mAllDisplays) {
+        for (ColorMode mode : mDisplayProperties.at(display.getDisplayId()).testColorModes) {
+            EXPECT_TRUE(
+                    mComposerClient
+                            ->setColorMode(display.getDisplayId(), mode, RenderIntent::COLORIMETRIC)
+                            .isOk());
 
-            ReadbackBuffer readbackBuffer(
-                    display->getDisplayId(), mComposerClient, display->getDisplayWidth(),
-                    display->getDisplayHeight(),
-                    mDisplayProperties.at(display->getDisplayId()).pixelFormat,
-                    mDisplayProperties.at(display->getDisplayId()).dataspace);
+            auto [dataspace, readbackSupported] =
+                    GetDataspaceAndIfReadBackSupported(display.getDisplayId());
+            if (!readbackSupported) {
+                continue;
+            }
+
+            ReadbackBuffer readbackBuffer(display.getDisplayId(), mComposerClient,
+                                          display.getDisplayWidth(), display.getDisplayHeight(),
+                                          mDisplayProperties.at(display.getDisplayId()).pixelFormat,
+                                          dataspace);
             ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
 
-            auto& bufferLayer = mDisplayGfx[display->getDisplayId()].bufferLayer;
+            auto& bufferLayer = mDisplayGfx[display.getDisplayId()].bufferLayer;
             bufferLayer->setTransform(Transform::ROT_180);
             bufferLayer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode));
 
             std::vector<Color> expectedColors(
-                    static_cast<size_t>(display->getDisplayWidth() * display->getDisplayHeight()));
-            int& sideLength = mDisplayGfx[display->getDisplayId()].sideLength;
-            ReadbackHelper::fillColorsArea(expectedColors, display->getDisplayWidth(),
+                    static_cast<size_t>(display.getDisplayWidth() * display.getDisplayHeight()));
+            int& sideLength = mDisplayGfx[display.getDisplayId()].sideLength;
+            ReadbackHelper::fillColorsArea(expectedColors, display.getDisplayWidth(),
                                            {sideLength / 2, sideLength / 2, sideLength, sideLength},
                                            RED);
-            ReadbackHelper::fillColorsArea(expectedColors, display->getDisplayWidth(),
+            ReadbackHelper::fillColorsArea(expectedColors, display.getDisplayWidth(),
                                            {0, 0, sideLength / 2, sideLength / 2}, BLUE);
 
-            auto& layers = mDisplayGfx[display->getDisplayId()].layers;
-            writeLayers(layers, display->getDisplayId());
-            ASSERT_TRUE(mDisplayProperties.at(display->getDisplayId()).reader.takeErrors().empty());
-            mDisplayProperties.at(display->getDisplayId())
-                    .writer.validateDisplay(display->getDisplayId(),
+            auto& layers = mDisplayGfx[display.getDisplayId()].layers;
+            writeLayers(layers, display.getDisplayId());
+            ASSERT_TRUE(mDisplayProperties.at(display.getDisplayId()).reader.takeErrors().empty());
+            mDisplayProperties.at(display.getDisplayId())
+                    .writer.validateDisplay(display.getDisplayId(),
                                             ComposerClientWriter::kNoTimestamp,
                                             ComposerClientWrapper::kNoFrameIntervalNs);
-            execute(display->getDisplayId());
-            if (!mDisplayProperties.at(display->getDisplayId())
-                         .reader.takeChangedCompositionTypes(display->getDisplayId())
+            execute(display.getDisplayId());
+            if (!mDisplayProperties.at(display.getDisplayId())
+                         .reader.takeChangedCompositionTypes(display.getDisplayId())
                          .empty()) {
                 continue;
             }
-            ASSERT_TRUE(mDisplayProperties.at(display->getDisplayId()).reader.takeErrors().empty());
-            mDisplayProperties.at(display->getDisplayId())
-                    .writer.presentDisplay(display->getDisplayId());
-            execute(display->getDisplayId());
-            ASSERT_TRUE(mDisplayProperties.at(display->getDisplayId()).reader.takeErrors().empty());
+            ASSERT_TRUE(mDisplayProperties.at(display.getDisplayId()).reader.takeErrors().empty());
+            mDisplayProperties.at(display.getDisplayId())
+                    .writer.presentDisplay(display.getDisplayId());
+            execute(display.getDisplayId());
+            ASSERT_TRUE(mDisplayProperties.at(display.getDisplayId()).reader.takeErrors().empty());
 
             ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
-            auto& testRenderEngine =
-                    mDisplayProperties.at(display->getDisplayId()).testRenderEngine;
+            auto& testRenderEngine = mDisplayProperties.at(display.getDisplayId()).testRenderEngine;
             testRenderEngine->setRenderLayers(layers);
             ASSERT_NO_FATAL_FAILURE(testRenderEngine->drawLayers());
             ASSERT_NO_FATAL_FAILURE(testRenderEngine->checkColorBuffer(expectedColors));
@@ -1888,59 +1993,63 @@
 
 // @VsrTest = 4.4-015
 TEST_P(GraphicsColorManagementCompositionTest, ColorConversion) {
-    for (const DisplayWrapper* display : mDisplaysWithReadbackBuffers) {
-        for (ColorMode mode : mDisplayProperties.at(display->getDisplayId()).testColorModes) {
-            EXPECT_TRUE(mComposerClient
-                                ->setColorMode(display->getDisplayId(), mode,
-                                               RenderIntent::COLORIMETRIC)
-                                .isOk());
+    for (const DisplayWrapper display : mAllDisplays) {
+        for (ColorMode mode : mDisplayProperties.at(display.getDisplayId()).testColorModes) {
+            EXPECT_TRUE(
+                    mComposerClient
+                            ->setColorMode(display.getDisplayId(), mode, RenderIntent::COLORIMETRIC)
+                            .isOk());
+
+            auto [dataspace, readbackSupported] =
+                    GetDataspaceAndIfReadBackSupported(display.getDisplayId());
+            if (!readbackSupported) {
+                continue;
+            }
 
             auto& clientCompositionDisplaySettings =
-                    mDisplayProperties.at(display->getDisplayId()).clientCompositionDisplaySettings;
+                    mDisplayProperties.at(display.getDisplayId()).clientCompositionDisplaySettings;
             clientCompositionDisplaySettings.outputDataspace =
-                    static_cast<::android::ui::Dataspace>(
-                            mDisplayProperties.at(display->getDisplayId()).dataspace);
-            mDisplayProperties.at(display->getDisplayId())
+                    static_cast<::android::ui::Dataspace>(dataspace);
+            mDisplayProperties.at(display.getDisplayId())
                     .testRenderEngine->setDisplaySettings(clientCompositionDisplaySettings);
 
-            makeLayer(*display);
+            makeLayer(display);
             for (auto color : {LIGHT_RED, LIGHT_GREEN, LIGHT_BLUE}) {
                 ALOGD("Testing color: %f, %f, %f, %f with color mode: %d", color.r, color.g,
                       color.b, color.a, mode);
                 ReadbackBuffer readbackBuffer(
-                        display->getDisplayId(), mComposerClient, display->getDisplayWidth(),
-                        display->getDisplayHeight(),
-                        mDisplayProperties.at(display->getDisplayId()).pixelFormat,
-                        mDisplayProperties.at(display->getDisplayId()).dataspace);
+                        display.getDisplayId(), mComposerClient, display.getDisplayWidth(),
+                        display.getDisplayHeight(),
+                        mDisplayProperties.at(display.getDisplayId()).pixelFormat, dataspace);
                 ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
-                fillColor(*display, color);
-                auto& layer = mDisplayGfx[display->getDisplayId()].layer;
-                writeLayers({layer}, display->getDisplayId());
-                EXPECT_TRUE(mComposerClient->setPowerMode(display->getDisplayId(), PowerMode::ON)
+                fillColor(display, color);
+                auto& layer = mDisplayGfx[display.getDisplayId()].layer;
+                writeLayers({layer}, display.getDisplayId());
+                EXPECT_TRUE(mComposerClient->setPowerMode(display.getDisplayId(), PowerMode::ON)
                                     .isOk());
 
                 ASSERT_TRUE(
-                        mDisplayProperties.at(display->getDisplayId()).reader.takeErrors().empty());
-                mDisplayProperties.at(display->getDisplayId())
-                        .writer.validateDisplay(display->getDisplayId(),
+                        mDisplayProperties.at(display.getDisplayId()).reader.takeErrors().empty());
+                mDisplayProperties.at(display.getDisplayId())
+                        .writer.validateDisplay(display.getDisplayId(),
                                                 ComposerClientWriter::kNoTimestamp,
                                                 ComposerClientWrapper::kNoFrameIntervalNs);
-                execute(display->getDisplayId());
-                if (!mDisplayProperties.at(display->getDisplayId())
-                             .reader.takeChangedCompositionTypes(display->getDisplayId())
+                execute(display.getDisplayId());
+                if (!mDisplayProperties.at(display.getDisplayId())
+                             .reader.takeChangedCompositionTypes(display.getDisplayId())
                              .empty()) {
                     continue;
                 }
                 ASSERT_TRUE(
-                        mDisplayProperties.at(display->getDisplayId()).reader.takeErrors().empty());
-                mDisplayProperties.at(display->getDisplayId())
-                        .writer.presentDisplay(display->getDisplayId());
-                execute(display->getDisplayId());
+                        mDisplayProperties.at(display.getDisplayId()).reader.takeErrors().empty());
+                mDisplayProperties.at(display.getDisplayId())
+                        .writer.presentDisplay(display.getDisplayId());
+                execute(display.getDisplayId());
                 ASSERT_TRUE(
-                        mDisplayProperties.at(display->getDisplayId()).reader.takeErrors().empty());
+                        mDisplayProperties.at(display.getDisplayId()).reader.takeErrors().empty());
 
                 auto& testRenderEngine =
-                        mDisplayProperties.at(display->getDisplayId()).testRenderEngine;
+                        mDisplayProperties.at(display.getDisplayId()).testRenderEngine;
                 testRenderEngine->setRenderLayers({layer});
                 ASSERT_NO_FATAL_FAILURE(testRenderEngine->drawLayers());
                 ASSERT_NO_FATAL_FAILURE(
diff --git a/radio/aidl/vts/radio_aidl_hal_utils.h b/radio/aidl/vts/radio_aidl_hal_utils.h
index d9c7311..3e2e633 100644
--- a/radio/aidl/vts/radio_aidl_hal_utils.h
+++ b/radio/aidl/vts/radio_aidl_hal_utils.h
@@ -65,8 +65,6 @@
 
 static constexpr const char* FEATURE_TELEPHONY = "android.hardware.telephony";
 
-static constexpr const char* FEATURE_TELEPHONY_CDMA = "android.hardware.telephony.cdma";
-
 static constexpr const char* FEATURE_TELEPHONY_IMS = "android.hardware.telephony.ims";
 
 static constexpr const char* FEATURE_TELEPHONY_CALLING = "android.hardware.telephony.calling";
diff --git a/radio/aidl/vts/radio_messaging_test.cpp b/radio/aidl/vts/radio_messaging_test.cpp
index 089895f..7e4ef96 100644
--- a/radio/aidl/vts/radio_messaging_test.cpp
+++ b/radio/aidl/vts/radio_messaging_test.cpp
@@ -113,104 +113,6 @@
 }
 
 /*
- * Test IRadioMessaging.sendCdmaSms() for the response returned.
- */
-TEST_P(RadioMessagingTest, sendCdmaSms) {
-    if (!deviceSupportsFeature(FEATURE_TELEPHONY_CDMA)) {
-        GTEST_SKIP() << "Skipping sendCdmaSms "
-                        "due to undefined FEATURE_TELEPHONY_CDMA";
-    }
-
-    serial = GetRandomSerialNumber();
-
-    // Create a CdmaSmsAddress
-    CdmaSmsAddress cdmaSmsAddress;
-    cdmaSmsAddress.digitMode = CdmaSmsAddress::DIGIT_MODE_FOUR_BIT;
-    cdmaSmsAddress.isNumberModeDataNetwork = false;
-    cdmaSmsAddress.numberType = CdmaSmsAddress::NUMBER_TYPE_UNKNOWN;
-    cdmaSmsAddress.numberPlan = CdmaSmsAddress::NUMBER_PLAN_UNKNOWN;
-    cdmaSmsAddress.digits = (std::vector<uint8_t>){11, 1, 6, 5, 10, 7, 7, 2, 10, 3, 10, 3};
-
-    // Create a CdmaSmsSubAddress
-    CdmaSmsSubaddress cdmaSmsSubaddress;
-    cdmaSmsSubaddress.subaddressType = CdmaSmsSubaddress::SUBADDRESS_TYPE_NSAP;
-    cdmaSmsSubaddress.odd = false;
-    cdmaSmsSubaddress.digits = (std::vector<uint8_t>){};
-
-    // Create a CdmaSmsMessage
-    CdmaSmsMessage cdmaSmsMessage;
-    cdmaSmsMessage.teleserviceId = 4098;
-    cdmaSmsMessage.isServicePresent = false;
-    cdmaSmsMessage.serviceCategory = 0;
-    cdmaSmsMessage.address = cdmaSmsAddress;
-    cdmaSmsMessage.subAddress = cdmaSmsSubaddress;
-    cdmaSmsMessage.bearerData =
-            (std::vector<uint8_t>){15, 0, 3, 32, 3, 16, 1, 8, 16, 53, 76, 68, 6, 51, 106, 0};
-
-    radio_messaging->sendCdmaSms(serial, cdmaSmsMessage);
-
-    EXPECT_EQ(std::cv_status::no_timeout, wait());
-    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_messaging->rspInfo.type);
-    EXPECT_EQ(serial, radioRsp_messaging->rspInfo.serial);
-
-    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
-        ASSERT_TRUE(CheckAnyOfErrors(
-                radioRsp_messaging->rspInfo.error,
-                {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE, RadioError::SIM_ABSENT},
-                CHECK_GENERAL_ERROR));
-    }
-}
-
-/*
- * Test IRadioMessaging.sendCdmaSmsExpectMore() for the response returned.
- */
-TEST_P(RadioMessagingTest, sendCdmaSmsExpectMore) {
-    if (!deviceSupportsFeature(FEATURE_TELEPHONY_CDMA)) {
-        GTEST_SKIP() << "Skipping sendCdmaSmsExpectMore "
-                        "due to undefined FEATURE_TELEPHONY_CDMA";
-    }
-
-    serial = GetRandomSerialNumber();
-
-    // Create a CdmaSmsAddress
-    CdmaSmsAddress cdmaSmsAddress;
-    cdmaSmsAddress.digitMode = CdmaSmsAddress::DIGIT_MODE_FOUR_BIT;
-    cdmaSmsAddress.isNumberModeDataNetwork = false;
-    cdmaSmsAddress.numberType = CdmaSmsAddress::NUMBER_TYPE_UNKNOWN;
-    cdmaSmsAddress.numberPlan = CdmaSmsAddress::NUMBER_PLAN_UNKNOWN;
-    cdmaSmsAddress.digits = (std::vector<uint8_t>){11, 1, 6, 5, 10, 7, 7, 2, 10, 3, 10, 3};
-
-    // Create a CdmaSmsSubAddress
-    CdmaSmsSubaddress cdmaSmsSubaddress;
-    cdmaSmsSubaddress.subaddressType = CdmaSmsSubaddress::SUBADDRESS_TYPE_NSAP;
-    cdmaSmsSubaddress.odd = false;
-    cdmaSmsSubaddress.digits = (std::vector<uint8_t>){};
-
-    // Create a CdmaSmsMessage
-    CdmaSmsMessage cdmaSmsMessage;
-    cdmaSmsMessage.teleserviceId = 4098;
-    cdmaSmsMessage.isServicePresent = false;
-    cdmaSmsMessage.serviceCategory = 0;
-    cdmaSmsMessage.address = cdmaSmsAddress;
-    cdmaSmsMessage.subAddress = cdmaSmsSubaddress;
-    cdmaSmsMessage.bearerData =
-            (std::vector<uint8_t>){15, 0, 3, 32, 3, 16, 1, 8, 16, 53, 76, 68, 6, 51, 106, 0};
-
-    radio_messaging->sendCdmaSmsExpectMore(serial, cdmaSmsMessage);
-
-    EXPECT_EQ(std::cv_status::no_timeout, wait());
-    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_messaging->rspInfo.type);
-    EXPECT_EQ(serial, radioRsp_messaging->rspInfo.serial);
-
-    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
-        ASSERT_TRUE(CheckAnyOfErrors(
-                radioRsp_messaging->rspInfo.error,
-                {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE, RadioError::SIM_ABSENT},
-                CHECK_GENERAL_ERROR));
-    }
-}
-
-/*
  * Test IRadioMessaging.setGsmBroadcastConfig() for the response returned.
  */
 TEST_P(RadioMessagingTest, setGsmBroadcastConfig) {
@@ -304,85 +206,6 @@
 }
 
 /*
- * Test IRadioMessaging.setCdmaBroadcastConfig() for the response returned.
- */
-TEST_P(RadioMessagingTest, setCdmaBroadcastConfig) {
-    if (!deviceSupportsFeature(FEATURE_TELEPHONY_CDMA)) {
-        GTEST_SKIP() << "Skipping setCdmaBroadcastConfig "
-                        "due to undefined FEATURE_TELEPHONY_CDMA";
-    }
-
-    serial = GetRandomSerialNumber();
-
-    CdmaBroadcastSmsConfigInfo cbSmsConfig;
-    cbSmsConfig.serviceCategory = 4096;
-    cbSmsConfig.language = 1;
-    cbSmsConfig.selected = true;
-
-    std::vector<CdmaBroadcastSmsConfigInfo> cdmaBroadcastSmsConfigInfoList = {cbSmsConfig};
-
-    radio_messaging->setCdmaBroadcastConfig(serial, cdmaBroadcastSmsConfigInfoList);
-
-    EXPECT_EQ(std::cv_status::no_timeout, wait());
-    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_messaging->rspInfo.type);
-    EXPECT_EQ(serial, radioRsp_messaging->rspInfo.serial);
-
-    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
-        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_messaging->rspInfo.error,
-                                     {RadioError::NONE, RadioError::INVALID_MODEM_STATE},
-                                     CHECK_GENERAL_ERROR));
-    }
-}
-
-/*
- * Test IRadioMessaging.getCdmaBroadcastConfig() for the response returned.
- */
-TEST_P(RadioMessagingTest, getCdmaBroadcastConfig) {
-    if (!deviceSupportsFeature(FEATURE_TELEPHONY_CDMA)) {
-        GTEST_SKIP() << "Skipping getCdmaBroadcastConfig "
-                        "due to undefined FEATURE_TELEPHONY_CDMA";
-    }
-
-    serial = GetRandomSerialNumber();
-
-    radio_messaging->getCdmaBroadcastConfig(serial);
-
-    EXPECT_EQ(std::cv_status::no_timeout, wait());
-    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_messaging->rspInfo.type);
-    EXPECT_EQ(serial, radioRsp_messaging->rspInfo.serial);
-
-    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
-        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_messaging->rspInfo.error, {RadioError::NONE},
-                                     CHECK_GENERAL_ERROR));
-    }
-}
-
-/*
- * Test IRadioMessaging.setCdmaBroadcastActivation() for the response returned.
- */
-TEST_P(RadioMessagingTest, setCdmaBroadcastActivation) {
-    if (!deviceSupportsFeature(FEATURE_TELEPHONY_CDMA)) {
-        GTEST_SKIP() << "Skipping setCdmaBroadcastActivation "
-                        "due to undefined FEATURE_TELEPHONY_CDMA";
-    }
-
-    serial = GetRandomSerialNumber();
-    bool activate = false;
-
-    radio_messaging->setCdmaBroadcastActivation(serial, activate);
-
-    EXPECT_EQ(std::cv_status::no_timeout, wait());
-    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_messaging->rspInfo.type);
-    EXPECT_EQ(serial, radioRsp_messaging->rspInfo.serial);
-
-    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
-        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_messaging->rspInfo.error,
-                                     {RadioError::NONE, RadioError::INVALID_ARGUMENTS},
-                                     CHECK_GENERAL_ERROR));
-    }
-}
-
-/*
  * Test IRadioMessaging.setGsmBroadcastActivation() for the response returned.
  */
 TEST_P(RadioMessagingTest, setGsmBroadcastActivation) {
@@ -462,35 +285,6 @@
 }
 
 /*
- * Test IRadioMessaging.acknowledgeLastIncomingCdmaSms() for the response returned.
- */
-TEST_P(RadioMessagingTest, acknowledgeLastIncomingCdmaSms) {
-    if (!deviceSupportsFeature(FEATURE_TELEPHONY_CDMA)) {
-        GTEST_SKIP() << "Skipping acknowledgeIncomingGsmSmsWithPdu "
-                        "due to undefined FEATURE_TELEPHONY_CDMA";
-    }
-
-    serial = GetRandomSerialNumber();
-
-    // Create a CdmaSmsAck
-    CdmaSmsAck cdmaSmsAck;
-    cdmaSmsAck.errorClass = false;
-    cdmaSmsAck.smsCauseCode = 1;
-
-    radio_messaging->acknowledgeLastIncomingCdmaSms(serial, cdmaSmsAck);
-
-    EXPECT_EQ(std::cv_status::no_timeout, wait());
-    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_messaging->rspInfo.type);
-    EXPECT_EQ(serial, radioRsp_messaging->rspInfo.serial);
-
-    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
-        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_messaging->rspInfo.error,
-                                     {RadioError::INVALID_ARGUMENTS, RadioError::NO_SMS_TO_ACK},
-                                     CHECK_GENERAL_ERROR));
-    }
-}
-
-/*
  * Test IRadioMessaging.sendImsSms() for the response returned.
  */
 TEST_P(RadioMessagingTest, sendImsSms) {
@@ -656,118 +450,6 @@
 }
 
 /*
- * Test IRadioMessaging.writeSmsToRuim() for the response returned.
- */
-TEST_P(RadioMessagingTest, writeSmsToRuim) {
-    if (!deviceSupportsFeature(FEATURE_TELEPHONY_CDMA)) {
-        GTEST_SKIP() << "Skipping writeSmsToRuim "
-                        "due to undefined FEATURE_TELEPHONY_CDMA";
-    }
-
-    serial = GetRandomSerialNumber();
-
-    // Create a CdmaSmsAddress
-    CdmaSmsAddress cdmaSmsAddress;
-    cdmaSmsAddress.digitMode = CdmaSmsAddress::DIGIT_MODE_FOUR_BIT;
-    cdmaSmsAddress.isNumberModeDataNetwork = false;
-    cdmaSmsAddress.numberType = CdmaSmsAddress::NUMBER_TYPE_UNKNOWN;
-    cdmaSmsAddress.numberPlan = CdmaSmsAddress::NUMBER_PLAN_UNKNOWN;
-    cdmaSmsAddress.digits = (std::vector<uint8_t>){11, 1, 6, 5, 10, 7, 7, 2, 10, 3, 10, 3};
-
-    // Create a CdmaSmsSubAddress
-    CdmaSmsSubaddress cdmaSmsSubaddress;
-    cdmaSmsSubaddress.subaddressType = CdmaSmsSubaddress::SUBADDRESS_TYPE_NSAP;
-    cdmaSmsSubaddress.odd = false;
-    cdmaSmsSubaddress.digits = (std::vector<uint8_t>){};
-
-    // Create a CdmaSmsMessage
-    CdmaSmsMessage cdmaSmsMessage;
-    cdmaSmsMessage.teleserviceId = 4098;
-    cdmaSmsMessage.isServicePresent = false;
-    cdmaSmsMessage.serviceCategory = 0;
-    cdmaSmsMessage.address = cdmaSmsAddress;
-    cdmaSmsMessage.subAddress = cdmaSmsSubaddress;
-    cdmaSmsMessage.bearerData =
-            (std::vector<uint8_t>){15, 0, 3, 32, 3, 16, 1, 8, 16, 53, 76, 68, 6, 51, 106, 0};
-
-    // Create a CdmaSmsWriteArgs
-    CdmaSmsWriteArgs cdmaSmsWriteArgs;
-    cdmaSmsWriteArgs.status = CdmaSmsWriteArgs::STATUS_REC_UNREAD;
-    cdmaSmsWriteArgs.message = cdmaSmsMessage;
-
-    radio_messaging->writeSmsToRuim(serial, cdmaSmsWriteArgs);
-
-    EXPECT_EQ(std::cv_status::no_timeout, wait());
-    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_messaging->rspInfo.type);
-    EXPECT_EQ(serial, radioRsp_messaging->rspInfo.serial);
-
-    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
-        ASSERT_TRUE(CheckAnyOfErrors(
-                radioRsp_messaging->rspInfo.error,
-                {RadioError::NONE, RadioError::INVALID_ARGUMENTS, RadioError::INVALID_SMS_FORMAT,
-                 RadioError::INVALID_SMSC_ADDRESS, RadioError::INVALID_STATE, RadioError::MODEM_ERR,
-                 RadioError::NO_SUCH_ENTRY, RadioError::SIM_ABSENT},
-                CHECK_GENERAL_ERROR));
-    }
-}
-
-/*
- * Test IRadioMessaging.deleteSmsOnRuim() for the response returned.
- */
-TEST_P(RadioMessagingTest, deleteSmsOnRuim) {
-    if (!deviceSupportsFeature(FEATURE_TELEPHONY_CDMA)) {
-        GTEST_SKIP() << "Skipping deleteSmsOnRuim "
-                        "due to undefined FEATURE_TELEPHONY_CDMA";
-    }
-
-    serial = GetRandomSerialNumber();
-    int index = 1;
-
-    // Create a CdmaSmsAddress
-    CdmaSmsAddress cdmaSmsAddress;
-    cdmaSmsAddress.digitMode = CdmaSmsAddress::DIGIT_MODE_FOUR_BIT;
-    cdmaSmsAddress.isNumberModeDataNetwork = false;
-    cdmaSmsAddress.numberType = CdmaSmsAddress::NUMBER_TYPE_UNKNOWN;
-    cdmaSmsAddress.numberPlan = CdmaSmsAddress::NUMBER_PLAN_UNKNOWN;
-    cdmaSmsAddress.digits = (std::vector<uint8_t>){11, 1, 6, 5, 10, 7, 7, 2, 10, 3, 10, 3};
-
-    // Create a CdmaSmsSubAddress
-    CdmaSmsSubaddress cdmaSmsSubaddress;
-    cdmaSmsSubaddress.subaddressType = CdmaSmsSubaddress::SUBADDRESS_TYPE_NSAP;
-    cdmaSmsSubaddress.odd = false;
-    cdmaSmsSubaddress.digits = (std::vector<uint8_t>){};
-
-    // Create a CdmaSmsMessage
-    CdmaSmsMessage cdmaSmsMessage;
-    cdmaSmsMessage.teleserviceId = 4098;
-    cdmaSmsMessage.isServicePresent = false;
-    cdmaSmsMessage.serviceCategory = 0;
-    cdmaSmsMessage.address = cdmaSmsAddress;
-    cdmaSmsMessage.subAddress = cdmaSmsSubaddress;
-    cdmaSmsMessage.bearerData =
-            (std::vector<uint8_t>){15, 0, 3, 32, 3, 16, 1, 8, 16, 53, 76, 68, 6, 51, 106, 0};
-
-    // Create a CdmaSmsWriteArgs
-    CdmaSmsWriteArgs cdmaSmsWriteArgs;
-    cdmaSmsWriteArgs.status = CdmaSmsWriteArgs::STATUS_REC_UNREAD;
-    cdmaSmsWriteArgs.message = cdmaSmsMessage;
-
-    radio_messaging->deleteSmsOnRuim(serial, index);
-
-    EXPECT_EQ(std::cv_status::no_timeout, wait());
-    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_messaging->rspInfo.type);
-    EXPECT_EQ(serial, radioRsp_messaging->rspInfo.serial);
-
-    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
-        ASSERT_TRUE(CheckAnyOfErrors(
-                radioRsp_messaging->rspInfo.error,
-                {RadioError::NONE, RadioError::INVALID_ARGUMENTS, RadioError::INVALID_MODEM_STATE,
-                 RadioError::MODEM_ERR, RadioError::NO_SUCH_ENTRY, RadioError::SIM_ABSENT},
-                CHECK_GENERAL_ERROR));
-    }
-}
-
-/*
  * Test IRadioMessaging.reportSmsMemoryStatus() for the response returned.
  */
 TEST_P(RadioMessagingTest, reportSmsMemoryStatus) {
diff --git a/radio/aidl/vts/radio_modem_test.cpp b/radio/aidl/vts/radio_modem_test.cpp
index 9fb7db8..1c8a6f8 100644
--- a/radio/aidl/vts/radio_modem_test.cpp
+++ b/radio/aidl/vts/radio_modem_test.cpp
@@ -201,6 +201,13 @@
         GTEST_SKIP() << "Skipping getDeviceIdentity "
                         "due to undefined FEATURE_TELEPHONY";
     }
+    int32_t aidl_version;
+    ndk::ScopedAStatus aidl_status = radio_modem->getInterfaceVersion(&aidl_version);
+    ASSERT_OK(aidl_status);
+    if (aidl_version >= 4) {
+        ALOGI("Skipped the test since getDeviceIdentity is deprecated");
+        GTEST_SKIP();
+    }
 
     serial = GetRandomSerialNumber();
 
@@ -285,29 +292,6 @@
 }
 
 /*
- * Test IRadioModem.nvWriteCdmaPrl() for the response returned.
- */
-TEST_P(RadioModemTest, nvWriteCdmaPrl) {
-    if (!deviceSupportsFeature(FEATURE_TELEPHONY_CDMA)) {
-        GTEST_SKIP() << "Skipping nvWriteCdmaPrl "
-                        "due to undefined FEATURE_TELEPHONY_CDMA";
-    }
-
-    serial = GetRandomSerialNumber();
-    std::vector<uint8_t> prl = {1, 2, 3, 4, 5};
-
-    radio_modem->nvWriteCdmaPrl(serial, std::vector<uint8_t>(prl));
-    EXPECT_EQ(std::cv_status::no_timeout, wait());
-    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_modem->rspInfo.type);
-    EXPECT_EQ(serial, radioRsp_modem->rspInfo.serial);
-
-    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
-        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_modem->rspInfo.error, {RadioError::NONE},
-                                     CHECK_GENERAL_ERROR));
-    }
-}
-
-/*
  * Test IRadioModem.nvResetConfig() for the response returned.
  */
 TEST_P(RadioModemTest, nvResetConfig) {
diff --git a/radio/aidl/vts/radio_network_test.cpp b/radio/aidl/vts/radio_network_test.cpp
index ff231db..bdd4148 100644
--- a/radio/aidl/vts/radio_network_test.cpp
+++ b/radio/aidl/vts/radio_network_test.cpp
@@ -590,42 +590,6 @@
 }
 
 /*
- * Test IRadioNetwork.setSignalStrengthReportingCriteria() for CDMA2000
- */
-TEST_P(RadioNetworkTest, setSignalStrengthReportingCriteria_Cdma2000) {
-    if (!deviceSupportsFeature(FEATURE_TELEPHONY_RADIO_ACCESS)) {
-        GTEST_SKIP() << "Skipping setSignalStrengthReportingCriteria_Cdma2000 "
-                        "due to undefined FEATURE_TELEPHONY_RADIO_ACCESS";
-    }
-
-    if (!deviceSupportsFeature(FEATURE_TELEPHONY_CDMA)) {
-        GTEST_SKIP() << "Skipping setSignalStrengthReportingCriteria_Cdma2000 "
-                        "due to undefined FEATURE_TELEPHONY_CDMA";
-    }
-
-    serial = GetRandomSerialNumber();
-
-    SignalThresholdInfo signalThresholdInfo;
-    signalThresholdInfo.signalMeasurement = SignalThresholdInfo::SIGNAL_MEASUREMENT_TYPE_RSSI;
-    signalThresholdInfo.hysteresisMs = 5000;
-    signalThresholdInfo.hysteresisDb = 2;
-    signalThresholdInfo.thresholds = {-105, -90, -75, -65};
-    signalThresholdInfo.isEnabled = true;
-    signalThresholdInfo.ran = AccessNetwork::CDMA2000;
-
-    ndk::ScopedAStatus res =
-            radio_network->setSignalStrengthReportingCriteria(serial, {signalThresholdInfo});
-    ASSERT_OK(res);
-    EXPECT_EQ(std::cv_status::no_timeout, wait());
-    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
-    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
-
-    ALOGI("setSignalStrengthReportingCriteria_Cdma2000, rspInfo.error = %s\n",
-          toString(radioRsp_network->rspInfo.error).c_str());
-    ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error, {RadioError::NONE}));
-}
-
-/*
  * Test IRadioNetwork.setSignalStrengthReportingCriteria() for NGRAN_SSRSRP
  */
 TEST_P(RadioNetworkTest, setSignalStrengthReportingCriteria_NGRAN_SSRSRP) {
@@ -790,15 +754,6 @@
     signalThresholdInfoEutran.isEnabled = true;
     signalThresholdInfoEutran.ran = AccessNetwork::EUTRAN;
 
-    SignalThresholdInfo signalThresholdInfoCdma2000;
-    signalThresholdInfoCdma2000.signalMeasurement =
-            SignalThresholdInfo::SIGNAL_MEASUREMENT_TYPE_RSSI;
-    signalThresholdInfoCdma2000.hysteresisMs = 5000;
-    signalThresholdInfoCdma2000.hysteresisDb = 2;
-    signalThresholdInfoCdma2000.thresholds = {-105, -90, -75, -65};
-    signalThresholdInfoCdma2000.isEnabled = true;
-    signalThresholdInfoCdma2000.ran = AccessNetwork::CDMA2000;
-
     SignalThresholdInfo signalThresholdInfoNgran;
     signalThresholdInfoNgran.signalMeasurement =
             SignalThresholdInfo::SIGNAL_MEASUREMENT_TYPE_SSRSRP;
@@ -811,9 +766,6 @@
     std::vector<SignalThresholdInfo> candidateSignalThresholdInfos = {
             signalThresholdInfoGeran, signalThresholdInfoUtran, signalThresholdInfoEutran,
             signalThresholdInfoNgran};
-    if (deviceSupportsFeature(FEATURE_TELEPHONY_CDMA)) {
-        candidateSignalThresholdInfos.push_back(signalThresholdInfoCdma2000);
-    }
 
     std::vector<SignalThresholdInfo> supportedSignalThresholdInfos;
     for (size_t i = 0; i < candidateSignalThresholdInfos.size(); i++) {
@@ -2015,53 +1967,6 @@
 }
 
 /*
- * Test IRadioNetwork.setCdmaRoamingPreference() for the response returned.
- */
-TEST_P(RadioNetworkTest, setCdmaRoamingPreference) {
-    if (!deviceSupportsFeature(FEATURE_TELEPHONY_CDMA)) {
-        GTEST_SKIP() << "Skipping setCdmaRoamingPreference "
-                        "due to undefined FEATURE_TELEPHONY_CDMA";
-    }
-
-    serial = GetRandomSerialNumber();
-
-    radio_network->setCdmaRoamingPreference(serial, CdmaRoamingType::HOME_NETWORK);
-    EXPECT_EQ(std::cv_status::no_timeout, wait());
-    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
-    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
-
-    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
-        ASSERT_TRUE(CheckAnyOfErrors(
-                radioRsp_network->rspInfo.error,
-                {RadioError::NONE, RadioError::SIM_ABSENT, RadioError::REQUEST_NOT_SUPPORTED}));
-    }
-}
-
-/*
- * Test IRadioNetwork.getCdmaRoamingPreference() for the response returned.
- */
-TEST_P(RadioNetworkTest, getCdmaRoamingPreference) {
-    if (!deviceSupportsFeature(FEATURE_TELEPHONY_CDMA)) {
-        GTEST_SKIP() << "Skipping getCdmaRoamingPreference "
-                        "due to undefined FEATURE_TELEPHONY_CDMA";
-    }
-
-    serial = GetRandomSerialNumber();
-
-    radio_network->getCdmaRoamingPreference(serial);
-    EXPECT_EQ(std::cv_status::no_timeout, wait());
-    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
-    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
-
-    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
-        ASSERT_TRUE(
-                CheckAnyOfErrors(radioRsp_network->rspInfo.error,
-                                 {RadioError::NONE, RadioError::SIM_ABSENT, RadioError::MODEM_ERR},
-                                 CHECK_GENERAL_ERROR));
-    }
-}
-
-/*
  * Test IRadioNetwork.getVoiceRadioTechnology() for the response returned.
  */
 TEST_P(RadioNetworkTest, getVoiceRadioTechnology) {
diff --git a/radio/aidl/vts/radio_sim_test.cpp b/radio/aidl/vts/radio_sim_test.cpp
index e7c7c65..73beb57 100644
--- a/radio/aidl/vts/radio_sim_test.cpp
+++ b/radio/aidl/vts/radio_sim_test.cpp
@@ -1066,106 +1066,6 @@
 }
 
 /*
- * Test IRadioSim.getCdmaSubscription() for the response returned.
- */
-TEST_P(RadioSimTest, getCdmaSubscription) {
-    if (!deviceSupportsFeature(FEATURE_TELEPHONY_CDMA)) {
-        GTEST_SKIP() << "Skipping getCdmaSubscription "
-                        "due to undefined FEATURE_TELEPHONY_CDMA";
-    }
-
-    serial = GetRandomSerialNumber();
-
-    radio_sim->getCdmaSubscription(serial);
-    EXPECT_EQ(std::cv_status::no_timeout, wait());
-    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
-    EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
-
-    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
-        ASSERT_TRUE(CheckAnyOfErrors(
-                radioRsp_sim->rspInfo.error,
-                {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED, RadioError::SIM_ABSENT}));
-    }
-}
-
-/*
- * Test IRadioSim.getCdmaSubscriptionSource() for the response returned.
- */
-TEST_P(RadioSimTest, getCdmaSubscriptionSource) {
-    if (!deviceSupportsFeature(FEATURE_TELEPHONY_CDMA)) {
-        GTEST_SKIP() << "Skipping getCdmaSubscriptionSource "
-                        "due to undefined FEATURE_TELEPHONY_CDMA";
-    }
-
-    serial = GetRandomSerialNumber();
-
-    radio_sim->getCdmaSubscriptionSource(serial);
-    EXPECT_EQ(std::cv_status::no_timeout, wait());
-    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
-    EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
-
-    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
-        ASSERT_TRUE(CheckAnyOfErrors(
-                radioRsp_sim->rspInfo.error,
-                {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED, RadioError::SIM_ABSENT}));
-    }
-}
-
-/*
- * Test IRadioSim.setCdmaSubscriptionSource() for the response returned.
- */
-TEST_P(RadioSimTest, setCdmaSubscriptionSource) {
-    if (!deviceSupportsFeature(FEATURE_TELEPHONY_CDMA)) {
-        GTEST_SKIP() << "Skipping setCdmaSubscriptionSource "
-                        "due to undefined FEATURE_TELEPHONY_CDMA";
-    }
-
-    serial = GetRandomSerialNumber();
-
-    radio_sim->setCdmaSubscriptionSource(serial, CdmaSubscriptionSource::RUIM_SIM);
-    EXPECT_EQ(std::cv_status::no_timeout, wait());
-    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
-    EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
-
-    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
-        ASSERT_TRUE(CheckAnyOfErrors(
-                radioRsp_sim->rspInfo.error,
-                {RadioError::NONE, RadioError::SIM_ABSENT, RadioError::SUBSCRIPTION_NOT_AVAILABLE},
-                CHECK_GENERAL_ERROR));
-    }
-}
-
-/*
- * Test IRadioSim.setUiccSubscription() for the response returned.
- */
-TEST_P(RadioSimTest, setUiccSubscription) {
-    if (!shouldTestCdma()) {
-        GTEST_SKIP() << "Skipping CDMA testing (deprecated)";
-    }
-    if (!deviceSupportsFeature(FEATURE_TELEPHONY_SUBSCRIPTION)) {
-        GTEST_SKIP() << "Skipping setUiccSubscription "
-                        "due to undefined FEATURE_TELEPHONY_SUBSCRIPTION";
-    }
-
-    serial = GetRandomSerialNumber();
-    SelectUiccSub item;
-    memset(&item, 0, sizeof(item));
-
-    radio_sim->setUiccSubscription(serial, item);
-    EXPECT_EQ(std::cv_status::no_timeout, wait());
-    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
-    EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
-
-    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
-        ASSERT_TRUE(
-                CheckAnyOfErrors(radioRsp_sim->rspInfo.error,
-                                 {RadioError::NONE, RadioError::INVALID_ARGUMENTS,
-                                  RadioError::MODEM_ERR, RadioError::SUBSCRIPTION_NOT_SUPPORTED},
-                                 CHECK_GENERAL_ERROR));
-    }
-}
-
-/*
  * Test IRadioSim.sendEnvelope() for the response returned.
  */
 TEST_P(RadioSimTest, sendEnvelope) {
diff --git a/radio/aidl/vts/radio_voice_test.cpp b/radio/aidl/vts/radio_voice_test.cpp
index 9eb5bac..3df6bfb 100644
--- a/radio/aidl/vts/radio_voice_test.cpp
+++ b/radio/aidl/vts/radio_voice_test.cpp
@@ -821,31 +821,6 @@
 }
 
 /*
- * Test IRadioVoice.sendCdmaFeatureCode() for the response returned.
- */
-TEST_P(RadioVoiceTest, sendCdmaFeatureCode) {
-    if (!deviceSupportsFeature(FEATURE_TELEPHONY_CDMA)) {
-        GTEST_SKIP() << "Skipping sendCdmaFeatureCode "
-                        "due to undefined FEATURE_TELEPHONY_CDMA";
-    }
-
-    serial = GetRandomSerialNumber();
-
-    radio_voice->sendCdmaFeatureCode(serial, std::string());
-    EXPECT_EQ(std::cv_status::no_timeout, wait());
-    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
-    EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
-
-    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
-        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_voice->rspInfo.error,
-                                     {RadioError::NONE, RadioError::INVALID_ARGUMENTS,
-                                      RadioError::INVALID_CALL_ID, RadioError::INVALID_MODEM_STATE,
-                                      RadioError::MODEM_ERR, RadioError::OPERATION_NOT_ALLOWED},
-                                     CHECK_GENERAL_ERROR));
-    }
-}
-
-/*
  * Test IRadioVoice.sendDtmf() for the response returned.
  */
 TEST_P(RadioVoiceTest, sendDtmf) {
diff --git a/security/see/hwcrypto/aidl/vts/functional/Android.bp b/security/see/hwcrypto/aidl/vts/functional/Android.bp
index c2514d1..eb2eba1 100644
--- a/security/see/hwcrypto/aidl/vts/functional/Android.bp
+++ b/security/see/hwcrypto/aidl/vts/functional/Android.bp
@@ -30,6 +30,7 @@
         "libvsock",
         "librpcbinder_rs",
         "librustutils",
+        "libhwcryptohal_common",
     ],
     arch: {
         arm64: {
@@ -50,8 +51,8 @@
 }
 
 rust_test {
-    name: "VtsAidlHwCryptoConnTest",
-    srcs: ["connection_test.rs"],
+    name: "VtsAidlHwCryptoTests",
+    srcs: ["hwcryptokey_tests.rs"],
     require_root: true,
     defaults: [
         "hw_crypto_hal_aidl_rust_defaults",
@@ -59,4 +60,24 @@
     rustlibs: [
         "libhwcryptohal_vts_test",
     ],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
+}
+
+rust_test {
+    name: "VtsAidlHwCryptoOperationsTests",
+    srcs: ["hwcrypto_operations_tests.rs"],
+    require_root: true,
+    defaults: [
+        "hw_crypto_hal_aidl_rust_defaults",
+    ],
+    rustlibs: [
+        "libhwcryptohal_vts_test",
+    ],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
 }
diff --git a/security/see/hwcrypto/aidl/vts/functional/AndroidTestSystem.xml b/security/see/hwcrypto/aidl/vts/functional/AndroidTestSystem.xml
deleted file mode 100644
index 649be23..0000000
--- a/security/see/hwcrypto/aidl/vts/functional/AndroidTestSystem.xml
+++ /dev/null
@@ -1,56 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  Copyright 2025 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.
-  -->
-    <configuration description="Runs {MODULE}">
-    <!-- object type="module_controller" class="com.android.tradefed.testtype.suite.module.CommandSuccessModuleController" -->
-        <!--Skip the test when trusty VM is not enabled. -->
-        <!--option name="run-command" value="getprop trusty.test_vm.nonsecure_vm_ready | grep 1" /-->
-    <!--/object-->
-    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" />
-    <!-- Target Preparers - Run Shell Commands -->
-    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
-        <option name="cleanup" value="true" />
-        <option name="push-file" key="trusty-vm-launcher.sh" value="/data/local/tmp/trusty_test_vm/trusty-vm-launcher.sh" />
-        <option name="push-file" key="trusty-wait-ready.sh" value="/data/local/tmp/trusty_test_vm/trusty-wait-ready.sh" />
-        <option name="push-file" key="wait_hw_crypto" value="/data/local/tmp/trusty_test_vm/wait_hw_crypto" />
-        <option name="push-file" key="trusty-test_vm-config.json" value="/data/local/tmp/trusty_test_vm/trusty-test_vm-config.json" />
-        <option name="push-file" key="trusty_test_vm.elf" value="/data/local/tmp/trusty_test_vm/trusty_test_vm.elf" />
-        <option name="push-file" key="VtsAidlHwCryptoConnTestSystem" value="/data/local/tmp/VtsAidlHwCryptoConnTestSystem" />
-    </target_preparer>
-    <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
-        <option name="throw-if-cmd-fail" value="true" />
-        <!--Note: the first run-command shall not expect the background command to have started -->
-        <option name="run-bg-command" value="sh /data/local/tmp/trusty_test_vm/trusty-vm-launcher.sh" />
-        <option name="run-command" value="sh /data/local/tmp/trusty_test_vm/trusty-wait-ready.sh" />
-        <option name="run-bg-command" value="start trusty-hwcryptohal" />
-        <option name="run-command" value="/data/local/tmp/trusty_test_vm/wait_hw_crypto" />
-        <option name="run-command" value="start storageproxyd_test_system" />
-        <option name="teardown-command" value="stop storageproxyd_test_system" />
-        <option name="teardown-command" value="stop trusty-hwcryptohal" />
-        <option name="teardown-command" value="killall storageproxyd_test_system || true" />
-        <option name="teardown-command" value="stop trusty-hwcryptohal" />
-        <option name="teardown-command" value="killall trusty || true" />
-    </target_preparer>
-
-    <test class="com.android.tradefed.testtype.rust.RustBinaryTest" >
-        <option name="test-device-path" value="/data/local/tmp" />
-        <option name="module-name" value="VtsAidlHwCryptoConnTestSystem" />
-        <!-- Rust tests are run in parallel by default. Run these ones
-            single-threaded, so that one test's secrets don't affect
-            the behaviour of a different test. -->
-        <option name="native-test-flag" value="--test-threads=1" />
-    </test>
-    </configuration>
diff --git a/security/see/hwcrypto/aidl/vts/functional/connection_test.rs b/security/see/hwcrypto/aidl/vts/functional/connection_test.rs
deleted file mode 100644
index 338923d..0000000
--- a/security/see/hwcrypto/aidl/vts/functional/connection_test.rs
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * 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.
- */
-
-//! HwCrypto Connection tests.
-
-#[test]
-fn test_hwcrypto_key_connection() {
-    let hw_crypto_key = hwcryptohal_vts_test::get_hwcryptokey();
-    assert!(hw_crypto_key.is_ok(), "Couldn't get back a hwcryptokey binder object");
-}
diff --git a/security/see/hwcrypto/aidl/vts/functional/hwcrypto_operations_tests.rs b/security/see/hwcrypto/aidl/vts/functional/hwcrypto_operations_tests.rs
new file mode 100644
index 0000000..521fb73
--- /dev/null
+++ b/security/see/hwcrypto/aidl/vts/functional/hwcrypto_operations_tests.rs
@@ -0,0 +1,586 @@
+/*
+ * Copyright (C) 2025 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.
+ */
+
+//! HwCryptoOperations tests.
+
+use android_hardware_security_see_hwcrypto::aidl::android::hardware::security::see::hwcrypto::types::{
+    AesKey::AesKey, ExplicitKeyMaterial::ExplicitKeyMaterial, KeyType::KeyType, KeyLifetime::KeyLifetime,
+    KeyUse::KeyUse, OperationData::OperationData, HmacOperationParameters::HmacOperationParameters,
+    SymmetricOperationParameters::SymmetricOperationParameters, SymmetricOperation::SymmetricOperation,
+    HmacKey::HmacKey, CipherModeParameters::CipherModeParameters, AesCipherMode::AesCipherMode,
+    SymmetricCryptoParameters::SymmetricCryptoParameters,
+};
+use android_hardware_security_see_hwcrypto::aidl::android::hardware::security::see::hwcrypto::{
+    KeyPolicy::KeyPolicy,CryptoOperation::CryptoOperation,CryptoOperationSet::CryptoOperationSet,
+    OperationParameters::OperationParameters, PatternParameters::PatternParameters,
+};
+
+#[test]
+fn test_hwcrypto_key_operations_connection() {
+    let hw_crypto_key = hwcryptohal_vts_test::get_hwcryptokey()
+        .expect("Couldn't get back a hwcryptokey binder object");
+    let hw_crypto_operations = hw_crypto_key.getHwCryptoOperations();
+    assert!(hw_crypto_operations.is_ok(), "Couldn't get back a hwcrypto operations binder object");
+}
+
+#[test]
+fn test_hwcrypto_key_operations_simple_aes_test() {
+    let hw_crypto_key = hwcryptohal_vts_test::get_hwcryptokey()
+        .expect("Couldn't get back a hwcryptokey binder object");
+    let hw_crypto_operations = hw_crypto_key
+        .getHwCryptoOperations()
+        .expect("Couldn't get back a hwcryptokey operations binder object");
+    let clear_key = ExplicitKeyMaterial::Aes(AesKey::Aes128([0; 16]));
+    let policy = KeyPolicy {
+        usage: KeyUse::ENCRYPT_DECRYPT,
+        keyLifetime: KeyLifetime::PORTABLE,
+        keyPermissions: Vec::new(),
+        keyManagementKey: false,
+        keyType: KeyType::AES_128_CBC_PKCS7_PADDING,
+    };
+    let key = hw_crypto_key.importClearKey(&clear_key, &policy).expect("couldn't import clear key");
+
+    let nonce = [0u8; 16];
+    let parameters = SymmetricCryptoParameters::Aes(AesCipherMode::Cbc(CipherModeParameters {
+        nonce: nonce.into(),
+    }));
+    let direction = SymmetricOperation::ENCRYPT;
+    let sym_op_params =
+        SymmetricOperationParameters { key: Some(key.clone()), direction, parameters };
+    let op_params = OperationParameters::SymmetricCrypto(sym_op_params);
+    let mut cmd_list = Vec::<CryptoOperation>::new();
+    let data_output = OperationData::DataBuffer(Vec::new());
+    cmd_list.push(CryptoOperation::DataOutput(data_output));
+    cmd_list.push(CryptoOperation::SetOperationParameters(op_params));
+    let input_data = OperationData::DataBuffer("string to be encrypted".as_bytes().to_vec());
+    cmd_list.push(CryptoOperation::DataInput(input_data));
+    let crypto_op_set = CryptoOperationSet { context: None, operations: cmd_list };
+    let mut crypto_sets = Vec::new();
+    crypto_sets.push(crypto_op_set);
+    let mut op_result = hw_crypto_operations
+        .processCommandList(&mut crypto_sets)
+        .expect("couldn't process commands");
+    // Extracting the vector from the command list because of ownership
+    let CryptoOperation::DataOutput(OperationData::DataBuffer(encrypted_data)) =
+        crypto_sets.remove(0).operations.remove(0)
+    else {
+        panic!("not reachable, we created this object above on the test");
+    };
+    let context = op_result.remove(0).context;
+    // Separating the finish call on a different command set to test the returned context
+    let mut cmd_list = Vec::<CryptoOperation>::new();
+    let data_output = OperationData::DataBuffer(encrypted_data);
+    cmd_list.push(CryptoOperation::DataOutput(data_output));
+    cmd_list.push(CryptoOperation::Finish(None));
+    let crypto_op_set = CryptoOperationSet { context, operations: cmd_list };
+    let mut crypto_sets = Vec::new();
+    crypto_sets.push(crypto_op_set);
+    hw_crypto_operations.processCommandList(&mut crypto_sets).expect("couldn't process commands");
+    let CryptoOperation::DataOutput(OperationData::DataBuffer(encrypted_data)) =
+        crypto_sets.remove(0).operations.remove(0)
+    else {
+        panic!("not reachable, we created this object above on the test");
+    };
+
+    // Decrypting
+    let parameters = SymmetricCryptoParameters::Aes(AesCipherMode::Cbc(CipherModeParameters {
+        nonce: nonce.into(),
+    }));
+    let direction = SymmetricOperation::DECRYPT;
+    let sym_op_params = SymmetricOperationParameters { key: Some(key), direction, parameters };
+    let op_params = OperationParameters::SymmetricCrypto(sym_op_params);
+    let mut cmd_list = Vec::<CryptoOperation>::new();
+    let data_output = OperationData::DataBuffer(Vec::new());
+    cmd_list.push(CryptoOperation::DataOutput(data_output));
+    cmd_list.push(CryptoOperation::SetOperationParameters(op_params));
+    cmd_list.push(CryptoOperation::DataInput(OperationData::DataBuffer(encrypted_data)));
+    cmd_list.push(CryptoOperation::Finish(None));
+    let crypto_op_set = CryptoOperationSet { context: None, operations: cmd_list };
+    let mut crypto_sets = Vec::new();
+    crypto_sets.push(crypto_op_set);
+    hw_crypto_operations.processCommandList(&mut crypto_sets).expect("couldn't process commands");
+    // Extracting the vector from the command list because of ownership
+    let CryptoOperation::DataOutput(OperationData::DataBuffer(decrypted_data)) =
+        crypto_sets.remove(0).operations.remove(0)
+    else {
+        panic!("not reachable, we created this object above on the test");
+    };
+    let decrypted_msg =
+        String::from_utf8(decrypted_data).expect("couldn't decode received message");
+    assert_eq!(decrypted_msg, "string to be encrypted", "couldn't retrieve original message");
+}
+
+#[test]
+fn test_hwcrypto_key_operations_simple_hmac_test() {
+    let hw_crypto_key = hwcryptohal_vts_test::get_hwcryptokey()
+        .expect("Couldn't get back a hwcryptokey binder object");
+    let hw_crypto_operations = hw_crypto_key
+        .getHwCryptoOperations()
+        .expect("Couldn't get back a hwcryptokey operations binder object");
+    let clear_key = ExplicitKeyMaterial::Hmac(HmacKey::Sha256([0; 32]));
+    let policy = KeyPolicy {
+        usage: KeyUse::SIGN,
+        keyLifetime: KeyLifetime::PORTABLE,
+        keyPermissions: Vec::new(),
+        keyManagementKey: false,
+        keyType: KeyType::HMAC_SHA256,
+    };
+    let key = hw_crypto_key.importClearKey(&clear_key, &policy).expect("couldn't import clear key");
+
+    let hmac_parameters = HmacOperationParameters { key: Some(key.clone()) };
+    let op_parameters = OperationParameters::Hmac(hmac_parameters);
+    let mut cmd_list = Vec::<CryptoOperation>::new();
+    let data_output = OperationData::DataBuffer(Vec::new());
+    cmd_list.push(CryptoOperation::DataOutput(data_output));
+    cmd_list.push(CryptoOperation::SetOperationParameters(op_parameters));
+    let input_data = OperationData::DataBuffer("text to be mac'ed".as_bytes().to_vec());
+    cmd_list.push(CryptoOperation::DataInput(input_data));
+    cmd_list.push(CryptoOperation::Finish(None));
+    let crypto_op_set = CryptoOperationSet { context: None, operations: cmd_list };
+    let mut crypto_sets = Vec::new();
+    crypto_sets.push(crypto_op_set);
+    hw_crypto_operations.processCommandList(&mut crypto_sets).expect("couldn't process commands");
+    // Extracting the vector from the command list because of ownership
+    let CryptoOperation::DataOutput(OperationData::DataBuffer(mac)) =
+        crypto_sets.remove(0).operations.remove(0)
+    else {
+        panic!("not reachable, we created this object above on the test");
+    };
+
+    //Getting a second mac to compare
+    let hmac_parameters = HmacOperationParameters { key: Some(key) };
+    let op_parameters = OperationParameters::Hmac(hmac_parameters);
+    let mut cmd_list = Vec::<CryptoOperation>::new();
+    let data_output = OperationData::DataBuffer(Vec::new());
+    cmd_list.push(CryptoOperation::DataOutput(data_output));
+    cmd_list.push(CryptoOperation::SetOperationParameters(op_parameters));
+    let input_data = OperationData::DataBuffer("text to be mac'ed".as_bytes().to_vec());
+    cmd_list.push(CryptoOperation::DataInput(input_data));
+    cmd_list.push(CryptoOperation::Finish(None));
+    let crypto_op_set = CryptoOperationSet { context: None, operations: cmd_list };
+    let mut crypto_sets = Vec::new();
+    crypto_sets.push(crypto_op_set);
+    hw_crypto_operations.processCommandList(&mut crypto_sets).expect("couldn't process commands");
+    // Extracting the vector from the command list because of ownership
+    let CryptoOperation::DataOutput(OperationData::DataBuffer(mac2)) =
+        crypto_sets.remove(0).operations.remove(0)
+    else {
+        panic!("not reachable, we created this object above on the test");
+    };
+    assert_eq!(mac, mac2, "got a different mac");
+}
+
+#[test]
+fn test_hwcrypto_key_operations_aes_simple_cbcs_test_non_block_multiple() {
+    let hw_crypto_key = hwcryptohal_vts_test::get_hwcryptokey()
+        .expect("Couldn't get back a hwcryptokey binder object");
+    let hw_crypto_operations = hw_crypto_key
+        .getHwCryptoOperations()
+        .expect("Couldn't get back a hwcryptokey operations binder object");
+
+    let usage = KeyUse::ENCRYPT_DECRYPT;
+    let key_type = KeyType::AES_128_CBC_NO_PADDING;
+    let policy = KeyPolicy {
+        usage,
+        keyLifetime: KeyLifetime::PORTABLE,
+        keyPermissions: Vec::new(),
+        keyType: key_type,
+        keyManagementKey: false,
+    };
+    let clear_key = ExplicitKeyMaterial::Aes(AesKey::Aes128([0; 16]));
+    let key = hw_crypto_key.importClearKey(&clear_key, &policy).expect("couldn't import clear key");
+
+    let nonce = [0u8; 16];
+    let parameters = SymmetricCryptoParameters::Aes(AesCipherMode::Cbc(CipherModeParameters {
+        nonce: nonce.into(),
+    }));
+    let direction = SymmetricOperation::ENCRYPT;
+    let sym_op_params =
+        SymmetricOperationParameters { key: Some(key.clone()), direction, parameters };
+    let op_params = OperationParameters::SymmetricCrypto(sym_op_params);
+    let mut cmd_list = Vec::<CryptoOperation>::new();
+    let data_output = OperationData::DataBuffer(Vec::new());
+    cmd_list.push(CryptoOperation::DataOutput(data_output));
+    cmd_list.push(CryptoOperation::SetOperationParameters(op_params));
+    cmd_list.push(CryptoOperation::SetPattern(PatternParameters {
+        numberBlocksProcess: 1,
+        numberBlocksCopy: 0,
+    }));
+    let input_data =
+        OperationData::DataBuffer("encryption data.0123456789abcdef".as_bytes().to_vec());
+    cmd_list.push(CryptoOperation::DataInput(input_data));
+    let input_data =
+        OperationData::DataBuffer("fedcba98765432100123456789abcdef".as_bytes().to_vec());
+    cmd_list.push(CryptoOperation::DataInput(input_data));
+    let input_data = OperationData::DataBuffer("unencrypted".as_bytes().to_vec());
+    cmd_list.push(CryptoOperation::DataInput(input_data));
+    cmd_list.push(CryptoOperation::Finish(None));
+    let crypto_op_set = CryptoOperationSet { context: None, operations: cmd_list };
+    let mut crypto_sets = Vec::new();
+    crypto_sets.push(crypto_op_set);
+    hw_crypto_operations.processCommandList(&mut crypto_sets).expect("couldn't process commands");
+    let CryptoOperation::DataOutput(OperationData::DataBuffer(encrypted_data)) =
+        crypto_sets.remove(0).operations.remove(0)
+    else {
+        panic!("not reachable, we created this object above on the test");
+    };
+
+    let clear_encrypted_msg =
+        String::from_utf8(encrypted_data[encrypted_data.len() - "unencrypted".len()..].to_vec())
+            .expect("couldn't decode message");
+    assert_eq!(clear_encrypted_msg, "unencrypted");
+
+    // Decrypting
+    let parameters = SymmetricCryptoParameters::Aes(AesCipherMode::Cbc(CipherModeParameters {
+        nonce: nonce.into(),
+    }));
+    let direction = SymmetricOperation::DECRYPT;
+    let sym_op_params =
+        SymmetricOperationParameters { key: Some(key.clone()), direction, parameters };
+    let op_params = OperationParameters::SymmetricCrypto(sym_op_params);
+    let mut cmd_list = Vec::<CryptoOperation>::new();
+    let data_output = OperationData::DataBuffer(Vec::new());
+    cmd_list.push(CryptoOperation::DataOutput(data_output));
+    cmd_list.push(CryptoOperation::SetOperationParameters(op_params));
+    cmd_list.push(CryptoOperation::SetPattern(PatternParameters {
+        numberBlocksProcess: 1,
+        numberBlocksCopy: 0,
+    }));
+    cmd_list.push(CryptoOperation::DataInput(OperationData::DataBuffer(encrypted_data)));
+    cmd_list.push(CryptoOperation::Finish(None));
+    let crypto_op_set = CryptoOperationSet { context: None, operations: cmd_list };
+    let mut crypto_sets = Vec::new();
+    crypto_sets.push(crypto_op_set);
+    hw_crypto_operations.processCommandList(&mut crypto_sets).expect("couldn't process commands");
+    let CryptoOperation::DataOutput(OperationData::DataBuffer(decrypted_data)) =
+        crypto_sets.remove(0).operations.remove(0)
+    else {
+        panic!("not reachable, we created this object above on the test");
+    };
+    let decrypted_msg =
+        String::from_utf8(decrypted_data).expect("couldn't decode received message");
+    assert_eq!(
+        decrypted_msg,
+        "encryption data.0123456789abcdeffedcba9876543210\
+        0123456789abcdefunencrypted",
+        "couldn't retrieve original message"
+    );
+}
+
+#[test]
+fn test_hwcrypto_key_operations_aes_simple_all_encrypted_cbcs_test() {
+    let hw_crypto_key = hwcryptohal_vts_test::get_hwcryptokey()
+        .expect("Couldn't get back a hwcryptokey binder object");
+    let hw_crypto_operations = hw_crypto_key
+        .getHwCryptoOperations()
+        .expect("Couldn't get back a hwcryptokey operations binder object");
+
+    let usage = KeyUse::ENCRYPT_DECRYPT;
+    let key_type = KeyType::AES_128_CBC_NO_PADDING;
+    let policy = KeyPolicy {
+        usage,
+        keyLifetime: KeyLifetime::PORTABLE,
+        keyPermissions: Vec::new(),
+        keyType: key_type,
+        keyManagementKey: false,
+    };
+    let clear_key = ExplicitKeyMaterial::Aes(AesKey::Aes128([0; 16]));
+    let key = hw_crypto_key.importClearKey(&clear_key, &policy).expect("couldn't import clear key");
+
+    let nonce = [0u8; 16];
+    let parameters = SymmetricCryptoParameters::Aes(AesCipherMode::Cbc(CipherModeParameters {
+        nonce: nonce.into(),
+    }));
+    let direction = SymmetricOperation::ENCRYPT;
+    let sym_op_params =
+        SymmetricOperationParameters { key: Some(key.clone()), direction, parameters };
+    let op_params = OperationParameters::SymmetricCrypto(sym_op_params);
+    let mut cmd_list = Vec::<CryptoOperation>::new();
+    let data_output = OperationData::DataBuffer(Vec::new());
+    cmd_list.push(CryptoOperation::DataOutput(data_output));
+    cmd_list.push(CryptoOperation::SetOperationParameters(op_params));
+    cmd_list.push(CryptoOperation::SetPattern(PatternParameters {
+        numberBlocksProcess: 1,
+        numberBlocksCopy: 0,
+    }));
+    let input_data =
+        OperationData::DataBuffer("encryption data.0123456789abcdef".as_bytes().to_vec());
+    cmd_list.push(CryptoOperation::DataInput(input_data));
+    let input_data =
+        OperationData::DataBuffer("fedcba98765432100123456789abcdef".as_bytes().to_vec());
+    cmd_list.push(CryptoOperation::DataInput(input_data));
+    cmd_list.push(CryptoOperation::Finish(None));
+    let crypto_op_set = CryptoOperationSet { context: None, operations: cmd_list };
+    let mut crypto_sets = Vec::new();
+    crypto_sets.push(crypto_op_set);
+    hw_crypto_operations.processCommandList(&mut crypto_sets).expect("couldn't process commands");
+
+    let CryptoOperation::DataOutput(OperationData::DataBuffer(encrypted_data)) =
+        crypto_sets.remove(0).operations.remove(0)
+    else {
+        panic!("not reachable, we created this object above on the test");
+    };
+
+    // Checking that encrypting with patter 0,0 is equivalent to pattern 1,0
+    let parameters = SymmetricCryptoParameters::Aes(AesCipherMode::Cbc(CipherModeParameters {
+        nonce: nonce.into(),
+    }));
+    let direction = SymmetricOperation::ENCRYPT;
+    let sym_op_params =
+        SymmetricOperationParameters { key: Some(key.clone()), direction, parameters };
+    let op_params = OperationParameters::SymmetricCrypto(sym_op_params);
+    let mut cmd_list = Vec::<CryptoOperation>::new();
+    let data_output = OperationData::DataBuffer(Vec::new());
+    cmd_list.push(CryptoOperation::DataOutput(data_output));
+    cmd_list.push(CryptoOperation::SetOperationParameters(op_params));
+    cmd_list.push(CryptoOperation::SetPattern(PatternParameters {
+        numberBlocksProcess: 0,
+        numberBlocksCopy: 0,
+    }));
+    let input_data =
+        OperationData::DataBuffer("encryption data.0123456789abcdef".as_bytes().to_vec());
+    cmd_list.push(CryptoOperation::DataInput(input_data));
+    let input_data =
+        OperationData::DataBuffer("fedcba98765432100123456789abcdef".as_bytes().to_vec());
+    cmd_list.push(CryptoOperation::DataInput(input_data));
+    cmd_list.push(CryptoOperation::Finish(None));
+    let crypto_op_set = CryptoOperationSet { context: None, operations: cmd_list };
+    let mut crypto_sets = Vec::new();
+    crypto_sets.push(crypto_op_set);
+    hw_crypto_operations.processCommandList(&mut crypto_sets).expect("couldn't process commands");
+    let CryptoOperation::DataOutput(OperationData::DataBuffer(encrypted_data1)) =
+        crypto_sets.remove(0).operations.remove(0)
+    else {
+        panic!("not reachable, we created this object above on the test");
+    };
+    assert_eq!(encrypted_data, encrypted_data1, "encrypted data should match");
+
+    // Decrypting
+    let parameters = SymmetricCryptoParameters::Aes(AesCipherMode::Cbc(CipherModeParameters {
+        nonce: nonce.into(),
+    }));
+    let direction = SymmetricOperation::DECRYPT;
+    let sym_op_params =
+        SymmetricOperationParameters { key: Some(key.clone()), direction, parameters };
+    let op_params = OperationParameters::SymmetricCrypto(sym_op_params);
+    let mut cmd_list = Vec::<CryptoOperation>::new();
+    let data_output = OperationData::DataBuffer(Vec::new());
+    cmd_list.push(CryptoOperation::DataOutput(data_output));
+    cmd_list.push(CryptoOperation::SetOperationParameters(op_params));
+    cmd_list.push(CryptoOperation::DataInput(OperationData::DataBuffer(encrypted_data)));
+    cmd_list.push(CryptoOperation::Finish(None));
+    let crypto_op_set = CryptoOperationSet { context: None, operations: cmd_list };
+    let mut crypto_sets = Vec::new();
+    crypto_sets.push(crypto_op_set);
+    hw_crypto_operations.processCommandList(&mut crypto_sets).expect("couldn't process commands");
+
+    let CryptoOperation::DataOutput(OperationData::DataBuffer(decrypted_data)) =
+        crypto_sets.remove(0).operations.remove(0)
+    else {
+        panic!("not reachable, we created this object above on the test");
+    };
+    let decrypted_msg =
+        String::from_utf8(decrypted_data).expect("couldn't decode received message");
+    assert_eq!(
+        decrypted_msg,
+        "encryption data.0123456789abcdeffedcba9876543210\
+        0123456789abcdef",
+        "couldn't retrieve original message"
+    );
+}
+
+#[test]
+fn check_cbcs_wrong_key_types() {
+    let hw_crypto_key = hwcryptohal_vts_test::get_hwcryptokey()
+        .expect("Couldn't get back a hwcryptokey binder object");
+    let hw_crypto_operations = hw_crypto_key
+        .getHwCryptoOperations()
+        .expect("Couldn't get back a hwcryptokey operations binder object");
+
+    let usage = KeyUse::ENCRYPT_DECRYPT;
+    let key_type = KeyType::AES_128_CBC_PKCS7_PADDING;
+    let policy = KeyPolicy {
+        usage,
+        keyLifetime: KeyLifetime::PORTABLE,
+        keyPermissions: Vec::new(),
+        keyType: key_type,
+        keyManagementKey: false,
+    };
+    let clear_key = ExplicitKeyMaterial::Aes(AesKey::Aes128([0; 16]));
+    let key = hw_crypto_key.importClearKey(&clear_key, &policy).expect("couldn't import clear key");
+
+    let nonce = [0u8; 16];
+    let parameters = SymmetricCryptoParameters::Aes(AesCipherMode::Cbc(CipherModeParameters {
+        nonce: nonce.into(),
+    }));
+    let direction = SymmetricOperation::ENCRYPT;
+    let sym_op_params = SymmetricOperationParameters { key: Some(key), direction, parameters };
+    let op_params = OperationParameters::SymmetricCrypto(sym_op_params);
+    let mut cmd_list = Vec::<CryptoOperation>::new();
+    let data_output = OperationData::DataBuffer(Vec::new());
+    cmd_list.push(CryptoOperation::DataOutput(data_output));
+    cmd_list.push(CryptoOperation::SetOperationParameters(op_params));
+    cmd_list.push(CryptoOperation::SetPattern(PatternParameters {
+        numberBlocksProcess: 1,
+        numberBlocksCopy: 9,
+    }));
+    let crypto_op_set = CryptoOperationSet { context: None, operations: cmd_list };
+    let mut crypto_sets = Vec::new();
+    crypto_sets.push(crypto_op_set);
+    let process_result = hw_crypto_operations.processCommandList(&mut crypto_sets);
+    assert!(process_result.is_err(), "Should not be able to use cbcs mode with this key type");
+
+    let policy = KeyPolicy {
+        usage,
+        keyLifetime: KeyLifetime::PORTABLE,
+        keyPermissions: Vec::new(),
+        keyType: KeyType::AES_256_CBC_NO_PADDING,
+        keyManagementKey: false,
+    };
+    let clear_key = ExplicitKeyMaterial::Aes(AesKey::Aes256([0; 32]));
+    let key = hw_crypto_key.importClearKey(&clear_key, &policy).expect("couldn't import clear key");
+    let parameters = SymmetricCryptoParameters::Aes(AesCipherMode::Cbc(CipherModeParameters {
+        nonce: nonce.into(),
+    }));
+    let sym_op_params = SymmetricOperationParameters { key: Some(key), direction, parameters };
+    let op_params = OperationParameters::SymmetricCrypto(sym_op_params);
+    let mut cmd_list = Vec::<CryptoOperation>::new();
+    let data_output = OperationData::DataBuffer(Vec::new());
+    cmd_list.push(CryptoOperation::DataOutput(data_output));
+    cmd_list.push(CryptoOperation::SetOperationParameters(op_params));
+    cmd_list.push(CryptoOperation::SetPattern(PatternParameters {
+        numberBlocksProcess: 1,
+        numberBlocksCopy: 9,
+    }));
+    let crypto_op_set = CryptoOperationSet { context: None, operations: cmd_list };
+    let mut crypto_sets = Vec::new();
+    crypto_sets.push(crypto_op_set);
+    let process_result = hw_crypto_operations.processCommandList(&mut crypto_sets);
+
+    assert!(process_result.is_err(), "Should not be able to use cbcs mode with this key type");
+}
+
+#[test]
+fn aes_simple_cbcs_test() {
+    let hw_crypto_key = hwcryptohal_vts_test::get_hwcryptokey()
+        .expect("Couldn't get back a hwcryptokey binder object");
+    let hw_crypto_operations = hw_crypto_key
+        .getHwCryptoOperations()
+        .expect("Couldn't get back a hwcryptokey operations binder object");
+
+    let usage = KeyUse::ENCRYPT_DECRYPT;
+    let key_type = KeyType::AES_128_CBC_NO_PADDING;
+    let policy = KeyPolicy {
+        usage,
+        keyLifetime: KeyLifetime::PORTABLE,
+        keyPermissions: Vec::new(),
+        keyType: key_type,
+        keyManagementKey: false,
+    };
+    let clear_key = ExplicitKeyMaterial::Aes(AesKey::Aes128([0; 16]));
+    let key = hw_crypto_key.importClearKey(&clear_key, &policy).expect("couldn't import clear key");
+
+    let nonce = [0u8; 16];
+    let parameters = SymmetricCryptoParameters::Aes(AesCipherMode::Cbc(CipherModeParameters {
+        nonce: nonce.into(),
+    }));
+    let direction = SymmetricOperation::ENCRYPT;
+    let sym_op_params =
+        SymmetricOperationParameters { key: Some(key.clone()), direction, parameters };
+    let op_params = OperationParameters::SymmetricCrypto(sym_op_params);
+    let mut cmd_list = Vec::<CryptoOperation>::new();
+    let data_output = OperationData::DataBuffer(Vec::new());
+    cmd_list.push(CryptoOperation::DataOutput(data_output));
+    cmd_list.push(CryptoOperation::SetOperationParameters(op_params));
+    cmd_list.push(CryptoOperation::SetPattern(PatternParameters {
+        numberBlocksProcess: 1,
+        numberBlocksCopy: 9,
+    }));
+    let input_data =
+        OperationData::DataBuffer("encryption data.0123456789abcdef".as_bytes().to_vec());
+    cmd_list.push(CryptoOperation::DataInput(input_data));
+    let input_data =
+        OperationData::DataBuffer("fedcba98765432100123456789abcdef".as_bytes().to_vec());
+    cmd_list.push(CryptoOperation::DataInput(input_data));
+    let input_data =
+        OperationData::DataBuffer("fedcba98765432100123456789abcdef".as_bytes().to_vec());
+    cmd_list.push(CryptoOperation::DataInput(input_data));
+    let input_data =
+        OperationData::DataBuffer("fedcba98765432100123456789abcdef".as_bytes().to_vec());
+    cmd_list.push(CryptoOperation::DataInput(input_data));
+    let input_data = OperationData::DataBuffer(
+        "fedcba98765432100123456789abcdefProtectedSection".as_bytes().to_vec(),
+    );
+    cmd_list.push(CryptoOperation::DataInput(input_data));
+    cmd_list.push(CryptoOperation::Finish(None));
+    let crypto_op_set = CryptoOperationSet { context: None, operations: cmd_list };
+    let mut crypto_sets = Vec::new();
+    crypto_sets.push(crypto_op_set);
+    hw_crypto_operations.processCommandList(&mut crypto_sets).expect("couldn't process commands");
+
+    let CryptoOperation::DataOutput(OperationData::DataBuffer(encrypted_data)) =
+        crypto_sets.remove(0).operations.remove(0)
+    else {
+        panic!("not reachable, we created this object above on the test");
+    };
+    let clear_encrypted_msg =
+        String::from_utf8(encrypted_data[16..encrypted_data.len() - 16].to_vec())
+            .expect("couldn't decode received message");
+    assert_eq!(
+        clear_encrypted_msg,
+        "0123456789abcdeffedcba98765432100123456789abcdeffedcba9876543210\
+        0123456789abcdeffedcba98765432100123456789abcdeffedcba98765432100123456789abcdef",
+        "couldn't retrieve clear portion"
+    );
+
+    // Decrypting
+    let parameters = SymmetricCryptoParameters::Aes(AesCipherMode::Cbc(CipherModeParameters {
+        nonce: nonce.into(),
+    }));
+    let direction = SymmetricOperation::DECRYPT;
+    let sym_op_params =
+        SymmetricOperationParameters { key: Some(key.clone()), direction, parameters };
+    let op_params = OperationParameters::SymmetricCrypto(sym_op_params);
+    let mut cmd_list = Vec::<CryptoOperation>::new();
+    let data_output = OperationData::DataBuffer(Vec::new());
+    cmd_list.push(CryptoOperation::DataOutput(data_output));
+    cmd_list.push(CryptoOperation::SetOperationParameters(op_params));
+    cmd_list.push(CryptoOperation::SetPattern(PatternParameters {
+        numberBlocksProcess: 1,
+        numberBlocksCopy: 9,
+    }));
+    cmd_list.push(CryptoOperation::DataInput(OperationData::DataBuffer(encrypted_data)));
+    cmd_list.push(CryptoOperation::Finish(None));
+    let crypto_op_set = CryptoOperationSet { context: None, operations: cmd_list };
+    let mut crypto_sets = Vec::new();
+    crypto_sets.push(crypto_op_set);
+    hw_crypto_operations.processCommandList(&mut crypto_sets).expect("couldn't process commands");
+
+    let CryptoOperation::DataOutput(OperationData::DataBuffer(decrypted_data)) =
+        crypto_sets.remove(0).operations.remove(0)
+    else {
+        panic!("not reachable, we created this object above on the test");
+    };
+    let decrypted_msg =
+        String::from_utf8(decrypted_data).expect("couldn't decode received message");
+    assert_eq!(
+        decrypted_msg,
+        "encryption data.0123456789abcdeffedcba9876543210\
+        0123456789abcdeffedcba98765432100123456789abcdeffedcba9876543210\
+        0123456789abcdeffedcba98765432100123456789abcdefProtectedSection",
+        "couldn't retrieve original message"
+    );
+}
diff --git a/security/see/hwcrypto/aidl/vts/functional/hwcryptokey_tests.rs b/security/see/hwcrypto/aidl/vts/functional/hwcryptokey_tests.rs
new file mode 100644
index 0000000..fcce839
--- /dev/null
+++ b/security/see/hwcrypto/aidl/vts/functional/hwcryptokey_tests.rs
@@ -0,0 +1,165 @@
+/*
+ * 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.
+ */
+
+//! HwCryptoKey tests.
+
+use android_hardware_security_see_hwcrypto::aidl::android::hardware::security::see::hwcrypto::IHwCryptoKey::{
+    DerivedKeyParameters::DerivedKeyParameters, DerivedKeyPolicy::DerivedKeyPolicy,
+    DiceBoundDerivationKey::DiceBoundDerivationKey, KeySlot::KeySlot,
+};
+use android_hardware_security_see_hwcrypto::aidl::android::hardware::security::see::hwcrypto::types::{
+    HalErrorCode, AesKey::AesKey, ExplicitKeyMaterial::ExplicitKeyMaterial, KeyType::KeyType, KeyLifetime::KeyLifetime, KeyUse::KeyUse,
+    HmacKey::HmacKey, ProtectionId::ProtectionId,
+};
+use android_hardware_security_see_hwcrypto::aidl::android::hardware::security::see::hwcrypto::KeyPolicy::KeyPolicy;
+use hwcryptohal_common;
+
+#[test]
+fn test_hwcrypto_key_connection() {
+    let hw_crypto_key = hwcryptohal_vts_test::get_hwcryptokey();
+    assert!(hw_crypto_key.is_ok(), "Couldn't get back a hwcryptokey binder object");
+}
+
+#[test]
+fn test_hwcrypto_key_get_current_dice_policy() {
+    let hw_crypto_key = hwcryptohal_vts_test::get_hwcryptokey()
+        .expect("Couldn't get back a hwcryptokey binder object");
+    let dice_policy = hw_crypto_key.getCurrentDicePolicy().expect("Couldn't get dice policy back");
+    assert!(!dice_policy.is_empty(), "received empty dice policy");
+}
+
+#[test]
+fn test_hwcrypto_get_keyslot_data() {
+    let hw_crypto_key = hwcryptohal_vts_test::get_hwcryptokey()
+        .expect("Couldn't get back a hwcryptokey binder object");
+    let key = hw_crypto_key.getKeyslotData(KeySlot::KEYMINT_SHARED_HMAC_KEY);
+    assert_eq!(
+        key.err()
+            .expect("should not be able to access this keylost from the host")
+            .service_specific_error(),
+        HalErrorCode::UNAUTHORIZED,
+        "wrong error type received"
+    );
+}
+
+#[test]
+fn test_hwcrypto_import_clear_key() {
+    let hw_crypto_key = hwcryptohal_vts_test::get_hwcryptokey()
+        .expect("Couldn't get back a hwcryptokey binder object");
+    let clear_key = ExplicitKeyMaterial::Aes(AesKey::Aes128([0; 16]));
+    let mut policy = KeyPolicy {
+        usage: KeyUse::ENCRYPT_DECRYPT,
+        keyLifetime: KeyLifetime::PORTABLE,
+        keyPermissions: Vec::new(),
+        keyManagementKey: false,
+        keyType: KeyType::AES_128_GCM,
+    };
+    let key = hw_crypto_key.importClearKey(&clear_key, &policy).expect("couldn't import key");
+    assert!(key.getPublicKey().is_err(), "symmetric keys don't have a public key");
+    let imported_policy = key.getKeyPolicy().expect("couldn't get key policy");
+    let serialized_policy =
+        hwcryptohal_common::key_policy_to_cbor(&policy).expect("couldn't serialize policy");
+    let serialized_impoorted_policy = hwcryptohal_common::key_policy_to_cbor(&imported_policy)
+        .expect("couldn't serialize policy");
+    assert_eq!(serialized_policy, serialized_impoorted_policy, "policies should match");
+    policy.keyLifetime = KeyLifetime::EPHEMERAL;
+    let key = hw_crypto_key.importClearKey(&clear_key, &policy);
+    assert!(key.is_err(), "imported keys should be of type PORTABLE");
+    policy.keyLifetime = KeyLifetime::HARDWARE;
+    let key = hw_crypto_key.importClearKey(&clear_key, &policy);
+    assert!(key.is_err(), "imported keys should be of type PORTABLE");
+}
+
+#[test]
+fn test_hwcrypto_token_export_import() {
+    // This test is not representative of the complete flow because here the exporter and importer
+    // are the same client, which is not something we would usually do
+    let hw_crypto_key = hwcryptohal_vts_test::get_hwcryptokey()
+        .expect("Couldn't get back a hwcryptokey binder object");
+    let clear_key = ExplicitKeyMaterial::Hmac(HmacKey::Sha256([0; 32]));
+    let policy = KeyPolicy {
+        usage: KeyUse::DERIVE,
+        keyLifetime: KeyLifetime::PORTABLE,
+        keyPermissions: Vec::new(),
+        keyManagementKey: false,
+        keyType: KeyType::HMAC_SHA256,
+    };
+    let key = hw_crypto_key.importClearKey(&clear_key, &policy).expect("couldn't import clear key");
+    let dice_policy = hw_crypto_key.getCurrentDicePolicy().expect("Couldn't get dice policy back");
+    let token =
+        key.getShareableToken(dice_policy.as_slice()).expect("Couldn't get shareable token");
+    let imported_key = hw_crypto_key
+        .keyTokenImport(&token, dice_policy.as_slice());
+    assert!(imported_key.is_ok(), "Couldn't import shareable token");
+    // TODO: Use operations to verify that the keys match
+}
+
+#[test]
+fn test_hwcrypto_android_invalid_calls() {
+    let hw_crypto_key = hwcryptohal_vts_test::get_hwcryptokey()
+        .expect("Couldn't get back a hwcryptokey binder object");
+    let clear_key = ExplicitKeyMaterial::Hmac(HmacKey::Sha256([0; 32]));
+    let policy = KeyPolicy {
+        usage: KeyUse::DERIVE,
+        keyLifetime: KeyLifetime::PORTABLE,
+        keyPermissions: Vec::new(),
+        keyManagementKey: false,
+        keyType: KeyType::HMAC_SHA256,
+    };
+    let key = hw_crypto_key.importClearKey(&clear_key, &policy).expect("couldn't import clear key");
+    let protections = Vec::new();
+    let res = key.setProtectionId(ProtectionId::WIDEVINE_OUTPUT_BUFFER, &protections);
+    assert_eq!(
+        res.err()
+            .expect("should not be call this function from the host")
+            .service_specific_error(),
+        HalErrorCode::UNAUTHORIZED,
+        "wrong error type received"
+    );
+    let derivation_key = DiceBoundDerivationKey::OpaqueKey(Some(key));
+    let res = hw_crypto_key.deriveCurrentDicePolicyBoundKey(&derivation_key);
+    assert_eq!(
+        res.err()
+            .expect("should not be call this function from the host")
+            .service_specific_error(),
+        HalErrorCode::UNAUTHORIZED,
+        "wrong error type received"
+    );
+    let fake_policy = Vec::new();
+    let res = hw_crypto_key.deriveDicePolicyBoundKey(&derivation_key, &fake_policy);
+    assert_eq!(
+        res.err()
+            .expect("should not be call this function from the host")
+            .service_specific_error(),
+        HalErrorCode::UNAUTHORIZED,
+        "wrong error type received"
+    );
+    let key = hw_crypto_key.importClearKey(&clear_key, &policy).expect("couldn't import clear key");
+    let derived_policy = DerivedKeyPolicy::OpaqueKey(Vec::new());
+    let derived_parameters = DerivedKeyParameters {
+        derivationKey: Some(key),
+        keyPolicy: derived_policy,
+        context: Vec::new(),
+    };
+    let res = hw_crypto_key.deriveKey(&derived_parameters);
+    assert_eq!(
+        res.err()
+            .expect("should not be call this function from the host")
+            .service_specific_error(),
+        HalErrorCode::UNAUTHORIZED,
+        "wrong error type received"
+    );
+}
diff --git a/security/see/hwcrypto/aidl/vts/functional/lib.rs b/security/see/hwcrypto/aidl/vts/functional/lib.rs
index 81ae3fa..465dde7 100644
--- a/security/see/hwcrypto/aidl/vts/functional/lib.rs
+++ b/security/see/hwcrypto/aidl/vts/functional/lib.rs
@@ -17,61 +17,11 @@
 //! VTS test library for HwCrypto functionality.
 //! It provides the base clases necessaries to write HwCrypto VTS tests
 
-#[cfg(target_arch = "x86_64")]
-use anyhow::Context;
 use anyhow::Result;
-#[cfg(target_arch = "x86_64")]
-use binder::{ExceptionCode, FromIBinder, IntoBinderResult, ParcelFileDescriptor};
-#[cfg(target_arch = "x86_64")]
-use rpcbinder::RpcSession;
-#[cfg(target_arch = "x86_64")]
-use vsock::VsockStream;
-#[cfg(target_arch = "x86_64")]
-use std::os::fd::{FromRawFd, IntoRawFd};
-#[cfg(target_arch = "x86_64")]
-use std::fs::File;
-#[cfg(target_arch = "x86_64")]
-use std::io::Read;
-#[cfg(target_arch = "x86_64")]
-use rustutils::system_properties;
-#[cfg(target_arch = "aarch64")]
 use android_hardware_security_see_hwcrypto::aidl::android::hardware::security::see::hwcrypto::IHwCryptoKey::BpHwCryptoKey;
 use android_hardware_security_see_hwcrypto::aidl::android::hardware::security::see::hwcrypto::IHwCryptoKey::IHwCryptoKey;
 
-#[cfg(target_arch = "x86_64")]
-const HWCRYPTO_SERVICE_PORT: u32 = 4;
-
-/// Local function to connect to service
-#[cfg(target_arch = "x86_64")]
-pub fn connect_service<T: FromIBinder + ?Sized>(
-    cid: u32,
-    port: u32,
-) -> Result<binder::Strong<T>, binder::StatusCode> {
-    RpcSession::new().setup_preconnected_client(|| {
-        let mut stream = VsockStream::connect_with_cid_port(cid, port).ok()?;
-        let mut buffer = [0];
-        let _ = stream.read(&mut buffer);
-        // SAFETY: ownership is transferred from stream to f
-        let f = unsafe { File::from_raw_fd(stream.into_raw_fd()) };
-        Some(ParcelFileDescriptor::new(f).into_raw_fd())
-    })
-}
-
-/// Get a HwCryptoKey binder service object using a direct vsock connection
-#[cfg(target_arch = "x86_64")]
-pub fn get_hwcryptokey() -> Result<binder::Strong<dyn IHwCryptoKey>, binder::Status> {
-    let cid = system_properties::read("trusty.test_vm.vm_cid")
-        .context("couldn't get vm cid")
-        .or_binder_exception(ExceptionCode::ILLEGAL_STATE)?
-        .ok_or(ExceptionCode::ILLEGAL_STATE)?
-        .parse::<u32>()
-        .context("couldn't parse vm cid")
-        .or_binder_exception(ExceptionCode::ILLEGAL_ARGUMENT)?;
-    Ok(connect_service(cid, HWCRYPTO_SERVICE_PORT)?)
-}
-
 /// Get a HwCryptoKey binder service object using the service manager
-#[cfg(target_arch = "aarch64")]
 pub fn get_hwcryptokey() -> Result<binder::Strong<dyn IHwCryptoKey>, binder::Status> {
     let interface_name = <BpHwCryptoKey as IHwCryptoKey>::get_descriptor().to_owned() + "/default";
     Ok(binder::get_interface(&interface_name)?)
diff --git a/security/see/hwcrypto/default/Android.bp b/security/see/hwcrypto/default/Android.bp
index ab23cfd..7a4a7b6 100644
--- a/security/see/hwcrypto/default/Android.bp
+++ b/security/see/hwcrypto/default/Android.bp
@@ -112,6 +112,7 @@
 cc_test {
     name: "HwCryptoHalDelegatorTests",
     enabled: false,
+    require_root: true,
     srcs: [
         "delegatorTest.cpp",
     ],
@@ -124,12 +125,14 @@
     shared_libs: [
         "libbase",
         "liblog",
+        "libutils",
         "libbinder",
         "libbinder_ndk",
     ],
     static_libs: [
         "android.hardware.security.see.hwcrypto-V1-ndk",
         "android.hardware.security.see.hwcrypto-V1-cpp",
+        "hwcryptohallib",
     ],
 
     arch: {
diff --git a/security/see/hwcrypto/default/delegatorTest.cpp b/security/see/hwcrypto/default/delegatorTest.cpp
index a80d6fd..28b177d 100644
--- a/security/see/hwcrypto/default/delegatorTest.cpp
+++ b/security/see/hwcrypto/default/delegatorTest.cpp
@@ -1,11 +1,84 @@
+#include <android/binder_manager.h>
 #include <gtest/gtest.h>
+#include <linux/dma-heap.h>
+#include <sys/auxv.h>
+#include <sys/mman.h>
 #include "hwcryptokeyimpl.h"
 
+static inline bool align_overflow(size_t size, size_t alignment, size_t* aligned) {
+    if (size % alignment == 0) {
+        *aligned = size;
+        return false;
+    }
+    size_t temp = 0;
+    bool overflow = __builtin_add_overflow(size / alignment, 1, &temp);
+    overflow |= __builtin_mul_overflow(temp, alignment, aligned);
+    return overflow;
+}
+
+static int allocate_buffers(size_t size) {
+    const char* device_name = "/dev/dma_heap/system";
+    int dma_heap_fd = open(device_name, O_RDONLY | O_CLOEXEC);
+    if (dma_heap_fd < 0) {
+        LOG(ERROR) << "Cannot open " << device_name;
+        return -1;
+    }
+    size_t aligned = 0;
+    if (align_overflow(size, getauxval(AT_PAGESZ), &aligned)) {
+        LOG(ERROR) << "Rounding up buffer size oveflowed";
+        return -1;
+    }
+    struct dma_heap_allocation_data allocation_request = {
+            .len = aligned,
+            .fd_flags = O_RDWR | O_CLOEXEC,
+    };
+    int rc = ioctl(dma_heap_fd, DMA_HEAP_IOCTL_ALLOC, &allocation_request);
+    if (rc < 0) {
+        LOG(ERROR) << "Buffer allocation request failed  " << rc;
+        return -1;
+    }
+    int fd = allocation_request.fd;
+    if (fd < 0) {
+        LOG(ERROR) << "Allocation request returned bad fd" << fd;
+        return -1;
+    }
+    return fd;
+}
+
 int main(int argc, char** argv) {
     ::testing::InitGoogleTest(&argc, argv);
     return RUN_ALL_TESTS();
 }
 
+TEST(HwCryptoHalDelegator, FdTest) {
+    const std::string instance =
+            std::string() + ndk_hwcrypto::IHwCryptoKey::descriptor + "/default";
+    ndk::SpAIBinder binder(AServiceManager_waitForService(instance.c_str()));
+    ASSERT_NE(binder, nullptr);
+    auto hwCryptoKey = ndk_hwcrypto::IHwCryptoKey::fromBinder(binder);
+    ASSERT_NE(hwCryptoKey, nullptr);
+    auto fd = allocate_buffers(4096);
+    EXPECT_GE(fd, 0);
+    ndk::ScopedFileDescriptor ndkFd(fd);
+    ndk_hwcrypto::MemoryBufferParameter memBuffParam = ndk_hwcrypto::MemoryBufferParameter();
+    memBuffParam.bufferHandle.set<ndk_hwcrypto::MemoryBufferParameter::MemoryBuffer::input>(
+            std::move(ndkFd));
+    memBuffParam.sizeBytes = 4096;
+    auto operation = ndk_hwcrypto::CryptoOperation();
+    operation.set<ndk_hwcrypto::CryptoOperation::setMemoryBuffer>(std::move(memBuffParam));
+    ndk_hwcrypto::CryptoOperationSet operationSet = ndk_hwcrypto::CryptoOperationSet();
+    operationSet.context = nullptr;
+    operationSet.operations.push_back(std::move(operation));
+    std::vector<ndk_hwcrypto::CryptoOperationSet> operationSets;
+    operationSets.push_back(std::move(operationSet));
+    std::vector<ndk_hwcrypto::CryptoOperationResult> aidl_return;
+    std::shared_ptr<ndk_hwcrypto::IHwCryptoOperations> hwCryptoOperations;
+    auto res = hwCryptoKey->getHwCryptoOperations(&hwCryptoOperations);
+    EXPECT_TRUE(res.isOk());
+    res = hwCryptoOperations->processCommandList(&operationSets, &aidl_return);
+    EXPECT_TRUE(res.isOk());
+}
+
 TEST(HwCryptoHalDelegator, keyPolicyCppToNdk) {
     cpp_hwcrypto::KeyPolicy cppPolicy = cpp_hwcrypto::KeyPolicy();
     cppPolicy.keyType = cpp_hwcrypto::types::KeyType::AES_128_CBC_PKCS7_PADDING;
@@ -46,4 +119,4 @@
               cpp_hwcrypto::types::KeyPermissions::ALLOW_EPHEMERAL_KEY_WRAPPING);
     EXPECT_EQ(cppPolicy.keyPermissions[1],
               cpp_hwcrypto::types::KeyPermissions::ALLOW_HARDWARE_KEY_WRAPPING);
-}
\ No newline at end of file
+}
diff --git a/security/see/hwcrypto/default/hwcryptokeyimpl.h b/security/see/hwcrypto/default/hwcryptokeyimpl.h
index 19be8b4..7d3ade7 100644
--- a/security/see/hwcrypto/default/hwcryptokeyimpl.h
+++ b/security/see/hwcrypto/default/hwcryptokeyimpl.h
@@ -46,30 +46,33 @@
 
     ndk::ScopedAStatus deriveCurrentDicePolicyBoundKey(
             const ndk_hwcrypto::IHwCryptoKey::DiceBoundDerivationKey& derivationKey,
-            ndk_hwcrypto::IHwCryptoKey::DiceCurrentBoundKeyResult* aidl_return);
+            ndk_hwcrypto::IHwCryptoKey::DiceCurrentBoundKeyResult* aidl_return) override;
 
     ndk::ScopedAStatus deriveDicePolicyBoundKey(
             const ndk_hwcrypto::IHwCryptoKey::DiceBoundDerivationKey& derivationKey,
             const ::std::vector<uint8_t>& dicePolicyForKeyVersion,
-            ndk_hwcrypto::IHwCryptoKey::DiceBoundKeyResult* aidl_return);
+            ndk_hwcrypto::IHwCryptoKey::DiceBoundKeyResult* aidl_return) override;
     ndk::ScopedAStatus deriveKey(const ndk_hwcrypto::IHwCryptoKey::DerivedKeyParameters& parameters,
-                                 ndk_hwcrypto::IHwCryptoKey::DerivedKey* aidl_return);
+                                 ndk_hwcrypto::IHwCryptoKey::DerivedKey* aidl_return) override;
 
     ndk::ScopedAStatus getHwCryptoOperations(
-            std::shared_ptr<ndk_hwcrypto::IHwCryptoOperations>* aidl_return);
+            std::shared_ptr<ndk_hwcrypto::IHwCryptoOperations>* aidl_return) override;
 
-    ndk::ScopedAStatus importClearKey(const ndk_hwcrypto::types::ExplicitKeyMaterial& keyMaterial,
-                                      const ndk_hwcrypto::KeyPolicy& newKeyPolicy,
-                                      std::shared_ptr<ndk_hwcrypto::IOpaqueKey>* aidl_return);
+    ndk::ScopedAStatus importClearKey(
+            const ndk_hwcrypto::types::ExplicitKeyMaterial& keyMaterial,
+            const ndk_hwcrypto::KeyPolicy& newKeyPolicy,
+            std::shared_ptr<ndk_hwcrypto::IOpaqueKey>* aidl_return) override;
 
-    ndk::ScopedAStatus getCurrentDicePolicy(std::vector<uint8_t>* aidl_return);
+    ndk::ScopedAStatus getCurrentDicePolicy(std::vector<uint8_t>* aidl_return) override;
 
-    ndk::ScopedAStatus keyTokenImport(const ndk_hwcrypto::types::OpaqueKeyToken& requestedKey,
-                                      const ::std::vector<uint8_t>& sealingDicePolicy,
-                                      std::shared_ptr<ndk_hwcrypto::IOpaqueKey>* aidl_return);
+    ndk::ScopedAStatus keyTokenImport(
+            const ndk_hwcrypto::types::OpaqueKeyToken& requestedKey,
+            const ::std::vector<uint8_t>& sealingDicePolicy,
+            std::shared_ptr<ndk_hwcrypto::IOpaqueKey>* aidl_return) override;
 
-    ndk::ScopedAStatus getKeyslotData(ndk_hwcrypto::IHwCryptoKey::KeySlot slotId,
-                                      std::shared_ptr<ndk_hwcrypto::IOpaqueKey>* aidl_return);
+    ndk::ScopedAStatus getKeyslotData(
+            ndk_hwcrypto::IHwCryptoKey::KeySlot slotId,
+            std::shared_ptr<ndk_hwcrypto::IOpaqueKey>* aidl_return) override;
 };
 
 template <typename LHP, typename RHP>
@@ -79,9 +82,10 @@
     policy.keyLifetime = static_cast<decltype(policy.keyLifetime)>(policyToConvert.keyLifetime);
     policy.keyType = static_cast<decltype(policy.keyType)>(policyToConvert.keyType);
     policy.keyManagementKey = policyToConvert.keyManagementKey;
+    policy.keyPermissions.reserve(policyToConvert.keyPermissions.size());
     for (auto permission : policyToConvert.keyPermissions) {
         policy.keyPermissions.push_back(
-                std::move(reinterpret_cast<decltype(policy.keyPermissions[0])>(permission)));
+                std::move(static_cast<decltype(policy.keyPermissions)::value_type>(permission)));
     }
     return policy;
 }
diff --git a/security/see/hwcrypto/default/hwcryptolib.cpp b/security/see/hwcrypto/default/hwcryptolib.cpp
index 0e15883..a7ecca1 100644
--- a/security/see/hwcrypto/default/hwcryptolib.cpp
+++ b/security/see/hwcrypto/default/hwcryptolib.cpp
@@ -115,11 +115,14 @@
 class HwCryptoOperationContextNdk : public ndk_hwcrypto::BnCryptoOperationContext {
   private:
     sp<cpp_hwcrypto::ICryptoOperationContext> mContext;
+    std::weak_ptr<ndk_hwcrypto::ICryptoOperationContext> self;
 
   public:
     HwCryptoOperationContextNdk(sp<cpp_hwcrypto::ICryptoOperationContext> operations)
         : mContext(std::move(operations)) {}
 
+    ~HwCryptoOperationContextNdk() { contextMapping.erase(self); }
+
     static std::shared_ptr<HwCryptoOperationContextNdk> Create(
             sp<cpp_hwcrypto::ICryptoOperationContext> operations) {
         if (operations == nullptr) {
@@ -132,18 +135,18 @@
             LOG(ERROR) << "failed to allocate HwCryptoOperationContext";
             return nullptr;
         }
+        contextNdk->self = contextNdk;
         return contextNdk;
     }
 };
 
-// TODO: Check refactoring opportunities like returning a Result<cpp_hwcrypto::types::OperationData>
-//       once we add the code that uses this function.
-Result<void> setOperationData(const ndk_hwcrypto::types::OperationData& ndkOperationData,
-                              cpp_hwcrypto::types::OperationData* cppOperationData) {
+std::optional<cpp_hwcrypto::types::OperationData> convertOperationData(
+        const ndk_hwcrypto::types::OperationData& ndkOperationData) {
+    cpp_hwcrypto::types::OperationData cppOperationData = cpp_hwcrypto::types::OperationData();
     cpp_hwcrypto::types::MemoryBufferReference cppMemBuffRef;
     switch (ndkOperationData.getTag()) {
         case ndk_hwcrypto::types::OperationData::dataBuffer:
-            cppOperationData->set<cpp_hwcrypto::types::OperationData::dataBuffer>(
+            cppOperationData.set<cpp_hwcrypto::types::OperationData::dataBuffer>(
                     ndkOperationData.get<ndk_hwcrypto::types::OperationData::dataBuffer>());
             break;
         case ndk_hwcrypto::types::OperationData::memoryBufferReference:
@@ -155,14 +158,253 @@
                     ndkOperationData
                             .get<ndk_hwcrypto::types::OperationData::memoryBufferReference>()
                             .sizeBytes;
-            cppOperationData->set<cpp_hwcrypto::types::OperationData::memoryBufferReference>(
+            cppOperationData.set<cpp_hwcrypto::types::OperationData::memoryBufferReference>(
                     std::move(cppMemBuffRef));
             break;
         default:
-            // This shouldn't happen with the current definitions
-            return ErrnoError() << "received unknown operation data type";
+            LOG(ERROR) << "received unknown operation data type";
+            return std::nullopt;
     }
-    return {};
+    return cppOperationData;
+}
+
+std::optional<cpp_hwcrypto::PatternParameters> convertPatternParameters(
+        const ndk_hwcrypto::PatternParameters& ndkpatternParameters) {
+    int64_t numberBlocksProcess = ndkpatternParameters.numberBlocksProcess;
+    int64_t numberBlocksCopy = ndkpatternParameters.numberBlocksCopy;
+    if ((numberBlocksProcess < 0) || (numberBlocksCopy < 0)) {
+        LOG(ERROR) << "received invalid pattern parameters";
+        return std::nullopt;
+    }
+    cpp_hwcrypto::PatternParameters patternParameters = cpp_hwcrypto::PatternParameters();
+    patternParameters.numberBlocksProcess = numberBlocksProcess;
+    patternParameters.numberBlocksCopy = numberBlocksCopy;
+    return patternParameters;
+}
+
+std::optional<cpp_hwcrypto::types::SymmetricOperation> convertSymmetricOperation(
+        const ndk_hwcrypto::types::SymmetricOperation& ndkSymmetricOperation) {
+    cpp_hwcrypto::types::SymmetricOperation symmetricOperation =
+            cpp_hwcrypto::types::SymmetricOperation();
+    switch (ndkSymmetricOperation) {
+        case ndk_hwcrypto::types::SymmetricOperation::ENCRYPT:
+            symmetricOperation = cpp_hwcrypto::types::SymmetricOperation::ENCRYPT;
+            break;
+        case ndk_hwcrypto::types::SymmetricOperation::DECRYPT:
+            symmetricOperation = cpp_hwcrypto::types::SymmetricOperation::DECRYPT;
+            break;
+        default:
+            LOG(ERROR) << "invalid symmetric operation type";
+            return std::nullopt;
+    }
+    return symmetricOperation;
+}
+
+cpp_hwcrypto::types::CipherModeParameters convertSymmetricModeParameters(
+        const ndk_hwcrypto::types::CipherModeParameters& ndkcipherModeParameters) {
+    cpp_hwcrypto::types::CipherModeParameters cipherModeParameters =
+            cpp_hwcrypto::types::CipherModeParameters();
+    cipherModeParameters.nonce = ndkcipherModeParameters.nonce;
+    return cipherModeParameters;
+}
+
+cpp_hwcrypto::types::AesGcmMode::AesGcmModeParameters convertSymmetricModeParameters(
+        const ndk_hwcrypto::types::AesGcmMode::AesGcmModeParameters& ndkgcmModeParameters) {
+    cpp_hwcrypto::types::AesGcmMode::AesGcmModeParameters gcmModeParameters =
+            cpp_hwcrypto::types::AesGcmMode::AesGcmModeParameters();
+    gcmModeParameters.nonce = ndkgcmModeParameters.nonce;
+    return gcmModeParameters;
+}
+
+std::optional<cpp_hwcrypto::MemoryBufferParameter> convertMemoryBufferParameters(
+        const ndk_hwcrypto::MemoryBufferParameter& ndkMemBuffParams) {
+    cpp_hwcrypto::MemoryBufferParameter memBuffParams = cpp_hwcrypto::MemoryBufferParameter();
+    memBuffParams.sizeBytes = ndkMemBuffParams.sizeBytes;
+    android::os::ParcelFileDescriptor pfd;
+    ndk::ScopedFileDescriptor ndkFd;
+    switch (ndkMemBuffParams.bufferHandle.getTag()) {
+        case ndk_hwcrypto::MemoryBufferParameter::MemoryBuffer::input:
+            ndkFd = ndkMemBuffParams.bufferHandle
+                            .get<ndk_hwcrypto::MemoryBufferParameter::MemoryBuffer::input>()
+                            .dup();
+            pfd.reset(binder::unique_fd(ndkFd.release()));
+            memBuffParams.bufferHandle
+                    .set<cpp_hwcrypto::MemoryBufferParameter::MemoryBuffer::input>(std::move(pfd));
+            break;
+        case ndk_hwcrypto::MemoryBufferParameter::MemoryBuffer::output:
+            ndkFd = ndkMemBuffParams.bufferHandle
+                            .get<ndk_hwcrypto::MemoryBufferParameter::MemoryBuffer::output>()
+                            .dup();
+            pfd.reset(binder::unique_fd(ndkFd.release()));
+            memBuffParams.bufferHandle
+                    .set<cpp_hwcrypto::MemoryBufferParameter::MemoryBuffer::output>(std::move(pfd));
+            break;
+        default:
+            LOG(ERROR) << "unknown bufferHandle type";
+            return std::nullopt;
+    }
+    return memBuffParams;
+}
+
+std::optional<cpp_hwcrypto::OperationParameters> convertOperationParameters(
+        const ndk_hwcrypto::OperationParameters& ndkOperationParameters) {
+    cpp_hwcrypto::OperationParameters operationParameters = cpp_hwcrypto::OperationParameters();
+    sp<cpp_hwcrypto::IOpaqueKey> opaqueKey;
+    cpp_hwcrypto::types::HmacOperationParameters hmacParameters =
+            cpp_hwcrypto::types::HmacOperationParameters();
+    std::optional<cpp_hwcrypto::types::SymmetricOperation> cppSymmetricOperation;
+    cpp_hwcrypto::types::CipherModeParameters cipherModeParameters;
+    cpp_hwcrypto::types::AesCipherMode cppAesCipherMode = cpp_hwcrypto::types::AesCipherMode();
+    cpp_hwcrypto::types::SymmetricOperationParameters cppSymmetricOperationParameters =
+            cpp_hwcrypto::types::SymmetricOperationParameters();
+    cpp_hwcrypto::types::SymmetricAuthOperationParameters cppSymmetricAuthOperationParameters =
+            cpp_hwcrypto::types::SymmetricAuthOperationParameters();
+    cpp_hwcrypto::types::AesGcmMode::AesGcmModeParameters cppAesGcmModeParameters =
+            cpp_hwcrypto::types::AesGcmMode::AesGcmModeParameters();
+    cpp_hwcrypto::types::AesGcmMode cppAesGcmMode = cpp_hwcrypto::types::AesGcmMode();
+    switch (ndkOperationParameters.getTag()) {
+        case ndk_hwcrypto::OperationParameters::symmetricAuthCrypto:
+            opaqueKey = retrieveCppBinder<cpp_hwcrypto::IOpaqueKey, ndk_hwcrypto::IOpaqueKey,
+                                          keyMapping>(
+                    ndkOperationParameters
+                            .get<ndk_hwcrypto::OperationParameters::symmetricAuthCrypto>()
+                            .key);
+            if (!opaqueKey) {
+                LOG(ERROR) << "couldn't get aes key";
+                return std::nullopt;
+            }
+            cppSymmetricAuthOperationParameters.key = std::move(opaqueKey);
+            cppSymmetricOperation = convertSymmetricOperation(
+                    ndkOperationParameters
+                            .get<ndk_hwcrypto::OperationParameters::symmetricAuthCrypto>()
+                            .direction);
+            if (!cppSymmetricOperation.has_value()) {
+                LOG(ERROR) << "couldn't get aes direction";
+                return std::nullopt;
+            }
+            cppSymmetricAuthOperationParameters.direction =
+                    std::move(cppSymmetricOperation.value());
+            switch (ndkOperationParameters
+                            .get<ndk_hwcrypto::OperationParameters::symmetricAuthCrypto>()
+                            .parameters.getTag()) {
+                case ndk_hwcrypto::types::SymmetricAuthCryptoParameters::aes:
+                    switch (ndkOperationParameters
+                                    .get<ndk_hwcrypto::OperationParameters::symmetricAuthCrypto>()
+                                    .parameters
+                                    .get<ndk_hwcrypto::types::SymmetricAuthCryptoParameters::aes>()
+                                    .getTag()) {
+                        case ndk_hwcrypto::types::AesGcmMode::gcmTag16:
+                            cppAesGcmModeParameters = convertSymmetricModeParameters(
+                                    ndkOperationParameters
+                                            .get<ndk_hwcrypto::OperationParameters::
+                                                         symmetricAuthCrypto>()
+                                            .parameters
+                                            .get<ndk_hwcrypto::types::
+                                                         SymmetricAuthCryptoParameters::aes>()
+                                            .get<ndk_hwcrypto::types::AesGcmMode::gcmTag16>());
+                            cppAesGcmMode.set<cpp_hwcrypto::types::AesGcmMode::gcmTag16>(
+                                    std::move(cppAesGcmModeParameters));
+                            cppSymmetricAuthOperationParameters.parameters
+                                    .set<cpp_hwcrypto::types::SymmetricAuthCryptoParameters::aes>(
+                                            std::move(cppAesGcmMode));
+                            break;
+                        default:
+                            LOG(ERROR) << "received invalid aes gcm parameters";
+                            return std::nullopt;
+                    }
+                    break;
+                default:
+                    LOG(ERROR) << "received invalid symmetric auth crypto parameters";
+                    return std::nullopt;
+            }
+            operationParameters.set<cpp_hwcrypto::OperationParameters::symmetricAuthCrypto>(
+                    std::move(cppSymmetricAuthOperationParameters));
+            break;
+        case ndk_hwcrypto::OperationParameters::symmetricCrypto:
+            opaqueKey = retrieveCppBinder<cpp_hwcrypto::IOpaqueKey, ndk_hwcrypto::IOpaqueKey,
+                                          keyMapping>(
+                    ndkOperationParameters.get<ndk_hwcrypto::OperationParameters::symmetricCrypto>()
+                            .key);
+            if (!opaqueKey) {
+                LOG(ERROR) << "couldn't get aes key";
+                return std::nullopt;
+            }
+            cppSymmetricOperationParameters.key = std::move(opaqueKey);
+            cppSymmetricOperation = convertSymmetricOperation(
+                    ndkOperationParameters.get<ndk_hwcrypto::OperationParameters::symmetricCrypto>()
+                            .direction);
+            if (!cppSymmetricOperation.has_value()) {
+                LOG(ERROR) << "couldn't get aes direction";
+                return std::nullopt;
+            }
+            cppSymmetricOperationParameters.direction = std::move(cppSymmetricOperation.value());
+            switch (ndkOperationParameters.get<ndk_hwcrypto::OperationParameters::symmetricCrypto>()
+                            .parameters.getTag()) {
+                case ndk_hwcrypto::types::SymmetricCryptoParameters::aes:
+                    switch (ndkOperationParameters
+                                    .get<ndk_hwcrypto::OperationParameters::symmetricCrypto>()
+                                    .parameters
+                                    .get<ndk_hwcrypto::types::SymmetricCryptoParameters::aes>()
+                                    .getTag()) {
+                        case ndk_hwcrypto::types::AesCipherMode::cbc:
+                            cipherModeParameters = convertSymmetricModeParameters(
+                                    ndkOperationParameters
+                                            .get<ndk_hwcrypto::OperationParameters::
+                                                         symmetricCrypto>()
+                                            .parameters
+                                            .get<ndk_hwcrypto::types::SymmetricCryptoParameters::
+                                                         aes>()
+                                            .get<ndk_hwcrypto::types::AesCipherMode::cbc>());
+                            cppAesCipherMode.set<cpp_hwcrypto::types::AesCipherMode::cbc>(
+                                    std::move(cipherModeParameters));
+                            cppSymmetricOperationParameters.parameters
+                                    .set<cpp_hwcrypto::types::SymmetricCryptoParameters::aes>(
+                                            std::move(cppAesCipherMode));
+                            break;
+                        case ndk_hwcrypto::types::AesCipherMode::ctr:
+                            cipherModeParameters = convertSymmetricModeParameters(
+                                    ndkOperationParameters
+                                            .get<ndk_hwcrypto::OperationParameters::
+                                                         symmetricCrypto>()
+                                            .parameters
+                                            .get<ndk_hwcrypto::types::SymmetricCryptoParameters::
+                                                         aes>()
+                                            .get<ndk_hwcrypto::types::AesCipherMode::ctr>());
+                            cppAesCipherMode.set<cpp_hwcrypto::types::AesCipherMode::ctr>(
+                                    std::move(cipherModeParameters));
+                            cppSymmetricOperationParameters.parameters
+                                    .set<cpp_hwcrypto::types::SymmetricCryptoParameters::aes>(
+                                            std::move(cppAesCipherMode));
+                            break;
+                        default:
+                            LOG(ERROR) << "received invalid aes parameters";
+                            return std::nullopt;
+                    }
+                    break;
+                default:
+                    LOG(ERROR) << "received invalid symmetric crypto parameters";
+                    return std::nullopt;
+            }
+            operationParameters.set<cpp_hwcrypto::OperationParameters::symmetricCrypto>(
+                    std::move(cppSymmetricOperationParameters));
+            break;
+        case ndk_hwcrypto::OperationParameters::hmac:
+            opaqueKey = retrieveCppBinder<cpp_hwcrypto::IOpaqueKey, ndk_hwcrypto::IOpaqueKey,
+                                          keyMapping>(
+                    ndkOperationParameters.get<ndk_hwcrypto::OperationParameters::hmac>().key);
+            if (!opaqueKey) {
+                LOG(ERROR) << "couldn't get hmac key";
+                return std::nullopt;
+            }
+            hmacParameters.key = opaqueKey;
+            operationParameters.set<cpp_hwcrypto::OperationParameters::hmac>(
+                    std::move(hmacParameters));
+            break;
+        default:
+            LOG(ERROR) << "received invalid operation parameters";
+            return std::nullopt;
+    }
+    return operationParameters;
 }
 
 class HwCryptoOperationsNdk : public ndk_hwcrypto::BnHwCryptoOperations {
@@ -189,19 +431,215 @@
     }
 
     ndk::ScopedAStatus processCommandList(
-            std::vector<ndk_hwcrypto::CryptoOperationSet>* /*operationSets*/,
-            std::vector<ndk_hwcrypto::CryptoOperationResult>* /*aidl_return*/) {
-        return ndk::ScopedAStatus::ok();
+            std::vector<ndk_hwcrypto::CryptoOperationSet>* operationSets,
+            std::vector<ndk_hwcrypto::CryptoOperationResult>* aidl_return) {
+        Status status = Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
+        if (operationSets == nullptr) {
+            LOG(ERROR) << "received a null operation set";
+            return convertStatus(status);
+        }
+        if (aidl_return == nullptr) {
+            LOG(ERROR) << "received a null CryptoOperationResult set";
+            return convertStatus(status);
+        }
+        std::vector<cpp_hwcrypto::CryptoOperationResult> binderResult;
+        std::vector<cpp_hwcrypto::CryptoOperationSet> cppOperationSets;
+        for (ndk_hwcrypto::CryptoOperationSet& operationSet : *operationSets) {
+            cpp_hwcrypto::CryptoOperationSet cppSingleOperation =
+                    cpp_hwcrypto::CryptoOperationSet();
+            cppSingleOperation.context =
+                    retrieveCppBinder<cpp_hwcrypto::ICryptoOperationContext,
+                                      ndk_hwcrypto::ICryptoOperationContext, contextMapping>(
+                            operationSet.context);
+            for (ndk_hwcrypto::CryptoOperation& operation : operationSet.operations) {
+                cpp_hwcrypto::CryptoOperation cppOperation;
+                cpp_hwcrypto::types::Void voidObj;
+                std::optional<cpp_hwcrypto::types::OperationData> cppOperationData;
+                std::optional<cpp_hwcrypto::PatternParameters> cppPatternParameters;
+                std::optional<cpp_hwcrypto::OperationParameters> cppOperationParameters;
+                std::optional<cpp_hwcrypto::MemoryBufferParameter> cppMemBuffParams;
+                switch (operation.getTag()) {
+                    case ndk_hwcrypto::CryptoOperation::setMemoryBuffer:
+                        cppMemBuffParams = convertMemoryBufferParameters(
+                                operation.get<ndk_hwcrypto::CryptoOperation::setMemoryBuffer>());
+                        if (cppMemBuffParams.has_value()) {
+                            cppOperation.set<cpp_hwcrypto::CryptoOperation::setMemoryBuffer>(
+                                    std::move(cppMemBuffParams.value()));
+                        } else {
+                            return convertStatus(status);
+                        }
+                        break;
+                    case ndk_hwcrypto::CryptoOperation::setOperationParameters:
+                        cppOperationParameters = convertOperationParameters(
+                                operation.get<
+                                        ndk_hwcrypto::CryptoOperation::setOperationParameters>());
+                        if (cppOperationParameters.has_value()) {
+                            cppOperation.set<cpp_hwcrypto::CryptoOperation::setOperationParameters>(
+                                    std::move(cppOperationParameters.value()));
+                        } else {
+                            LOG(ERROR) << "couldn't convert operation parameters";
+                            return convertStatus(status);
+                        }
+                        break;
+                    case ndk_hwcrypto::CryptoOperation::setPattern:
+                        cppPatternParameters = convertPatternParameters(
+                                operation.get<ndk_hwcrypto::CryptoOperation::setPattern>());
+                        if (cppPatternParameters.has_value()) {
+                            cppOperation.set<cpp_hwcrypto::CryptoOperation::setPattern>(
+                                    std::move(cppPatternParameters.value()));
+                        } else {
+                            LOG(ERROR) << "couldn't convert pattern parameters";
+                            return convertStatus(status);
+                        }
+                        break;
+                    case ndk_hwcrypto::CryptoOperation::copyData:
+                        cppOperationData = convertOperationData(
+                                operation.get<ndk_hwcrypto::CryptoOperation::copyData>());
+                        if (cppOperationData.has_value()) {
+                            cppOperation.set<cpp_hwcrypto::CryptoOperation::copyData>(
+                                    std::move(cppOperationData.value()));
+                        } else {
+                            LOG(ERROR) << "couldn't convert CryptoOperation::copyData";
+                            return convertStatus(status);
+                        }
+                        break;
+                    case ndk_hwcrypto::CryptoOperation::aadInput:
+                        cppOperationData = convertOperationData(
+                                operation.get<ndk_hwcrypto::CryptoOperation::aadInput>());
+                        if (cppOperationData.has_value()) {
+                            cppOperation.set<cpp_hwcrypto::CryptoOperation::aadInput>(
+                                    std::move(cppOperationData.value()));
+                        } else {
+                            LOG(ERROR) << "couldn't convert CryptoOperation::aadInput";
+                            return convertStatus(status);
+                        }
+                        break;
+                    case ndk_hwcrypto::CryptoOperation::dataInput:
+                        cppOperationData = convertOperationData(
+                                operation.get<ndk_hwcrypto::CryptoOperation::dataInput>());
+                        if (cppOperationData.has_value()) {
+                            cppOperation.set<cpp_hwcrypto::CryptoOperation::dataInput>(
+                                    std::move(cppOperationData.value()));
+                        } else {
+                            LOG(ERROR) << "couldn't convert CryptoOperation::dataInput";
+                            return convertStatus(status);
+                        }
+                        break;
+                    case ndk_hwcrypto::CryptoOperation::dataOutput:
+                        cppOperationData = convertOperationData(
+                                operation.get<ndk_hwcrypto::CryptoOperation::dataOutput>());
+                        if (cppOperationData.has_value()) {
+                            cppOperation.set<cpp_hwcrypto::CryptoOperation::dataOutput>(
+                                    std::move(cppOperationData.value()));
+                        } else {
+                            LOG(ERROR) << "couldn't convert CryptoOperation::dataOutput";
+                            return convertStatus(status);
+                        }
+                        break;
+                    case ndk_hwcrypto::CryptoOperation::destroyContext:
+                        cppOperation.set<cpp_hwcrypto::CryptoOperation::destroyContext>(
+                                std::move(voidObj));
+                        break;
+                    case ndk_hwcrypto::CryptoOperation::finish:
+                        cppOperation.set<cpp_hwcrypto::CryptoOperation::finish>(std::move(voidObj));
+                        break;
+                    default:
+                        // This shouldn't happen
+                        LOG(ERROR) << "received unknown crypto operation";
+                        return convertStatus(status);
+                }
+                cppSingleOperation.operations.push_back(std::move(cppOperation));
+            }
+            cppOperationSets.push_back(std::move(cppSingleOperation));
+        }
+        status = mHwCryptoOperations->processCommandList(&cppOperationSets, &binderResult);
+        if (status.isOk()) {
+            *aidl_return = std::vector<ndk_hwcrypto::CryptoOperationResult>();
+            for (cpp_hwcrypto::CryptoOperationResult& result : binderResult) {
+                ndk_hwcrypto::CryptoOperationResult ndkResult =
+                        ndk_hwcrypto::CryptoOperationResult();
+                if (result.context != nullptr) {
+                    insertBinderMapping<cpp_hwcrypto::ICryptoOperationContext,
+                                        ndk_hwcrypto::ICryptoOperationContext,
+                                        HwCryptoOperationContextNdk, contextMapping>(
+                            result.context, &ndkResult.context);
+                } else {
+                    ndkResult.context = nullptr;
+                }
+                aidl_return->push_back(std::move(ndkResult));
+            }
+        } else {
+            // No reason to copy back the data output vectors if this failed
+            LOG(ERROR) << "couldn't process command list";
+            return convertStatus(status);
+        }
+        // We need to copy the vectors from the cpp operations back to the ndk one
+        if (cppOperationSets.size() != operationSets->size()) {
+            LOG(ERROR) << "ndk and cpp operation sets had a different number of elements";
+            return convertStatus(Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT));
+        }
+        for (unsigned setIdx = 0; setIdx < cppOperationSets.size(); ++setIdx) {
+            if (cppOperationSets[setIdx].operations.size() !=
+                (*operationSets)[setIdx].operations.size()) {
+                LOG(ERROR) << "ndk and cpp operations on set " << setIdx
+                           << " had a different number of elements";
+                return convertStatus(Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT));
+            }
+            for (unsigned operationIdx = 0;
+                 operationIdx < cppOperationSets[setIdx].operations.size(); ++operationIdx) {
+                if (cppOperationSets[setIdx].operations[operationIdx].getTag() ==
+                    cpp_hwcrypto::CryptoOperation::dataOutput) {
+                    if ((*operationSets)[setIdx].operations[operationIdx].getTag() !=
+                        ndk_hwcrypto::CryptoOperation::dataOutput) {
+                        LOG(ERROR)
+                                << "ndk and cpp operations on set " << setIdx << " and operation "
+                                << operationIdx << " had a different operation type";
+                        return convertStatus(
+                                Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT));
+                    }
+                    if (cppOperationSets[setIdx]
+                                .operations[operationIdx]
+                                .get<cpp_hwcrypto::CryptoOperation::dataOutput>()
+                                .getTag() == cpp_hwcrypto::types::OperationData::dataBuffer) {
+                        // This is the only case on which we need to move the data backto the
+                        // original array
+                        if ((*operationSets)[setIdx]
+                                    .operations[operationIdx]
+                                    .get<ndk_hwcrypto::CryptoOperation::dataOutput>()
+                                    .getTag() != ndk_hwcrypto::types::OperationData::dataBuffer) {
+                            LOG(ERROR) << "ndk and cpp operations on set " << setIdx
+                                       << " and operation " << operationIdx
+                                       << " had a different operation data output type";
+                            return convertStatus(
+                                    Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT));
+                        }
+                        (*operationSets)[setIdx]
+                                .operations[operationIdx]
+                                .get<ndk_hwcrypto::CryptoOperation::dataOutput>()
+                                .set<ndk_hwcrypto::types::OperationData::dataBuffer>(
+                                        cppOperationSets[setIdx]
+                                                .operations[operationIdx]
+                                                .get<cpp_hwcrypto::CryptoOperation::dataOutput>()
+                                                .get<cpp_hwcrypto::types::OperationData::
+                                                             dataBuffer>());
+                    }
+                }
+            }
+        }
+        return convertStatus(status);
     }
 };
 
 class OpaqueKeyNdk : public ndk_hwcrypto::BnOpaqueKey {
   private:
     sp<cpp_hwcrypto::IOpaqueKey> mOpaqueKey;
+    std::weak_ptr<ndk_hwcrypto::IOpaqueKey> self;
 
   public:
     OpaqueKeyNdk(sp<cpp_hwcrypto::IOpaqueKey> opaqueKey) : mOpaqueKey(std::move(opaqueKey)) {}
 
+    ~OpaqueKeyNdk() { keyMapping.erase(self); }
+
     static std::shared_ptr<OpaqueKeyNdk> Create(sp<cpp_hwcrypto::IOpaqueKey> opaqueKey) {
         if (opaqueKey == nullptr) {
             return nullptr;
@@ -213,6 +651,7 @@
             LOG(ERROR) << "failed to allocate HwCryptoKey";
             return nullptr;
         }
+        opaqueKeyNdk->self = opaqueKeyNdk;
         return opaqueKeyNdk;
     }
 
@@ -271,13 +710,19 @@
     ndk::ScopedAStatus setProtectionId(
             const ndk_hwcrypto::types::ProtectionId /*protectionId*/,
             const ::std::vector<ndk_hwcrypto::types::OperationType>& /*allowedOperations*/) {
-        return ndk::ScopedAStatus::ok();
+        return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
+                ndk_hwcrypto::types::HalErrorCode::UNAUTHORIZED,
+                "android is not authorized to call setProtectionId");
     }
 };
 
 Result<void> HwCryptoKey::connectToTrusty(const char* tipcDev) {
     assert(!mSession);
-    mSession = RpcTrustyConnectWithSessionInitializer(tipcDev, HWCRYPTO_KEY_PORT, [](auto) {});
+    auto session_initializer = [](sp<RpcSession>& session) {
+        session->setFileDescriptorTransportMode(RpcSession::FileDescriptorTransportMode::TRUSTY);
+    };
+    mSession =
+            RpcTrustyConnectWithSessionInitializer(tipcDev, HWCRYPTO_KEY_PORT, session_initializer);
     if (!mSession) {
         return ErrnoError() << "failed to connect to hwcrypto";
     }
@@ -308,24 +753,26 @@
 ndk::ScopedAStatus HwCryptoKey::deriveCurrentDicePolicyBoundKey(
         const ndk_hwcrypto::IHwCryptoKey::DiceBoundDerivationKey& /*derivationKey*/,
         ndk_hwcrypto::IHwCryptoKey::DiceCurrentBoundKeyResult* /*aidl_return*/) {
-    // return mHwCryptoServer->deriveCurrentDicePolicyBoundKey(derivationKey, aidl_return);
-    return ndk::ScopedAStatus::ok();
+    return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
+            ndk_hwcrypto::types::HalErrorCode::UNAUTHORIZED,
+            "android is not authorized to call deriveCurrentDicePolicyBoundKey");
 }
 
 ndk::ScopedAStatus HwCryptoKey::deriveDicePolicyBoundKey(
         const ndk_hwcrypto::IHwCryptoKey::DiceBoundDerivationKey& /*derivationKey*/,
         const ::std::vector<uint8_t>& /*dicePolicyForKeyVersion*/,
         ndk_hwcrypto::IHwCryptoKey::DiceBoundKeyResult* /*aidl_return*/) {
-    // return mHwCryptoServer->deriveDicePolicyBoundKey(derivationKey, dicePolicyForKeyVersion,
-    // aidl_return);
-    return ndk::ScopedAStatus::ok();
+    return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
+            ndk_hwcrypto::types::HalErrorCode::UNAUTHORIZED,
+            "android is not authorized to call deriveDicePolicyBoundKey");
 }
 
 ndk::ScopedAStatus HwCryptoKey::deriveKey(
         const ndk_hwcrypto::IHwCryptoKey::DerivedKeyParameters& /*parameters*/,
         ndk_hwcrypto::IHwCryptoKey::DerivedKey* /*aidl_return*/) {
-    // return mHwCryptoServer->deriveKey(parameters, aidl_return);
-    return ndk::ScopedAStatus::ok();
+    return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
+            ndk_hwcrypto::types::HalErrorCode::UNAUTHORIZED,
+            "android is not authorized to call deriveKey");
 }
 
 ndk::ScopedAStatus HwCryptoKey::getHwCryptoOperations(
diff --git a/security/see/storage/default/Android.bp b/security/see/storage/default/Android.bp
new file mode 100644
index 0000000..7ea7739
--- /dev/null
+++ b/security/see/storage/default/Android.bp
@@ -0,0 +1,21 @@
+//
+// Copyright (C) 2025 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.
+
+prebuilt_etc {
+    name: "android.hardware.security.see.storage-service.trusty.xml",
+    sub_dir: "vintf",
+    vendor: true,
+    src: "android.hardware.security.see.storage-service.trusty.xml",
+}
diff --git a/security/see/storage/default/android.hardware.security.see.storage-service.trusty.xml b/security/see/storage/default/android.hardware.security.see.storage-service.trusty.xml
new file mode 100644
index 0000000..89f3839
--- /dev/null
+++ b/security/see/storage/default/android.hardware.security.see.storage-service.trusty.xml
@@ -0,0 +1,10 @@
+<manifest version="1.0" type="device">
+    <hal format="aidl" exclusive-to="virtual-machine">
+        <name>android.hardware.security.see.storage</name>
+        <version>1</version>
+        <interface>
+            <name>ISecureStorage</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+</manifest>