Merge "VtsHalTargetTest: Improve error checks" into main
diff --git a/audio/aidl/default/include/core-impl/DriverStubImpl.h b/audio/aidl/default/include/core-impl/DriverStubImpl.h
index a1a6c82..84f869a 100644
--- a/audio/aidl/default/include/core-impl/DriverStubImpl.h
+++ b/audio/aidl/default/include/core-impl/DriverStubImpl.h
@@ -22,7 +22,9 @@
 
 class DriverStubImpl : virtual public DriverInterface {
   public:
-    explicit DriverStubImpl(const StreamContext& context);
+    explicit DriverStubImpl(const StreamContext& context)
+        : DriverStubImpl(context, 500 /*asyncSleepTimeUs*/) {}
+    DriverStubImpl(const StreamContext& context, int asyncSleepTimeUs);
 
     ::android::status_t init(DriverCallbackInterface* callback) override;
     ::android::status_t drain(StreamDescriptor::DrainMode) override;
@@ -40,6 +42,8 @@
     const int mSampleRate;
     const bool mIsAsynchronous;
     const bool mIsInput;
+    const int32_t mMixPortHandle;
+    const int mAsyncSleepTimeUs;
     bool mIsInitialized = false;  // Used for validating the state machine logic.
     bool mIsStandby = true;       // Used for validating the state machine logic.
     int64_t mStartTimeNs = 0;
diff --git a/audio/aidl/default/include/core-impl/StreamOffloadStub.h b/audio/aidl/default/include/core-impl/StreamOffloadStub.h
index 3b452f9..67abe95 100644
--- a/audio/aidl/default/include/core-impl/StreamOffloadStub.h
+++ b/audio/aidl/default/include/core-impl/StreamOffloadStub.h
@@ -60,11 +60,14 @@
     ::android::status_t drain(StreamDescriptor::DrainMode drainMode) override;
     ::android::status_t flush() override;
     ::android::status_t pause() override;
+    ::android::status_t start() override;
     ::android::status_t transfer(void* buffer, size_t frameCount, size_t* actualFrameCount,
                                  int32_t* latencyMs) override;
     void shutdown() override;
 
   private:
+    ::android::status_t startWorkerIfNeeded();
+
     DspSimulatorState mState;
     DspSimulatorWorker mDspWorker;
     bool mDspWorkerStarted = false;
diff --git a/audio/aidl/default/stub/DriverStubImpl.cpp b/audio/aidl/default/stub/DriverStubImpl.cpp
index 107affb..0d129e6 100644
--- a/audio/aidl/default/stub/DriverStubImpl.cpp
+++ b/audio/aidl/default/stub/DriverStubImpl.cpp
@@ -24,19 +24,27 @@
 
 namespace aidl::android::hardware::audio::core {
 
-DriverStubImpl::DriverStubImpl(const StreamContext& context)
+DriverStubImpl::DriverStubImpl(const StreamContext& context, int asyncSleepTimeUs)
     : mBufferSizeFrames(context.getBufferSizeInFrames()),
       mFrameSizeBytes(context.getFrameSize()),
       mSampleRate(context.getSampleRate()),
       mIsAsynchronous(!!context.getAsyncCallback()),
-      mIsInput(context.isInput()) {}
+      mIsInput(context.isInput()),
+      mMixPortHandle(context.getMixPortHandle()),
+      mAsyncSleepTimeUs(asyncSleepTimeUs) {}
+
+#define LOG_ENTRY()                                                                          \
+    LOG(DEBUG) << "[" << (mIsInput ? "in" : "out") << "|ioHandle:" << mMixPortHandle << "] " \
+               << __func__;
 
 ::android::status_t DriverStubImpl::init(DriverCallbackInterface* /*callback*/) {
+    LOG_ENTRY();
     mIsInitialized = true;
     return ::android::OK;
 }
 
 ::android::status_t DriverStubImpl::drain(StreamDescriptor::DrainMode) {
+    LOG_ENTRY();
     if (!mIsInitialized) {
         LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
     }
@@ -46,14 +54,15 @@
             const size_t delayUs = static_cast<size_t>(
                     std::roundf(mBufferSizeFrames * kMicrosPerSecond / mSampleRate));
             usleep(delayUs);
-        } else {
-            usleep(500);
+        } else if (mAsyncSleepTimeUs) {
+            usleep(mAsyncSleepTimeUs);
         }
     }
     return ::android::OK;
 }
 
 ::android::status_t DriverStubImpl::flush() {
+    LOG_ENTRY();
     if (!mIsInitialized) {
         LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
     }
@@ -61,6 +70,7 @@
 }
 
 ::android::status_t DriverStubImpl::pause() {
+    LOG_ENTRY();
     if (!mIsInitialized) {
         LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
     }
@@ -68,6 +78,7 @@
 }
 
 ::android::status_t DriverStubImpl::standby() {
+    LOG_ENTRY();
     if (!mIsInitialized) {
         LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
     }
@@ -76,6 +87,7 @@
 }
 
 ::android::status_t DriverStubImpl::start() {
+    LOG_ENTRY();
     if (!mIsInitialized) {
         LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
     }
@@ -87,6 +99,7 @@
 
 ::android::status_t DriverStubImpl::transfer(void* buffer, size_t frameCount,
                                              size_t* actualFrameCount, int32_t*) {
+    // No LOG_ENTRY as this is called very often.
     if (!mIsInitialized) {
         LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
     }
@@ -95,7 +108,7 @@
     }
     *actualFrameCount = frameCount;
     if (mIsAsynchronous) {
-        usleep(500);
+        if (mAsyncSleepTimeUs) usleep(mAsyncSleepTimeUs);
     } else {
         mFramesSinceStart += *actualFrameCount;
         const long bufferDurationUs = (*actualFrameCount) * MICROS_PER_SECOND / mSampleRate;
@@ -120,6 +133,7 @@
 }
 
 void DriverStubImpl::shutdown() {
+    LOG_ENTRY();
     mIsInitialized = false;
 }
 
diff --git a/audio/aidl/default/stub/StreamOffloadStub.cpp b/audio/aidl/default/stub/StreamOffloadStub.cpp
index fb12697..95cef35 100644
--- a/audio/aidl/default/stub/StreamOffloadStub.cpp
+++ b/audio/aidl/default/stub/StreamOffloadStub.cpp
@@ -81,11 +81,13 @@
 }
 
 DriverOffloadStubImpl::DriverOffloadStubImpl(const StreamContext& context)
-    : DriverStubImpl(context),
+    : DriverStubImpl(context, 0 /*asyncSleepTimeUs*/),
       mState{context.getFormat().encoding, context.getSampleRate(),
              250 /*earlyNotifyMs*/ * context.getSampleRate() / MILLIS_PER_SECOND,
              static_cast<int64_t>(context.getBufferSizeInFrames()) / 2},
-      mDspWorker(mState) {}
+      mDspWorker(mState) {
+    LOG_IF(FATAL, !mIsAsynchronous) << "The steam must be used in asynchronous mode";
+}
 
 ::android::status_t DriverOffloadStubImpl::init(DriverCallbackInterface* callback) {
     RETURN_STATUS_IF_ERROR(DriverStubImpl::init(callback));
@@ -99,10 +101,7 @@
 }
 
 ::android::status_t DriverOffloadStubImpl::drain(StreamDescriptor::DrainMode drainMode) {
-    // Does not call into the DriverStubImpl::drain.
-    if (!mIsInitialized) {
-        LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
-    }
+    RETURN_STATUS_IF_ERROR(DriverStubImpl::drain(drainMode));
     std::lock_guard l(mState.lock);
     if (!mState.clipFramesLeft.empty()) {
         // Cut playback of the current clip.
@@ -132,23 +131,27 @@
     return ::android::OK;
 }
 
+::android::status_t DriverOffloadStubImpl::start() {
+    RETURN_STATUS_IF_ERROR(DriverStubImpl::start());
+    RETURN_STATUS_IF_ERROR(startWorkerIfNeeded());
+    bool hasClips;  // Can be start after paused draining.
+    {
+        std::lock_guard l(mState.lock);
+        hasClips = !mState.clipFramesLeft.empty();
+        LOG(DEBUG) << __func__
+                   << ": clipFramesLeft: " << ::android::internal::ToString(mState.clipFramesLeft);
+    }
+    if (hasClips) {
+        mDspWorker.resume();
+    }
+    return ::android::OK;
+}
+
 ::android::status_t DriverOffloadStubImpl::transfer(void* buffer, size_t frameCount,
-                                                    size_t* actualFrameCount,
-                                                    int32_t* /*latencyMs*/) {
-    // Does not call into the DriverStubImpl::transfer.
-    if (!mIsInitialized) {
-        LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
-    }
-    if (mIsStandby) {
-        LOG(FATAL) << __func__ << ": must not happen while in standby";
-    }
-    if (!mDspWorkerStarted) {
-        // This is an "audio service thread," must have elevated priority.
-        if (!mDspWorker.start("dsp_sim", ANDROID_PRIORITY_URGENT_AUDIO)) {
-            return ::android::NO_INIT;
-        }
-        mDspWorkerStarted = true;
-    }
+                                                    size_t* actualFrameCount, int32_t* latencyMs) {
+    RETURN_STATUS_IF_ERROR(
+            DriverStubImpl::transfer(buffer, frameCount, actualFrameCount, latencyMs));
+    RETURN_STATUS_IF_ERROR(startWorkerIfNeeded());
     // Scan the buffer for clip headers.
     *actualFrameCount = frameCount;
     while (buffer != nullptr && frameCount > 0) {
@@ -189,6 +192,18 @@
 void DriverOffloadStubImpl::shutdown() {
     LOG(DEBUG) << __func__ << ": stopping the DSP simulator worker";
     mDspWorker.stop();
+    DriverStubImpl::shutdown();
+}
+
+::android::status_t DriverOffloadStubImpl::startWorkerIfNeeded() {
+    if (!mDspWorkerStarted) {
+        // This is an "audio service thread," must have elevated priority.
+        if (!mDspWorker.start("dsp_sim", ANDROID_PRIORITY_URGENT_AUDIO)) {
+            return ::android::NO_INIT;
+        }
+        mDspWorkerStarted = true;
+    }
+    return ::android::OK;
 }
 
 // static
diff --git a/audio/aidl/vts/VtsHalAudioCoreConfigTargetTest.cpp b/audio/aidl/vts/VtsHalAudioCoreConfigTargetTest.cpp
index 7ca60be..713af9a 100644
--- a/audio/aidl/vts/VtsHalAudioCoreConfigTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioCoreConfigTargetTest.cpp
@@ -367,8 +367,15 @@
             auto criterionValue = criterionRule.criterionAndValue;
             auto matchesWhen = criterionRule.matchingRule;
             auto criteriaIt = find_if(criteria.begin(), criteria.end(), [&](const auto& criterion) {
+                auto getForceConfigTag = [](const AudioHalCapCriterionV2& forceConfig) {
+                    return forceConfig.get<AudioHalCapCriterionV2::forceConfigForUse>()
+                            .values[0].getTag();
+                };
                 return criterion.has_value() &&
-                       criterion.value().getTag() == selectionCriterion.getTag();
+                       criterion.value().getTag() == selectionCriterion.getTag() &&
+                       (criterion.value().getTag() != AudioHalCapCriterionV2::forceConfigForUse ||
+                        getForceConfigTag(criterion.value()) ==
+                                getForceConfigTag(selectionCriterion));
             });
             EXPECT_NE(criteriaIt, criteria.end())
                     << " Invalid rule criterion " << toString(selectionCriterion.getTag());
diff --git a/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp b/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
index 8bbb60b..21b7aff 100644
--- a/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
@@ -5012,7 +5012,7 @@
         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"), kAidlVersion1, kStreamTransientStateTransitionDelayMs,
+        std::make_tuple(std::string("Pause"), kAidlVersion3, kStreamTransientStateTransitionDelayMs,
                         StreamTypeFilter::ASYNC, makePauseCommands(false, false),
                         false /*validatePositionIncrease*/);
 
@@ -5117,9 +5117,8 @@
                                          kDrainOutSyncSeq, kDrainOutAsyncSeq,
                                          kDrainEarlyOutAsyncSeq, kDrainPauseOutSyncSeq,
                                          kDrainPauseOutAsyncSeq, kDrainEarlyPauseOutAsyncSeq,
-                                         kStandbyOutSyncSeq, kStandbyOutAsyncSeq,
-                                         kPauseOutSyncSeq,  // kPauseOutAsyncSeq,
-                                         kFlushOutSyncSeq, kFlushOutAsyncSeq,
+                                         kStandbyOutSyncSeq, kStandbyOutAsyncSeq, kPauseOutSyncSeq,
+                                         kPauseOutAsyncSeq, kFlushOutSyncSeq, kFlushOutAsyncSeq,
                                          kDrainPauseFlushOutSyncSeq, kDrainPauseFlushOutAsyncSeq),
                          testing::Values(false, true)),
         GetStreamIoTestName);
diff --git a/audio/aidl/vts/VtsHalDynamicsProcessingTest.cpp b/audio/aidl/vts/VtsHalDynamicsProcessingTest.cpp
index 1dd9b0c..74f00c0 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) {
@@ -1547,6 +1558,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/bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.cpp b/bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.cpp
index a52d761..2fde910 100644
--- a/bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.cpp
+++ b/bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.cpp
@@ -2843,11 +2843,11 @@
 
     if (asymmetric) {
       source_ase_requriement.aseConfiguration.codecConfiguration = {
-          CodecSpecificConfigurationLtv::SamplingFrequency::HZ8000,
+          CodecSpecificConfigurationLtv::SamplingFrequency::HZ16000,
           CodecSpecificConfigurationLtv::FrameDuration::US10000, allocation};
     } else {
       source_ase_requriement.aseConfiguration.codecConfiguration = {
-          CodecSpecificConfigurationLtv::SamplingFrequency::HZ16000,
+          CodecSpecificConfigurationLtv::SamplingFrequency::HZ32000,
           CodecSpecificConfigurationLtv::FrameDuration::US10000, allocation};
     }
 
diff --git a/compatibility_matrices/Android.bp b/compatibility_matrices/Android.bp
index 63ef223..0d37060 100644
--- a/compatibility_matrices/Android.bp
+++ b/compatibility_matrices/Android.bp
@@ -88,8 +88,6 @@
         "compatibility_matrix.5.xml",
     ],
     kernel_configs: [
-        "kernel_config_r_4.14",
-        "kernel_config_r_4.19",
         "kernel_config_r_5.4",
     ],
 }
diff --git a/compatibility_matrices/compatibility_matrix.5.xml b/compatibility_matrices/compatibility_matrix.5.xml
index 1cf98b0..d01a6ea 100644
--- a/compatibility_matrices/compatibility_matrix.5.xml
+++ b/compatibility_matrices/compatibility_matrix.5.xml
@@ -1,578 +1,7 @@
 <compatibility-matrix version="1.0" type="framework" level="5">
-    <hal format="hidl">
-        <name>android.hardware.atrace</name>
-        <version>1.0</version>
-        <interface>
-            <name>IAtraceDevice</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.audio</name>
-        <version>6.0</version>
-        <interface>
-            <name>IDevicesFactory</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.audio.effect</name>
-        <version>6.0</version>
-        <interface>
-            <name>IEffectsFactory</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.authsecret</name>
-        <version>1.0</version>
-        <interface>
-            <name>IAuthSecret</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.automotive.audiocontrol</name>
-        <version>1.0</version>
-        <version>2.0</version>
-        <interface>
-            <name>IAudioControl</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.automotive.can</name>
-        <version>1.0</version>
-        <interface>
-            <name>ICanBus</name>
-            <regex-instance>.*</regex-instance>
-        </interface>
-        <interface>
-            <name>ICanController</name>
-            <regex-instance>.*</regex-instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.automotive.evs</name>
-        <version>1.0-1</version>
-        <interface>
-            <name>IEvsEnumerator</name>
-            <instance>default</instance>
-            <regex-instance>[a-z]+/[0-9]+</regex-instance>
-        </interface>
-    </hal>
-    <hal format="aidl">
-        <name>android.hardware.automotive.occupant_awareness</name>
-        <interface>
-            <name>IOccupantAwareness</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.automotive.sv</name>
-        <version>1.0</version>
-        <interface>
-            <name>ISurroundViewService</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.automotive.vehicle</name>
-        <version>2.0</version>
-        <interface>
-            <name>IVehicle</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.biometrics.face</name>
-        <version>1.0</version>
-        <interface>
-            <name>IBiometricsFace</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.biometrics.fingerprint</name>
-        <version>2.1-2</version>
-        <interface>
-            <name>IBiometricsFingerprint</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.bluetooth</name>
-        <version>1.0-1</version>
-        <interface>
-            <name>IBluetoothHci</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.bluetooth.audio</name>
-        <version>2.0</version>
-        <interface>
-            <name>IBluetoothAudioProvidersFactory</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.boot</name>
-        <version>1.1</version>
-        <interface>
-            <name>IBootControl</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.broadcastradio</name>
-        <version>1.0-1</version>
-        <interface>
-            <name>IBroadcastRadioFactory</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.broadcastradio</name>
-        <version>2.0</version>
-        <interface>
-            <name>IBroadcastRadio</name>
-            <regex-instance>.*</regex-instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.camera.provider</name>
-        <version>2.4-6</version>
-        <interface>
-            <name>ICameraProvider</name>
-            <regex-instance>[^/]+/[0-9]+</regex-instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.cas</name>
-        <version>1.1-2</version>
-        <interface>
-            <name>IMediaCasService</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.confirmationui</name>
-        <version>1.0</version>
-        <interface>
-            <name>IConfirmationUI</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.contexthub</name>
-        <version>1.0-1</version>
-        <interface>
-            <name>IContexthub</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.drm</name>
-        <version>1.3</version>
-        <interface>
-            <name>ICryptoFactory</name>
-            <regex-instance>.*</regex-instance>
-        </interface>
-        <interface>
-            <name>IDrmFactory</name>
-            <regex-instance>.*</regex-instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.dumpstate</name>
-        <version>1.1</version>
-        <interface>
-            <name>IDumpstateDevice</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.gatekeeper</name>
-        <version>1.0</version>
-        <interface>
-            <name>IGatekeeper</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.gnss</name>
-        <version>2.0-1</version>
-        <interface>
-            <name>IGnss</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <!-- Either the AIDL or the HIDL allocator HAL must exist on the device.
-         If the HIDL composer HAL exists, it must be at least version 2.0.
-         See DeviceManifestTest.GrallocHal -->
-    <hal format="hidl">
-        <name>android.hardware.graphics.allocator</name>
-        <!-- New, non-Go devices should use 4.0, tested in vts_treble_vintf_vendor_test -->
-        <version>2.0</version>
-        <version>3.0</version>
-        <version>4.0</version>
-        <interface>
-            <name>IAllocator</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.graphics.composer</name>
-        <version>2.1-4</version>
-        <interface>
-            <name>IComposer</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.graphics.mapper</name>
-        <!-- New, non-Go devices should use 4.0, tested in vts_treble_vintf_vendor_test -->
-        <version>2.1</version>
-        <version>3.0</version>
-        <version>4.0</version>
-        <interface>
-            <name>IMapper</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <!-- Either the AIDL or the HIDL health HAL must exist on the device.
-         If the HIDL health HAL exists, it must be at least version 2.1.
-         See DeviceManifestTest.HealthHal -->
-    <hal format="hidl">
-        <name>android.hardware.health</name>
-        <version>2.1</version>
-        <interface>
-            <name>IHealth</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.health.storage</name>
-        <version>1.0</version>
-        <interface>
-            <name>IStorage</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="aidl">
-        <name>android.hardware.identity</name>
-        <!--
-          b/178458001: identity V2 is introduced in R, but Android R VINTF does not support AIDL
-          versions. Hence, we only specify identity V2 in compatibility_matrix.5.xml in Android S+
-          branches. In Android R branches, the matrix implicitly specifies V1.
-          SingleManifestTest.ManifestAidlHalsServed has an exemption for this.
-        -->
-        <version>1-2</version>
-        <interface>
-            <name>IIdentityCredentialStore</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.ir</name>
-        <version>1.0</version>
-        <interface>
-            <name>IConsumerIr</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.input.classifier</name>
-        <version>1.0</version>
-        <interface>
-            <name>IInputClassifier</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.keymaster</name>
-        <version>3.0</version>
-        <version>4.0-1</version>
-        <interface>
-            <name>IKeymasterDevice</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.keymaster</name>
-        <version>4.0-1</version>
-        <interface>
-            <name>IKeymasterDevice</name>
-            <instance>strongbox</instance>
-        </interface>
-    </hal>
-    <hal format="aidl">
-        <name>android.hardware.light</name>
-        <interface>
-            <name>ILights</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.media.c2</name>
-        <version>1.0-1</version>
-        <interface>
-            <name>IComponentStore</name>
-            <instance>software</instance>
-            <regex-instance>default[0-9]*</regex-instance>
-            <regex-instance>vendor[0-9]*_software</regex-instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.media.c2</name>
-        <version>1.0</version>
-        <interface>
-            <name>IConfigurable</name>
-            <instance>default</instance>
-            <instance>software</instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.media.omx</name>
-        <version>1.0</version>
-        <interface>
-            <name>IOmx</name>
-            <instance>default</instance>
-        </interface>
-        <interface>
-            <name>IOmxStore</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.memtrack</name>
-        <version>1.0</version>
-        <interface>
-            <name>IMemtrack</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.neuralnetworks</name>
-        <version>1.0-3</version>
-        <interface>
-            <name>IDevice</name>
-            <regex-instance>.*</regex-instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.nfc</name>
-        <version>1.2</version>
-        <interface>
-            <name>INfc</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.oemlock</name>
-        <version>1.0</version>
-        <interface>
-            <name>IOemLock</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="aidl">
-        <name>android.hardware.power</name>
-        <interface>
-            <name>IPower</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.power.stats</name>
-        <version>1.0</version>
-        <interface>
-            <name>IPowerStats</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.radio</name>
-        <version>1.4</version>
-        <version>1.5</version>
-        <interface>
-            <name>IRadio</name>
-            <instance>slot1</instance>
-            <instance>slot2</instance>
-            <instance>slot3</instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.radio</name>
-        <version>1.2</version>
-        <interface>
-            <name>ISap</name>
-            <instance>slot1</instance>
-            <instance>slot2</instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.radio.config</name>
-        <!--
-        See compatibility_matrix.4.xml on versioning of radio config HAL.
-        -->
-        <version>1.1</version>
-        <interface>
-            <name>IRadioConfig</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.renderscript</name>
-        <version>1.0</version>
-        <interface>
-            <name>IDevice</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="aidl">
-        <name>android.hardware.rebootescrow</name>
-        <interface>
-            <name>IRebootEscrow</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.secure_element</name>
-        <version>1.0-2</version>
-        <interface>
-            <name>ISecureElement</name>
-            <regex-instance>eSE[1-9][0-9]*</regex-instance>
-            <regex-instance>SIM[1-9][0-9]*</regex-instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.sensors</name>
-        <version>1.0</version>
-        <version>2.0-1</version>
-        <interface>
-            <name>ISensors</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.soundtrigger</name>
-        <version>2.0-3</version>
-        <interface>
-            <name>ISoundTriggerHw</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.tetheroffload.config</name>
-        <version>1.0</version>
-        <interface>
-            <name>IOffloadConfig</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.tetheroffload.control</name>
-        <version>1.0</version>
-        <interface>
-            <name>IOffloadControl</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.thermal</name>
-        <version>2.0</version>
-        <interface>
-            <name>IThermal</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.tv.cec</name>
-        <version>1.0</version>
-        <interface>
-            <name>IHdmiCec</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.tv.input</name>
-        <version>1.0</version>
-        <interface>
-            <name>ITvInput</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.tv.tuner</name>
-        <version>1.0</version>
-        <interface>
-            <name>ITuner</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.usb</name>
-        <version>1.0-2</version>
-        <interface>
-            <name>IUsb</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.usb.gadget</name>
-        <version>1.0-1</version>
-        <interface>
-            <name>IUsbGadget</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="aidl">
-        <name>android.hardware.vibrator</name>
-        <interface>
-            <name>IVibrator</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.vr</name>
-        <version>1.0</version>
-        <interface>
-            <name>IVr</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.weaver</name>
-        <version>1.0</version>
-        <interface>
-            <name>IWeaver</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.wifi</name>
-        <version>1.0-4</version>
-        <interface>
-            <name>IWifi</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.wifi.hostapd</name>
-        <version>1.0-2</version>
-        <interface>
-            <name>IHostapd</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.wifi.supplicant</name>
-        <version>1.0-3</version>
-        <interface>
-            <name>ISupplicant</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
+  <!--
+    Android R FCM has been deprecated, but this file is kept
+    to help manage the android11-5.4 kernel config requirements as that
+    kernel version is not being deprecated with the R FCM.
+    -->
 </compatibility-matrix>
diff --git a/compatibility_matrices/exclude/fcm_exclude.cpp b/compatibility_matrices/exclude/fcm_exclude.cpp
index 1d5b2bd..fdbeab0 100644
--- a/compatibility_matrices/exclude/fcm_exclude.cpp
+++ b/compatibility_matrices/exclude/fcm_exclude.cpp
@@ -104,6 +104,28 @@
             "android.hardware.vibrator@1.1",
             "android.hardware.vibrator@1.2",
             "android.hardware.vibrator@1.3",
+
+            // b/392700935 for HALs deprecated in R
+            "android.hardware.automotive.audiocontrol@1.0",
+            "android.hardware.automotive.audiocontrol@2.0",
+            "android.hardware.boot@1.1",
+            "android.hardware.contexthub@1.0",
+            "android.hardware.contexthub@1.1",
+            "android.hardware.health.storage@1.0",
+            "android.hardware.memtrack@1.0",
+            "android.hardware.power.stats@1.0",
+            "android.hardware.radio@1.4",
+            "android.hardware.radio@1.5",
+            "android.hardware.soundtrigger@2.0",
+            "android.hardware.soundtrigger@2.1",
+            "android.hardware.soundtrigger@2.2",
+            "android.hardware.tetheroffload.control@1.0",
+            "android.hardware.vr@1.0",
+            "android.hardware.wifi.supplicant@1.0",
+            "android.hardware.wifi.supplicant@1.1",
+            "android.hardware.wifi@1.0",
+            "android.hardware.wifi@1.1",
+            "android.hardware.wifi@1.2",
     };
 
     auto package_has_prefix = [&](const std::string& prefix) {
diff --git a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
index 1908d05..0ae4b96 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
@@ -550,8 +550,14 @@
     void deleteKey(in byte[] keyBlob);
 
     /**
-     * Deletes all keys in the hardware keystore. Used when keystore is reset completely. After
-     * this function is called all keys created previously must be rendered permanently unusable.
+     * Deletes all keys in the hardware keystore. Used when keystore is reset completely.
+     *
+     * For StrongBox KeyMint: After this function is called all keys created previously must be
+     * rendered permanently unusable.
+     *
+     * For TEE KeyMint: After this function is called all keys with Tag::ROLLBACK_RESISTANCE in
+     * their hardware-enforced authorization lists must be rendered permanently unusable.  Keys
+     * without Tag::ROLLBACK_RESISTANCE may or may not be rendered unusable.
      */
     void deleteAllKeys();
 
diff --git a/security/keymint/aidl/vts/functional/Android.bp b/security/keymint/aidl/vts/functional/Android.bp
index da3427a..a8ccabf 100644
--- a/security/keymint/aidl/vts/functional/Android.bp
+++ b/security/keymint/aidl/vts/functional/Android.bp
@@ -100,6 +100,9 @@
     export_static_lib_headers: [
         "libkeymint_support",
     ],
+    shared_libs: [
+        "libkeystore2_flags_cc",
+    ],
     static_libs: [
         "libgmock_ndk",
     ],
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
index 0c86a27..0ec76a5 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
@@ -29,6 +29,7 @@
 #include <android-base/strings.h>
 #include <android/binder_manager.h>
 #include <android/content/pm/IPackageManagerNative.h>
+#include <android_security_keystore2.h>
 #include <cppbor_parse.h>
 #include <cutils/properties.h>
 #include <gmock/gmock.h>
@@ -387,11 +388,11 @@
     os_patch_level_ = getOsPatchlevel();
     vendor_patch_level_ = getVendorPatchlevel();
 
-    // TODO(b/369375199): temporary code, remove when apexd -> keystore2 -> KeyMint transmission
-    // of module info happens.
-    {
-        GTEST_LOG_(INFO) << "Setting MODULE_HASH to fake value as fallback";
-        // Ensure that a MODULE_HASH value is definitely present in KeyMint (if it's >= v4).
+    if (!::android::security::keystore2::attest_modules()) {
+        // Some tests (for v4+) require that the KeyMint instance has been
+        // provided with a module hash value.  If the keystore2 flag is off,
+        // this will not happen, so set a fake value here instead.
+        GTEST_LOG_(INFO) << "Setting MODULE_HASH to fake value as fallback when flag off";
         vector<uint8_t> fakeModuleHash = {
                 0xf3, 0xf1, 0x1f, 0xe5, 0x13, 0x05, 0xfe, 0xfa, 0xe9, 0xc3, 0x53,
                 0xef, 0x69, 0xdf, 0x9f, 0xd7, 0x0c, 0x1e, 0xcc, 0x2c, 0x2c, 0x62,
diff --git a/security/keymint/aidl/vts/functional/KeyMintTest.cpp b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
index 2f34b9d..5a6eea1 100644
--- a/security/keymint/aidl/vts/functional/KeyMintTest.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
@@ -9134,5 +9134,12 @@
             }
         }
     }
+    // Some tests rely on information about the state of the system having been received by KeyMint,
+    // so ensure that has happened before running tests.
+    using namespace std::chrono_literals;
+    if (!android::base::WaitForProperty("keystore.module_hash.sent", "true", 30s)) {
+        std::cerr << "Warning: running test before keystore.module_hash.sent is true\n";
+    }
+
     return RUN_ALL_TESTS();
 }
diff --git a/security/rkp/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl b/security/rkp/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
index 21c5315..00112b1 100644
--- a/security/rkp/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
+++ b/security/rkp/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
@@ -54,8 +54,12 @@
  * use by the IRemotelyProvisionedComponent.
  *
  * The root keypair is generated by immutable code (e.g. ROM), from a Unique Device Secret (UDS).
- * The keypair that is generated from it can be referred to as the UDS_Pub/UDS_Priv keys. After the
- * device-unique secret is used, it must be made unavailable to any later boot stage.
+ * The UDS is a hardware-bound secret that forms the root of identify for the device and code
+ * running on the device. The keypair generated from the UDS is referred to as the UDS_Pub/UDS_Priv
+ * keypair. After the device-unique secret is used, it must be made unavailable to any later boot
+ * stage. Refer to the
+ * [Open Profile for DICE ](https://pigweed.googlesource.com/open-dice/+/HEAD/docs/specification.md#uds-details)
+ * specification for more details on the UDS.
  *
  * In this way, booting the device incrementally builds a certificate chain that (a) identifies and
  * validates the integrity of every stage and (b) contains a set of public keys that correspond to
@@ -95,8 +99,8 @@
  *
  * 2) The CDI_Leaf_Priv key cannot be used to sign arbitrary data.
  *
- * 3) Backend infrastructure does not correlate UDS_Pub with the certificates signed and sent back
- *    to the device.
+ * 3) Backend infrastructure very closely guards access to UDS_Pub, limiting it to the minimum
+ *    set of services that need to know it for security, privacy, and counter-abuse purposes.
  *
  * Versioning
  * ==========
diff --git a/security/see/hwcrypto/aidl/Android.bp b/security/see/hwcrypto/aidl/Android.bp
index c64b827..2115f19 100644
--- a/security/see/hwcrypto/aidl/Android.bp
+++ b/security/see/hwcrypto/aidl/Android.bp
@@ -31,6 +31,7 @@
     },
     frozen: true,
     system_ext_specific: true,
+    vendor_available: true,
     versions_with_info: [
         {
             version: "1",
diff --git a/security/see/hwcrypto/aidl/vts/functional/Android.bp b/security/see/hwcrypto/aidl/vts/functional/Android.bp
index beb8976..c2514d1 100644
--- a/security/see/hwcrypto/aidl/vts/functional/Android.bp
+++ b/security/see/hwcrypto/aidl/vts/functional/Android.bp
@@ -19,6 +19,8 @@
 rust_defaults {
     name: "hw_crypto_hal_aidl_rust_defaults",
     enabled: false,
+    prefer_rlib: true,
+    vendor_available: true,
     rustlibs: [
         "libbinder_rs",
         "android.hardware.security.see.hwcrypto-V1-rust",
@@ -30,7 +32,7 @@
         "librustutils",
     ],
     arch: {
-        x86_64: {
+        arm64: {
             enabled: true,
         },
     },
@@ -47,22 +49,6 @@
     ],
 }
 
-rust_binary {
-    name: "wait_hw_crypto",
-    prefer_rlib: true,
-    defaults: [
-        "hw_crypto_hal_aidl_rust_defaults",
-    ],
-    srcs: ["wait_service.rs"],
-    rustlibs: [
-        "libhwcryptohal_vts_test",
-        "liblogger",
-        "liblog_rust",
-        "libanyhow",
-        "libclap",
-    ],
-}
-
 rust_test {
     name: "VtsAidlHwCryptoConnTest",
     srcs: ["connection_test.rs"],
@@ -73,11 +59,4 @@
     rustlibs: [
         "libhwcryptohal_vts_test",
     ],
-    data: [
-        ":trusty_test_vm_elf",
-        ":trusty_test_vm_config",
-        ":trusty_vm_launcher_sh",
-        ":trusty_wait_ready_sh",
-        ":wait_hw_crypto",
-    ],
 }
diff --git a/security/see/hwcrypto/aidl/vts/functional/AndroidTest.xml b/security/see/hwcrypto/aidl/vts/functional/AndroidTestSystem.xml
similarity index 92%
rename from security/see/hwcrypto/aidl/vts/functional/AndroidTest.xml
rename to security/see/hwcrypto/aidl/vts/functional/AndroidTestSystem.xml
index 73290cf..649be23 100644
--- a/security/see/hwcrypto/aidl/vts/functional/AndroidTest.xml
+++ b/security/see/hwcrypto/aidl/vts/functional/AndroidTestSystem.xml
@@ -27,8 +27,8 @@
         <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="VtsAidlHwCryptoConnTest" value="/data/local/tmp/VtsAidlHwCryptoConnTest" />
+        <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" />
@@ -47,7 +47,7 @@
 
     <test class="com.android.tradefed.testtype.rust.RustBinaryTest" >
         <option name="test-device-path" value="/data/local/tmp" />
-        <option name="module-name" value="VtsAidlHwCryptoConnTest" />
+        <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. -->
diff --git a/security/see/hwcrypto/aidl/vts/functional/lib.rs b/security/see/hwcrypto/aidl/vts/functional/lib.rs
index e14ac83..81ae3fa 100644
--- a/security/see/hwcrypto/aidl/vts/functional/lib.rs
+++ b/security/see/hwcrypto/aidl/vts/functional/lib.rs
@@ -17,19 +17,32 @@
 //! VTS test library for HwCrypto functionality.
 //! It provides the base clases necessaries to write HwCrypto VTS tests
 
-use anyhow::{Context, Result};
+#[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,
@@ -44,7 +57,8 @@
     })
 }
 
-/// Get a HwCryptoKey binder service object
+/// 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")
@@ -55,3 +69,10 @@
         .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/aidl/vts/functional/wait_service.rs b/security/see/hwcrypto/aidl/vts/functional/wait_service.rs
deleted file mode 100644
index 13cbcb1..0000000
--- a/security/see/hwcrypto/aidl/vts/functional/wait_service.rs
+++ /dev/null
@@ -1,47 +0,0 @@
-// 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.
-
-//! Small utility to wait for hwcrypto service to be up
-
-use anyhow::{/*Context,*/ Result};
-use clap::Parser;
-use log::info;
-use std::{thread, time};
-
-#[derive(Parser)]
-/// Collection of CLI for trusty_security_vm_launcher
-pub struct Args {
-    /// Number of repetitions for the wait
-    #[arg(long, default_value_t = 20)]
-    number_repetitions: u32,
-
-    /// Delay between repetitiond
-    #[arg(long, default_value_t = 2)]
-    delay_between_repetitions: u32,
-}
-
-fn main() -> Result<()> {
-    let args = Args::parse();
-
-    info!("Waiting for hwcrypto service");
-    let delay = time::Duration::new(args.delay_between_repetitions.into(), 0);
-    for _ in 0..args.number_repetitions {
-        let hw_crypto_key = hwcryptohal_vts_test::get_hwcryptokey();
-        if hw_crypto_key.is_ok() {
-            break;
-        }
-        thread::sleep(delay);
-    }
-    Ok(())
-}
diff --git a/security/see/hwcrypto/default/Android.bp b/security/see/hwcrypto/default/Android.bp
new file mode 100644
index 0000000..ab23cfd
--- /dev/null
+++ b/security/see/hwcrypto/default/Android.bp
@@ -0,0 +1,140 @@
+// 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.
+
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_library {
+    name: "hwcryptohallib",
+    enabled: false,
+    shared_libs: [
+        "libbase",
+        "liblog",
+        "libbinder",
+        "libbinder_ndk",
+        "libbinder_trusty",
+        "libtrusty",
+        "libutils",
+
+        // AIDL interface deps versions, please refer to below link
+        // https://source.android.com/docs/core/architecture/aidl/stable-aidl#module-naming-rules
+        "android.hardware.security.see.hwcrypto-V1-ndk",
+        "android.hardware.security.see.hwcrypto-V1-cpp",
+    ],
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+    srcs: ["hwcryptolib.cpp"],
+    proprietary: true,
+    arch: {
+        arm64: {
+            enabled: true,
+        },
+    },
+}
+
+cc_binary {
+    name: "android.hardware.trusty.hwcryptohal-service",
+    enabled: false,
+    relative_install_path: "hw",
+    srcs: [
+        "hwcrypto_delegator.cpp",
+    ],
+    shared_libs: [
+        "libbase",
+        "liblog",
+        "libbinder",
+        "libbinder_ndk",
+        "libbinder_trusty",
+        "libtrusty",
+        "libutils",
+        "hwcryptohallib",
+
+        // AIDL interface deps versions, please refer to below link
+        // https://source.android.com/docs/core/architecture/aidl/stable-aidl#module-naming-rules
+        "android.hardware.security.see.hwcrypto-V1-ndk",
+        "android.hardware.security.see.hwcrypto-V1-cpp",
+    ],
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+    proprietary: true,
+    vintf_fragments: ["android.hardware.security.see.hwcrypto-service.trusty.xml"],
+    init_rc: ["android.hardware.security.see.hwcrypto-service.trusty.rc"],
+    arch: {
+        arm64: {
+            enabled: true,
+        },
+    },
+}
+
+cc_fuzz {
+    name: "android.hardware.trusty.hwcryptohal-service_fuzzer",
+    enabled: false,
+    defaults: ["service_fuzzer_defaults"],
+    static_libs: [
+        "android.hardware.security.see.hwcrypto-V1-ndk",
+        "android.hardware.security.see.hwcrypto-V1-cpp",
+        "liblog",
+        "hwcryptohallib",
+    ],
+    shared_libs: [
+        "libbinder_trusty",
+        "libtrusty",
+    ],
+    srcs: ["fuzzer.cpp"],
+    fuzz_config: {
+        cc: [
+            "oarbildo@google.com",
+        ],
+    },
+    arch: {
+        arm64: {
+            enabled: true,
+        },
+    },
+}
+
+cc_test {
+    name: "HwCryptoHalDelegatorTests",
+    enabled: false,
+    srcs: [
+        "delegatorTest.cpp",
+    ],
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wextra",
+    ],
+
+    shared_libs: [
+        "libbase",
+        "liblog",
+        "libbinder",
+        "libbinder_ndk",
+    ],
+    static_libs: [
+        "android.hardware.security.see.hwcrypto-V1-ndk",
+        "android.hardware.security.see.hwcrypto-V1-cpp",
+    ],
+
+    arch: {
+        arm64: {
+            enabled: true,
+        },
+    },
+}
diff --git a/security/see/hwcrypto/default/android.hardware.security.see.hwcrypto-service.trusty.rc b/security/see/hwcrypto/default/android.hardware.security.see.hwcrypto-service.trusty.rc
new file mode 100644
index 0000000..8665755
--- /dev/null
+++ b/security/see/hwcrypto/default/android.hardware.security.see.hwcrypto-service.trusty.rc
@@ -0,0 +1,5 @@
+service trusty-hwcryptohal /vendor/bin/hw/android.hardware.trusty.hwcryptohal-service \
+-d ${ro.hardware.trusty_ipc_dev:-/dev/trusty-ipc-dev0}
+    class hal
+    user system
+    group system
diff --git a/security/see/hwcrypto/default/android.hardware.security.see.hwcrypto-service.trusty.xml b/security/see/hwcrypto/default/android.hardware.security.see.hwcrypto-service.trusty.xml
new file mode 100644
index 0000000..8ac0942
--- /dev/null
+++ b/security/see/hwcrypto/default/android.hardware.security.see.hwcrypto-service.trusty.xml
@@ -0,0 +1,10 @@
+<manifest version="1.0" type="device">
+    <hal format="aidl">
+        <name>android.hardware.security.see.hwcrypto</name>
+        <version>1</version>
+        <interface>
+            <name>IHwCryptoKey</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+</manifest>
\ No newline at end of file
diff --git a/security/see/hwcrypto/default/delegatorTest.cpp b/security/see/hwcrypto/default/delegatorTest.cpp
new file mode 100644
index 0000000..a80d6fd
--- /dev/null
+++ b/security/see/hwcrypto/default/delegatorTest.cpp
@@ -0,0 +1,49 @@
+#include <gtest/gtest.h>
+#include "hwcryptokeyimpl.h"
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    return RUN_ALL_TESTS();
+}
+
+TEST(HwCryptoHalDelegator, keyPolicyCppToNdk) {
+    cpp_hwcrypto::KeyPolicy cppPolicy = cpp_hwcrypto::KeyPolicy();
+    cppPolicy.keyType = cpp_hwcrypto::types::KeyType::AES_128_CBC_PKCS7_PADDING;
+    cppPolicy.usage = cpp_hwcrypto::types::KeyUse::DECRYPT;
+    cppPolicy.keyLifetime = cpp_hwcrypto::types::KeyLifetime::PORTABLE;
+    cppPolicy.keyManagementKey = false;
+    cppPolicy.keyPermissions.push_back(
+            cpp_hwcrypto::types::KeyPermissions::ALLOW_PORTABLE_KEY_WRAPPING);
+    ndk_hwcrypto::KeyPolicy ndkPolicy = android::trusty::hwcryptohalservice::convertKeyPolicy<
+            ndk_hwcrypto::KeyPolicy, cpp_hwcrypto::KeyPolicy>(cppPolicy);
+    EXPECT_EQ(ndkPolicy.keyType, ndk_hwcrypto::types::KeyType::AES_128_CBC_PKCS7_PADDING);
+    EXPECT_EQ(ndkPolicy.usage, ndk_hwcrypto::types::KeyUse::DECRYPT);
+    EXPECT_EQ(ndkPolicy.keyLifetime, ndk_hwcrypto::types::KeyLifetime::PORTABLE);
+    EXPECT_EQ(ndkPolicy.keyManagementKey, false);
+    EXPECT_EQ(ndkPolicy.keyPermissions.size(), 1ul);
+    EXPECT_EQ(ndkPolicy.keyPermissions[0],
+              ndk_hwcrypto::types::KeyPermissions::ALLOW_PORTABLE_KEY_WRAPPING);
+}
+
+TEST(HwCryptoHalDelegator, keyPolicyNdkToCpp) {
+    ndk_hwcrypto::KeyPolicy ndkPolicy = ndk_hwcrypto::KeyPolicy();
+    ndkPolicy.keyType = ndk_hwcrypto::types::KeyType::AES_128_CTR;
+    ndkPolicy.usage = ndk_hwcrypto::types::KeyUse::ENCRYPT_DECRYPT;
+    ndkPolicy.keyLifetime = ndk_hwcrypto::types::KeyLifetime::HARDWARE;
+    ndkPolicy.keyManagementKey = true;
+    ndkPolicy.keyPermissions.push_back(
+            ndk_hwcrypto::types::KeyPermissions::ALLOW_EPHEMERAL_KEY_WRAPPING);
+    ndkPolicy.keyPermissions.push_back(
+            ndk_hwcrypto::types::KeyPermissions::ALLOW_HARDWARE_KEY_WRAPPING);
+    cpp_hwcrypto::KeyPolicy cppPolicy = android::trusty::hwcryptohalservice::convertKeyPolicy<
+            cpp_hwcrypto::KeyPolicy, ndk_hwcrypto::KeyPolicy>(ndkPolicy);
+    EXPECT_EQ(cppPolicy.keyType, cpp_hwcrypto::types::KeyType::AES_128_CTR);
+    EXPECT_EQ(cppPolicy.usage, cpp_hwcrypto::types::KeyUse::ENCRYPT_DECRYPT);
+    EXPECT_EQ(cppPolicy.keyLifetime, cpp_hwcrypto::types::KeyLifetime::HARDWARE);
+    EXPECT_EQ(cppPolicy.keyManagementKey, true);
+    EXPECT_EQ(cppPolicy.keyPermissions.size(), 2ul);
+    EXPECT_EQ(cppPolicy.keyPermissions[0],
+              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/fuzzer.cpp b/security/see/hwcrypto/default/fuzzer.cpp
new file mode 100644
index 0000000..4673066
--- /dev/null
+++ b/security/see/hwcrypto/default/fuzzer.cpp
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <fuzzbinder/libbinder_ndk_driver.h>
+#include <fuzzer/FuzzedDataProvider.h>
+#include "hwcryptokeyimpl.h"
+
+using android::fuzzService;
+using ndk::SharedRefBase;
+
+static const char* TIPC_DEFAULT_DEVNAME = "/dev/trusty-ipc-dev0";
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    auto hwCryptoServer =
+            android::trusty::hwcryptohalservice::HwCryptoKey::Create(TIPC_DEFAULT_DEVNAME);
+
+    fuzzService(hwCryptoServer->asBinder().get(), FuzzedDataProvider(data, size));
+
+    return 0;
+}
diff --git a/security/see/hwcrypto/default/hwcrypto_delegator.cpp b/security/see/hwcrypto/default/hwcrypto_delegator.cpp
new file mode 100644
index 0000000..1c3528c
--- /dev/null
+++ b/security/see/hwcrypto/default/hwcrypto_delegator.cpp
@@ -0,0 +1,81 @@
+/*
+ * 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.
+ */
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <getopt.h>
+#include <string>
+#include "hwcryptokeyimpl.h"
+
+static void showUsageAndExit(int code) {
+    LOG(ERROR) << "usage: android.hardware.trusty.hwcryptohal-service -d <trusty_dev>";
+    exit(code);
+}
+
+static void parseDeviceName(int argc, char* argv[], char*& device_name) {
+    static const char* _sopts = "h:d:";
+    static const struct option _lopts[] = {{"help", no_argument, nullptr, 'h'},
+                                           {"trusty_dev", required_argument, nullptr, 'd'},
+                                           {0, 0, 0, 0}};
+    int opt;
+    int oidx = 0;
+
+    while ((opt = getopt_long(argc, argv, _sopts, _lopts, &oidx)) != -1) {
+        switch (opt) {
+            case 'd':
+                device_name = strdup(optarg);
+                break;
+            case 'h':
+                showUsageAndExit(EXIT_SUCCESS);
+                break;
+            default:
+                LOG(ERROR) << "unrecognized option: " << opt;
+                showUsageAndExit(EXIT_FAILURE);
+        }
+    }
+
+    if (device_name == nullptr) {
+        LOG(ERROR) << "missing required argument(s)";
+        showUsageAndExit(EXIT_FAILURE);
+    }
+
+    LOG(INFO) << "starting android.hardware.trusty.hwcryptohal-service";
+    LOG(INFO) << "trusty dev: " << device_name;
+}
+
+int main(int argc, char* argv[]) {
+    char* device_name;
+    parseDeviceName(argc, argv, device_name);
+
+    auto hwCryptoServer = android::trusty::hwcryptohalservice::HwCryptoKey::Create(device_name);
+    if (hwCryptoServer == nullptr) {
+        LOG(ERROR) << "couldn't create hwcrypto service";
+        exit(EXIT_FAILURE);
+    }
+    ABinderProcess_setThreadPoolMaxThreadCount(0);
+    const std::string instance =
+            std::string() + ndk_hwcrypto::IHwCryptoKey::descriptor + "/default";
+    binder_status_t status =
+            AServiceManager_addService(hwCryptoServer->asBinder().get(), instance.c_str());
+    if (status != STATUS_OK) {
+        LOG(ERROR) << "couldn't register hwcrypto service";
+    }
+    CHECK_EQ(status, STATUS_OK);
+    ABinderProcess_joinThreadPool();
+
+    return 0;
+}
diff --git a/security/see/hwcrypto/default/hwcryptokeyimpl.h b/security/see/hwcrypto/default/hwcryptokeyimpl.h
new file mode 100644
index 0000000..19be8b4
--- /dev/null
+++ b/security/see/hwcrypto/default/hwcryptokeyimpl.h
@@ -0,0 +1,115 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/security/see/hwcrypto/BnHwCryptoKey.h>
+#include <aidl/android/hardware/security/see/hwcrypto/IHwCryptoKey.h>
+#include <aidl/android/hardware/security/see/hwcrypto/types/HalErrorCode.h>
+#include <android-base/logging.h>
+#include <android-base/result.h>
+#include <android/hardware/security/see/hwcrypto/IHwCryptoKey.h>
+#include <binder/RpcSession.h>
+
+// We use cpp interfaces to talk to Trusty, and ndk interfaces for the platform
+namespace cpp_hwcrypto = android::hardware::security::see::hwcrypto;
+namespace ndk_hwcrypto = aidl::android::hardware::security::see::hwcrypto;
+
+namespace android {
+namespace trusty {
+namespace hwcryptohalservice {
+
+class HwCryptoKey : public ndk_hwcrypto::BnHwCryptoKey {
+  private:
+    sp<cpp_hwcrypto::IHwCryptoKey> mHwCryptoServer;
+    sp<IBinder> mRoot;
+    sp<RpcSession> mSession;
+    android::base::Result<void> connectToTrusty(const char* tipcDev);
+
+  public:
+    HwCryptoKey();
+
+    static std::shared_ptr<HwCryptoKey> Create(const char* tipcDev);
+
+    ndk::ScopedAStatus deriveCurrentDicePolicyBoundKey(
+            const ndk_hwcrypto::IHwCryptoKey::DiceBoundDerivationKey& derivationKey,
+            ndk_hwcrypto::IHwCryptoKey::DiceCurrentBoundKeyResult* aidl_return);
+
+    ndk::ScopedAStatus deriveDicePolicyBoundKey(
+            const ndk_hwcrypto::IHwCryptoKey::DiceBoundDerivationKey& derivationKey,
+            const ::std::vector<uint8_t>& dicePolicyForKeyVersion,
+            ndk_hwcrypto::IHwCryptoKey::DiceBoundKeyResult* aidl_return);
+    ndk::ScopedAStatus deriveKey(const ndk_hwcrypto::IHwCryptoKey::DerivedKeyParameters& parameters,
+                                 ndk_hwcrypto::IHwCryptoKey::DerivedKey* aidl_return);
+
+    ndk::ScopedAStatus getHwCryptoOperations(
+            std::shared_ptr<ndk_hwcrypto::IHwCryptoOperations>* aidl_return);
+
+    ndk::ScopedAStatus importClearKey(const ndk_hwcrypto::types::ExplicitKeyMaterial& keyMaterial,
+                                      const ndk_hwcrypto::KeyPolicy& newKeyPolicy,
+                                      std::shared_ptr<ndk_hwcrypto::IOpaqueKey>* aidl_return);
+
+    ndk::ScopedAStatus getCurrentDicePolicy(std::vector<uint8_t>* 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);
+
+    ndk::ScopedAStatus getKeyslotData(ndk_hwcrypto::IHwCryptoKey::KeySlot slotId,
+                                      std::shared_ptr<ndk_hwcrypto::IOpaqueKey>* aidl_return);
+};
+
+template <typename LHP, typename RHP>
+LHP convertKeyPolicy(const RHP& policyToConvert) {
+    LHP policy = LHP();
+    policy.usage = static_cast<decltype(policy.usage)>(policyToConvert.usage);
+    policy.keyLifetime = static_cast<decltype(policy.keyLifetime)>(policyToConvert.keyLifetime);
+    policy.keyType = static_cast<decltype(policy.keyType)>(policyToConvert.keyType);
+    policy.keyManagementKey = policyToConvert.keyManagementKey;
+    for (auto permission : policyToConvert.keyPermissions) {
+        policy.keyPermissions.push_back(
+                std::move(reinterpret_cast<decltype(policy.keyPermissions[0])>(permission)));
+    }
+    return policy;
+}
+
+template <typename CPP, typename NDK,
+          std::map<std::weak_ptr<NDK>, wp<CPP>, std::owner_less<>>& mapping>
+sp<CPP> retrieveCppBinder(const std::shared_ptr<NDK>& ndkBinder) {
+    if (ndkBinder == nullptr) {
+        return nullptr;
+    }
+    if (mapping.find(ndkBinder) == mapping.end()) {
+        LOG(ERROR) << "couldn't find wrapped key";
+        return nullptr;
+    }
+    auto cppBbinder = mapping[ndkBinder];
+    return cppBbinder.promote();
+}
+
+template <typename CPP_BINDER, typename NDK_BINDER, typename NDK_BASE,
+          std::map<std::weak_ptr<NDK_BINDER>, wp<CPP_BINDER>, std::owner_less<>>& mapping>
+void insertBinderMapping(const sp<CPP_BINDER>& cppBinder, std::shared_ptr<NDK_BINDER>* ndkBinder) {
+    std::shared_ptr<NDK_BINDER> spNdkBinder = NDK_BASE::Create(cppBinder);
+    std::weak_ptr<NDK_BINDER> wptrNdkBinder = spNdkBinder;
+    wp<CPP_BINDER> wpCppBinder = cppBinder;
+    mapping.insert({wptrNdkBinder, wpCppBinder});
+    *ndkBinder = spNdkBinder;
+}
+
+}  // namespace hwcryptohalservice
+}  // namespace trusty
+}  // namespace android
diff --git a/security/see/hwcrypto/default/hwcryptolib.cpp b/security/see/hwcrypto/default/hwcryptolib.cpp
new file mode 100644
index 0000000..0e15883
--- /dev/null
+++ b/security/see/hwcrypto/default/hwcryptolib.cpp
@@ -0,0 +1,412 @@
+/*
+ * 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.
+ */
+
+#include <aidl/android/hardware/security/see/hwcrypto/BnCryptoOperationContext.h>
+#include <aidl/android/hardware/security/see/hwcrypto/BnHwCryptoOperations.h>
+#include <aidl/android/hardware/security/see/hwcrypto/BnOpaqueKey.h>
+#include <aidl/android/hardware/security/see/hwcrypto/IOpaqueKey.h>
+#include <android-base/logging.h>
+#include <android/hardware/security/see/hwcrypto/BnHwCryptoKey.h>
+#include <binder/RpcTrusty.h>
+#include <trusty/tipc.h>
+#include <optional>
+#include <string>
+#include "hwcryptokeyimpl.h"
+
+using android::IBinder;
+using android::IInterface;
+using android::RpcSession;
+using android::RpcTrustyConnectWithSessionInitializer;
+using android::sp;
+using android::wp;
+using android::base::ErrnoError;
+using android::base::Error;
+using android::base::Result;
+using android::binder::Status;
+
+namespace android {
+namespace trusty {
+namespace hwcryptohalservice {
+
+#define HWCRYPTO_KEY_PORT "com.android.trusty.rust.hwcryptohal.V1"
+
+// Even though we get the cpp_hwcrypto::IOpaqueKey and cpp_hwcrypto::ICryptoOperationContext and
+// create the ndk_hwcrypto wrappers on this library we cannot cast them back when we need them
+// because they are received on the function calls as binder objects and there is no reliable
+// we to do this cast yet. Because of that we are creating maps to hold the wrapped objects
+// and translate them on function calls.
+// TODO: Add cleanup of both keyMapping and contextMapping once we have more test infrastructure in
+//       place.
+std::map<std::weak_ptr<ndk_hwcrypto::IOpaqueKey>, wp<cpp_hwcrypto::IOpaqueKey>, std::owner_less<>>
+        keyMapping;
+std::map<std::weak_ptr<ndk_hwcrypto::ICryptoOperationContext>,
+         wp<cpp_hwcrypto::ICryptoOperationContext>, std::owner_less<>>
+        contextMapping;
+
+static ndk::ScopedAStatus convertStatus(Status status) {
+    if (status.isOk()) {
+        return ndk::ScopedAStatus::ok();
+    } else {
+        auto exCode = status.exceptionCode();
+        if (exCode == Status::Exception::EX_SERVICE_SPECIFIC) {
+            return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
+                    status.serviceSpecificErrorCode(), status.exceptionMessage());
+        } else {
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(exCode,
+                                                                    status.exceptionMessage());
+        }
+    }
+}
+
+static std::optional<cpp_hwcrypto::types::ExplicitKeyMaterial> convertExplicitKeyMaterial(
+        const ndk_hwcrypto::types::ExplicitKeyMaterial& keyMaterial) {
+    auto explicitKeyCpp = cpp_hwcrypto::types::ExplicitKeyMaterial();
+
+    if (keyMaterial.getTag() == ndk_hwcrypto::types::ExplicitKeyMaterial::aes) {
+        auto aesKey = keyMaterial.get<ndk_hwcrypto::types::ExplicitKeyMaterial::aes>();
+        auto aesKeyCpp = cpp_hwcrypto::types::AesKey();
+        if (aesKey.getTag() == ndk_hwcrypto::types::AesKey::aes128) {
+            aesKeyCpp.set<cpp_hwcrypto::types::AesKey::aes128>(
+                    aesKey.get<ndk_hwcrypto::types::AesKey::aes128>());
+            explicitKeyCpp.set<cpp_hwcrypto::types::ExplicitKeyMaterial::aes>(aesKeyCpp);
+        } else if (aesKey.getTag() == ndk_hwcrypto::types::AesKey::aes256) {
+            aesKeyCpp.set<cpp_hwcrypto::types::AesKey::aes256>(
+                    aesKey.get<ndk_hwcrypto::types::AesKey::aes256>());
+            explicitKeyCpp.set<cpp_hwcrypto::types::ExplicitKeyMaterial::aes>(aesKeyCpp);
+        } else {
+            LOG(ERROR) << "unknown AesKey type";
+            return std::nullopt;
+        }
+    } else if (keyMaterial.getTag() == ndk_hwcrypto::types::ExplicitKeyMaterial::hmac) {
+        auto hmacKey = keyMaterial.get<ndk_hwcrypto::types::ExplicitKeyMaterial::hmac>();
+        auto hmacKeyCpp = cpp_hwcrypto::types::HmacKey();
+        if (hmacKey.getTag() == ndk_hwcrypto::types::HmacKey::sha256) {
+            hmacKeyCpp.set<cpp_hwcrypto::types::HmacKey::sha256>(
+                    hmacKey.get<ndk_hwcrypto::types::HmacKey::sha256>());
+            explicitKeyCpp.set<cpp_hwcrypto::types::ExplicitKeyMaterial::hmac>(hmacKeyCpp);
+        } else if (hmacKey.getTag() == ndk_hwcrypto::types::HmacKey::sha512) {
+            hmacKeyCpp.set<cpp_hwcrypto::types::HmacKey::sha512>(
+                    hmacKey.get<ndk_hwcrypto::types::HmacKey::sha512>());
+            explicitKeyCpp.set<cpp_hwcrypto::types::ExplicitKeyMaterial::hmac>(hmacKeyCpp);
+        } else {
+            LOG(ERROR) << "unknown HmacKey type";
+            return std::nullopt;
+        }
+    } else {
+        LOG(ERROR) << "unknown Key type";
+        return std::nullopt;
+    }
+    return explicitKeyCpp;
+}
+
+class HwCryptoOperationContextNdk : public ndk_hwcrypto::BnCryptoOperationContext {
+  private:
+    sp<cpp_hwcrypto::ICryptoOperationContext> mContext;
+
+  public:
+    HwCryptoOperationContextNdk(sp<cpp_hwcrypto::ICryptoOperationContext> operations)
+        : mContext(std::move(operations)) {}
+
+    static std::shared_ptr<HwCryptoOperationContextNdk> Create(
+            sp<cpp_hwcrypto::ICryptoOperationContext> operations) {
+        if (operations == nullptr) {
+            return nullptr;
+        }
+        std::shared_ptr<HwCryptoOperationContextNdk> contextNdk =
+                ndk::SharedRefBase::make<HwCryptoOperationContextNdk>(std::move(operations));
+
+        if (!contextNdk) {
+            LOG(ERROR) << "failed to allocate HwCryptoOperationContext";
+            return nullptr;
+        }
+        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) {
+    cpp_hwcrypto::types::MemoryBufferReference cppMemBuffRef;
+    switch (ndkOperationData.getTag()) {
+        case ndk_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:
+            cppMemBuffRef.startOffset =
+                    ndkOperationData
+                            .get<ndk_hwcrypto::types::OperationData::memoryBufferReference>()
+                            .startOffset;
+            cppMemBuffRef.sizeBytes =
+                    ndkOperationData
+                            .get<ndk_hwcrypto::types::OperationData::memoryBufferReference>()
+                            .sizeBytes;
+            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";
+    }
+    return {};
+}
+
+class HwCryptoOperationsNdk : public ndk_hwcrypto::BnHwCryptoOperations {
+  private:
+    sp<cpp_hwcrypto::IHwCryptoOperations> mHwCryptoOperations;
+
+  public:
+    HwCryptoOperationsNdk(sp<cpp_hwcrypto::IHwCryptoOperations> operations)
+        : mHwCryptoOperations(std::move(operations)) {}
+
+    static std::shared_ptr<HwCryptoOperationsNdk> Create(
+            sp<cpp_hwcrypto::IHwCryptoOperations> operations) {
+        if (operations == nullptr) {
+            return nullptr;
+        }
+        std::shared_ptr<HwCryptoOperationsNdk> operationsNdk =
+                ndk::SharedRefBase::make<HwCryptoOperationsNdk>(std::move(operations));
+
+        if (!operationsNdk) {
+            LOG(ERROR) << "failed to allocate HwCryptoOperations";
+            return nullptr;
+        }
+        return operationsNdk;
+    }
+
+    ndk::ScopedAStatus processCommandList(
+            std::vector<ndk_hwcrypto::CryptoOperationSet>* /*operationSets*/,
+            std::vector<ndk_hwcrypto::CryptoOperationResult>* /*aidl_return*/) {
+        return ndk::ScopedAStatus::ok();
+    }
+};
+
+class OpaqueKeyNdk : public ndk_hwcrypto::BnOpaqueKey {
+  private:
+    sp<cpp_hwcrypto::IOpaqueKey> mOpaqueKey;
+
+  public:
+    OpaqueKeyNdk(sp<cpp_hwcrypto::IOpaqueKey> opaqueKey) : mOpaqueKey(std::move(opaqueKey)) {}
+
+    static std::shared_ptr<OpaqueKeyNdk> Create(sp<cpp_hwcrypto::IOpaqueKey> opaqueKey) {
+        if (opaqueKey == nullptr) {
+            return nullptr;
+        }
+        std::shared_ptr<OpaqueKeyNdk> opaqueKeyNdk =
+                ndk::SharedRefBase::make<OpaqueKeyNdk>(std::move(opaqueKey));
+
+        if (!opaqueKeyNdk) {
+            LOG(ERROR) << "failed to allocate HwCryptoKey";
+            return nullptr;
+        }
+        return opaqueKeyNdk;
+    }
+
+    ndk::ScopedAStatus exportWrappedKey(
+            const std::shared_ptr<ndk_hwcrypto::IOpaqueKey>& wrappingKey,
+            ::std::vector<uint8_t>* aidl_return) {
+        Status status = Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
+        auto wrappingKeyNdk =
+                retrieveCppBinder<cpp_hwcrypto::IOpaqueKey, ndk_hwcrypto::IOpaqueKey, keyMapping>(
+                        wrappingKey);
+        if (wrappingKeyNdk == nullptr) {
+            LOG(ERROR) << "couldn't get wrapped key";
+            return convertStatus(status);
+        }
+        status = mOpaqueKey->exportWrappedKey(wrappingKeyNdk, aidl_return);
+        return convertStatus(status);
+    }
+
+    ndk::ScopedAStatus getKeyPolicy(ndk_hwcrypto::KeyPolicy* aidl_return) {
+        Status status = Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
+        if (aidl_return == nullptr) {
+            LOG(ERROR) << "return value passed to getKeyPolicy is nullptr";
+            return convertStatus(status);
+        }
+        cpp_hwcrypto::KeyPolicy cppPolicy = cpp_hwcrypto::KeyPolicy();
+
+        status = mOpaqueKey->getKeyPolicy(&cppPolicy);
+        if (status.isOk()) {
+            auto ndkPolicy =
+                    convertKeyPolicy<ndk_hwcrypto::KeyPolicy, cpp_hwcrypto::KeyPolicy>(cppPolicy);
+            *aidl_return = std::move(ndkPolicy);
+        }
+        return convertStatus(status);
+    }
+
+    ndk::ScopedAStatus getPublicKey(::std::vector<uint8_t>* aidl_return) {
+        auto status = mOpaqueKey->getPublicKey(aidl_return);
+        return convertStatus(status);
+    }
+
+    ndk::ScopedAStatus getShareableToken(const ::std::vector<uint8_t>& sealingDicePolicy,
+                                         ndk_hwcrypto::types::OpaqueKeyToken* aidl_return) {
+        Status status = Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
+        if (aidl_return == nullptr) {
+            LOG(ERROR) << "return value passed to getShareableToken is nullptr";
+            return convertStatus(status);
+        }
+        cpp_hwcrypto::types::OpaqueKeyToken binder_return;
+        status = mOpaqueKey->getShareableToken(sealingDicePolicy, &binder_return);
+        if (status.isOk()) {
+            aidl_return->keyToken = std::move(binder_return.keyToken);
+        }
+        return convertStatus(status);
+    }
+
+    ndk::ScopedAStatus setProtectionId(
+            const ndk_hwcrypto::types::ProtectionId /*protectionId*/,
+            const ::std::vector<ndk_hwcrypto::types::OperationType>& /*allowedOperations*/) {
+        return ndk::ScopedAStatus::ok();
+    }
+};
+
+Result<void> HwCryptoKey::connectToTrusty(const char* tipcDev) {
+    assert(!mSession);
+    mSession = RpcTrustyConnectWithSessionInitializer(tipcDev, HWCRYPTO_KEY_PORT, [](auto) {});
+    if (!mSession) {
+        return ErrnoError() << "failed to connect to hwcrypto";
+    }
+    mRoot = mSession->getRootObject();
+    mHwCryptoServer = cpp_hwcrypto::IHwCryptoKey::asInterface(mRoot);
+    return {};
+}
+
+HwCryptoKey::HwCryptoKey() {}
+
+std::shared_ptr<HwCryptoKey> HwCryptoKey::Create(const char* tipcDev) {
+    std::shared_ptr<HwCryptoKey> hwCrypto = ndk::SharedRefBase::make<HwCryptoKey>();
+
+    if (!hwCrypto) {
+        LOG(ERROR) << "failed to allocate HwCryptoKey";
+        return nullptr;
+    }
+
+    auto ret = hwCrypto->connectToTrusty(tipcDev);
+    if (!ret.ok()) {
+        LOG(ERROR) << "failed to connect HwCryptoKey to Trusty: " << ret.error();
+        return nullptr;
+    }
+
+    return hwCrypto;
+}
+
+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();
+}
+
+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();
+}
+
+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();
+}
+
+ndk::ScopedAStatus HwCryptoKey::getHwCryptoOperations(
+        std::shared_ptr<ndk_hwcrypto::IHwCryptoOperations>* aidl_return) {
+    Status status = Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
+    if (aidl_return == nullptr) {
+        LOG(ERROR) << "return value passed to getHwCryptoOperations is nullptr";
+        return convertStatus(status);
+    }
+    sp<cpp_hwcrypto::IHwCryptoOperations> binder_return;
+    status = mHwCryptoServer->getHwCryptoOperations(&binder_return);
+    if (status.isOk()) {
+        std::shared_ptr<ndk_hwcrypto::IHwCryptoOperations> operations =
+                HwCryptoOperationsNdk::Create(binder_return);
+        *aidl_return = operations;
+    }
+    return convertStatus(status);
+}
+
+ndk::ScopedAStatus HwCryptoKey::importClearKey(
+        const ndk_hwcrypto::types::ExplicitKeyMaterial& keyMaterial,
+        const ndk_hwcrypto::KeyPolicy& newKeyPolicy,
+        std::shared_ptr<ndk_hwcrypto::IOpaqueKey>* aidl_return) {
+    sp<cpp_hwcrypto::IOpaqueKey> binder_return = nullptr;
+    Status status = Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
+    if (aidl_return == nullptr) {
+        LOG(ERROR) << "return value passed to importClearKey is nullptr";
+        return convertStatus(status);
+    }
+    auto cppKeyPolicy =
+            convertKeyPolicy<cpp_hwcrypto::KeyPolicy, ndk_hwcrypto::KeyPolicy>(newKeyPolicy);
+    auto explicitKeyCpp = convertExplicitKeyMaterial(keyMaterial);
+    if (!explicitKeyCpp.has_value()) {
+        LOG(ERROR) << "couldn't convert key material";
+        return convertStatus(status);
+    }
+    status = mHwCryptoServer->importClearKey(explicitKeyCpp.value(), cppKeyPolicy, &binder_return);
+    if (status.isOk()) {
+        if ((binder_return != nullptr)) {
+            insertBinderMapping<cpp_hwcrypto::IOpaqueKey, ndk_hwcrypto::IOpaqueKey, OpaqueKeyNdk,
+                                keyMapping>(binder_return, aidl_return);
+        } else {
+            *aidl_return = nullptr;
+        }
+    }
+    return convertStatus(status);
+}
+
+ndk::ScopedAStatus HwCryptoKey::getCurrentDicePolicy(std::vector<uint8_t>* aidl_return) {
+    auto status = mHwCryptoServer->getCurrentDicePolicy(aidl_return);
+    return convertStatus(status);
+}
+
+ndk::ScopedAStatus HwCryptoKey::keyTokenImport(
+        const ndk_hwcrypto::types::OpaqueKeyToken& requestedKey,
+        const ::std::vector<uint8_t>& sealingDicePolicy,
+        std::shared_ptr<ndk_hwcrypto::IOpaqueKey>* aidl_return) {
+    Status status = Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
+    if (aidl_return == nullptr) {
+        LOG(ERROR) << "return value passed to keyTokenImport is nullptr";
+        return convertStatus(status);
+    }
+    sp<cpp_hwcrypto::IOpaqueKey> binder_return;
+    cpp_hwcrypto::types::OpaqueKeyToken requestedKeyCpp;
+    // trying first a shallow copy of the vector
+    requestedKeyCpp.keyToken = requestedKey.keyToken;
+    status = mHwCryptoServer->keyTokenImport(requestedKeyCpp, sealingDicePolicy, &binder_return);
+    if (status.isOk()) {
+        std::shared_ptr<ndk_hwcrypto::IOpaqueKey> opaqueKey = OpaqueKeyNdk::Create(binder_return);
+        *aidl_return = opaqueKey;
+    }
+    return convertStatus(status);
+}
+
+ndk::ScopedAStatus HwCryptoKey::getKeyslotData(
+        ndk_hwcrypto::IHwCryptoKey::KeySlot /*slotId*/,
+        std::shared_ptr<ndk_hwcrypto::IOpaqueKey>* /*aidl_return*/) {
+    return ndk::ScopedAStatus::fromServiceSpecificError(
+            ndk_hwcrypto::types::HalErrorCode::UNAUTHORIZED);
+}
+
+}  // namespace hwcryptohalservice
+}  // namespace trusty
+}  // namespace android