Merge changes from topic "broadcastradio-aidl"

* changes:
  Default implementation for BroadcastRadio AIDL HAL
  Migrate broadcast radio HAL from HIDL to AIDL
diff --git a/audio/aidl/android/hardware/audio/effect/IEffect.aidl b/audio/aidl/android/hardware/audio/effect/IEffect.aidl
index 44e916b..d7a9501 100644
--- a/audio/aidl/android/hardware/audio/effect/IEffect.aidl
+++ b/audio/aidl/android/hardware/audio/effect/IEffect.aidl
@@ -31,24 +31,26 @@
      *
      * @throws a EX_UNSUPPORTED_OPERATION if device capability/resource is not enough or system
      *         failure happens.
-     * @note Open an already-opened effect instance should do nothing and not result in throw error.
+     * @note Open an already-opened effect instance should do nothing and should not throw an error.
      */
     void open();
 
     /**
-     * Called by the client to close the effect instance, instance context will be kept after
-     * close, but processing thread should be destroyed and consume no CPU. It is recommended to
-     * close the effect on the client side as soon as it becomes unused, it's client responsibility
-     * to make sure all parameter/buffer is correct if client wants to reopen a closed instance.
+     * Called by the client to close the effect instance, processing thread should be destroyed and
+     * consume no CPU after close.
      *
-     * Effect instance close interface should always success unless:
+     * It is recommended to close the effect on the client side as soon as it becomes unused, it's
+     * client responsibility to make sure all parameter/buffer is correct if client wants to reopen
+     * a closed instance.
+     *
+     * Effect instance close interface should always succeed unless:
      * 1. The effect instance is not in a proper state to be closed, for example it's still in
      * processing state.
      * 2. There is system/hardware related failure when close.
      *
      * @throws EX_ILLEGAL_STATE if the effect instance is not in a proper state to be closed.
      * @throws EX_UNSUPPORTED_OPERATION if the effect instance failed to close for any other reason.
-     * @note Close an already-closed effect should do nothing and not result in throw error.
+     * @note Close an already-closed effect should do nothing and should not throw an error.
      */
     void close();
 
diff --git a/audio/aidl/default/EffectFactory.cpp b/audio/aidl/default/EffectFactory.cpp
index ea9d470..a9848fd 100644
--- a/audio/aidl/default/EffectFactory.cpp
+++ b/audio/aidl/default/EffectFactory.cpp
@@ -29,23 +29,9 @@
     // TODO: implement this with xml parser on audio_effect.xml, and filter with optional
     // parameters.
     Descriptor::Identity id;
-    id.type = {static_cast<int32_t>(0x0bed4300),
-               0xddd6,
-               0x11db,
-               0x8f34,
-               {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
-    id.uuid = EqualizerUUID;
+    id.type = EqualizerTypeUUID;
+    id.uuid = EqualizerSwImplUUID;
     mIdentityList.push_back(id);
-    // TODO: Add visualizer with default implementation later
-#if 0
-    id.type = {static_cast<int32_t>(0xd3467faa),
-               0xacc7,
-               0x4d34,
-               0xacaf,
-               {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
-    id.uuid = VisualizerUUID;
-    mIdentityList.push_back(id);
-#endif
 }
 
 ndk::ScopedAStatus Factory::queryEffects(const std::optional<AudioUuid>& in_type,
@@ -63,7 +49,7 @@
         const AudioUuid& in_impl_uuid,
         std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>* _aidl_return) {
     LOG(DEBUG) << __func__ << ": UUID " << in_impl_uuid.toString();
-    if (in_impl_uuid == EqualizerUUID) {
+    if (in_impl_uuid == EqualizerSwImplUUID) {
         *_aidl_return = ndk::SharedRefBase::make<Equalizer>();
     } else {
         LOG(ERROR) << __func__ << ": UUID "
diff --git a/audio/aidl/default/EffectMain.cpp b/audio/aidl/default/EffectMain.cpp
index b30f2e7..3219dd6 100644
--- a/audio/aidl/default/EffectMain.cpp
+++ b/audio/aidl/default/EffectMain.cpp
@@ -23,7 +23,7 @@
 int main() {
     // This is a debug implementation, always enable debug logging.
     android::base::SetMinimumLogSeverity(::android::base::DEBUG);
-    ABinderProcess_setThreadPoolMaxThreadCount(1);
+    ABinderProcess_setThreadPoolMaxThreadCount(0);
 
     auto effectFactory =
             ndk::SharedRefBase::make<aidl::android::hardware::audio::effect::Factory>();
diff --git a/audio/aidl/default/equalizer/Equalizer.cpp b/audio/aidl/default/equalizer/Equalizer.cpp
index dae3ab7..8b157fa 100644
--- a/audio/aidl/default/equalizer/Equalizer.cpp
+++ b/audio/aidl/default/equalizer/Equalizer.cpp
@@ -21,15 +21,6 @@
 
 namespace aidl::android::hardware::audio::effect {
 
-Equalizer::Equalizer() {
-    // Implementation UUID
-    mDesc.common.id.uuid = {static_cast<int32_t>(0xce772f20),
-                            0x847d,
-                            0x11df,
-                            0xbb17,
-                            {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
-}
-
 ndk::ScopedAStatus Equalizer::open() {
     LOG(DEBUG) << __func__;
     return ndk::ScopedAStatus::ok();
diff --git a/audio/aidl/default/include/equalizer-impl/Equalizer.h b/audio/aidl/default/include/equalizer-impl/Equalizer.h
index 44b1d6d..ea16cb9 100644
--- a/audio/aidl/default/include/equalizer-impl/Equalizer.h
+++ b/audio/aidl/default/include/equalizer-impl/Equalizer.h
@@ -21,23 +21,31 @@
 
 namespace aidl::android::hardware::audio::effect {
 
-// Equalizer implementation UUID.
-static const ::aidl::android::media::audio::common::AudioUuid EqualizerUUID = {
+// Equalizer type UUID.
+static const ::aidl::android::media::audio::common::AudioUuid EqualizerTypeUUID = {
         static_cast<int32_t>(0x0bed4300),
         0xddd6,
         0x11db,
         0x8f34,
         {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
 
+// Equalizer implementation UUID.
+static const ::aidl::android::media::audio::common::AudioUuid EqualizerSwImplUUID = {
+        static_cast<int32_t>(0x0bed4300),
+        0x847d,
+        0x11df,
+        0xbb17,
+        {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
+
 class Equalizer : public BnEffect {
   public:
-    Equalizer();
+    Equalizer() = default;
     ndk::ScopedAStatus open() override;
     ndk::ScopedAStatus close() override;
     ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
 
   private:
     // Effect descriptor.
-    Descriptor mDesc = {.common.id.type = EqualizerUUID};
+    Descriptor mDesc = {.common = {.id = {.type = EqualizerTypeUUID, .uuid = EqualizerSwImplUUID}}};
 };
 }  // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp b/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp
index 9b100b1..8b5eb13 100644
--- a/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp
@@ -33,6 +33,7 @@
 #include <aidl/android/hardware/audio/effect/IFactory.h>
 
 #include "AudioHalBinderServiceUtil.h"
+#include "TestUtils.h"
 
 using namespace android;
 
@@ -45,7 +46,7 @@
 
 class EffectFactoryHelper {
   public:
-    EffectFactoryHelper(const std::string& name) : mServiceName(name) {}
+    explicit EffectFactoryHelper(const std::string& name) : mServiceName(name) {}
 
     void ConnectToFactoryService() {
         mEffectFactory = IFactory::fromBinder(binderUtil.connectToService(mServiceName));
@@ -60,27 +61,22 @@
 
     void QueryAllEffects() {
         EXPECT_NE(mEffectFactory, nullptr);
-        ScopedAStatus status =
-                mEffectFactory->queryEffects(std::nullopt, std::nullopt, &mCompleteIds);
-        EXPECT_EQ(status.getExceptionCode(), EX_NONE);
+        EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, std::nullopt, &mCompleteIds));
     }
 
     void QueryEffects(const std::optional<AudioUuid>& in_type,
                       const std::optional<AudioUuid>& in_instance,
                       std::vector<Descriptor::Identity>* _aidl_return) {
         EXPECT_NE(mEffectFactory, nullptr);
-        ScopedAStatus status = mEffectFactory->queryEffects(in_type, in_instance, _aidl_return);
-        EXPECT_EQ(status.getExceptionCode(), EX_NONE);
+        EXPECT_IS_OK(mEffectFactory->queryEffects(in_type, in_instance, _aidl_return));
         mIds = *_aidl_return;
     }
 
     void CreateEffects() {
         EXPECT_NE(mEffectFactory, nullptr);
-        ScopedAStatus status;
         for (const auto& id : mIds) {
             std::shared_ptr<IEffect> effect;
-            status = mEffectFactory->createEffect(id.uuid, &effect);
-            EXPECT_EQ(status.getExceptionCode(), EX_NONE) << id.toString();
+            EXPECT_IS_OK(mEffectFactory->createEffect(id.uuid, &effect));
             EXPECT_NE(effect, nullptr) << id.toString();
             mEffectIdMap[effect] = id;
         }
@@ -88,10 +84,8 @@
 
     void DestroyEffects() {
         EXPECT_NE(mEffectFactory, nullptr);
-        ScopedAStatus status;
         for (const auto& it : mEffectIdMap) {
-            status = mEffectFactory->destroyEffect(it.first);
-            EXPECT_EQ(status.getExceptionCode(), EX_NONE) << it.second.toString();
+            EXPECT_IS_OK(mEffectFactory->destroyEffect(it.first));
         }
         mEffectIdMap.clear();
     }
@@ -143,7 +137,7 @@
 TEST_P(EffectFactoryTest, QueriedDescriptorList) {
     std::vector<Descriptor::Identity> descriptors;
     mFactory.QueryEffects(std::nullopt, std::nullopt, &descriptors);
-    EXPECT_NE(static_cast<int>(descriptors.size()), 0);
+    EXPECT_NE(descriptors.size(), 0UL);
 }
 
 TEST_P(EffectFactoryTest, DescriptorUUIDNotNull) {
@@ -159,52 +153,52 @@
 TEST_P(EffectFactoryTest, QueriedDescriptorNotExistType) {
     std::vector<Descriptor::Identity> descriptors;
     mFactory.QueryEffects(nullUuid, std::nullopt, &descriptors);
-    EXPECT_EQ(static_cast<int>(descriptors.size()), 0);
+    EXPECT_EQ(descriptors.size(), 0UL);
 }
 
 TEST_P(EffectFactoryTest, QueriedDescriptorNotExistInstance) {
     std::vector<Descriptor::Identity> descriptors;
     mFactory.QueryEffects(std::nullopt, nullUuid, &descriptors);
-    EXPECT_EQ(static_cast<int>(descriptors.size()), 0);
+    EXPECT_EQ(descriptors.size(), 0UL);
 }
 
 TEST_P(EffectFactoryTest, CreateAndDestroyRepeat) {
     std::vector<Descriptor::Identity> descriptors;
     mFactory.QueryEffects(std::nullopt, std::nullopt, &descriptors);
-    int numIds = static_cast<int>(mFactory.GetEffectIds().size());
-    EXPECT_NE(numIds, 0);
+    auto numIds = mFactory.GetEffectIds().size();
+    EXPECT_NE(numIds, 0UL);
 
-    EXPECT_EQ(static_cast<int>(mFactory.GetEffectMap().size()), 0);
+    EXPECT_EQ(mFactory.GetEffectMap().size(), 0UL);
     mFactory.CreateEffects();
-    EXPECT_EQ(static_cast<int>(mFactory.GetEffectMap().size()), numIds);
+    EXPECT_EQ(mFactory.GetEffectMap().size(), numIds);
     mFactory.DestroyEffects();
-    EXPECT_EQ(static_cast<int>(mFactory.GetEffectMap().size()), 0);
+    EXPECT_EQ(mFactory.GetEffectMap().size(), 0UL);
 
     // Create and destroy again
     mFactory.CreateEffects();
-    EXPECT_EQ(static_cast<int>(mFactory.GetEffectMap().size()), numIds);
+    EXPECT_EQ(mFactory.GetEffectMap().size(), numIds);
     mFactory.DestroyEffects();
-    EXPECT_EQ(static_cast<int>(mFactory.GetEffectMap().size()), 0);
+    EXPECT_EQ(mFactory.GetEffectMap().size(), 0UL);
 }
 
 TEST_P(EffectFactoryTest, CreateMultipleInstanceOfSameEffect) {
     std::vector<Descriptor::Identity> descriptors;
     mFactory.QueryEffects(std::nullopt, std::nullopt, &descriptors);
-    int numIds = static_cast<int>(mFactory.GetEffectIds().size());
-    EXPECT_NE(numIds, 0);
+    auto numIds = mFactory.GetEffectIds().size();
+    EXPECT_NE(numIds, 0UL);
 
-    EXPECT_EQ(static_cast<int>(mFactory.GetEffectMap().size()), 0);
+    EXPECT_EQ(mFactory.GetEffectMap().size(), 0UL);
     mFactory.CreateEffects();
-    EXPECT_EQ(static_cast<int>(mFactory.GetEffectMap().size()), numIds);
+    EXPECT_EQ(mFactory.GetEffectMap().size(), numIds);
     // Create effect instances of same implementation
     mFactory.CreateEffects();
-    EXPECT_EQ(static_cast<int>(mFactory.GetEffectMap().size()), 2 * numIds);
+    EXPECT_EQ(mFactory.GetEffectMap().size(), 2 * numIds);
 
     mFactory.CreateEffects();
-    EXPECT_EQ(static_cast<int>(mFactory.GetEffectMap().size()), 3 * numIds);
+    EXPECT_EQ(mFactory.GetEffectMap().size(), 3 * numIds);
 
     mFactory.DestroyEffects();
-    EXPECT_EQ(static_cast<int>(mFactory.GetEffectMap().size()), 0);
+    EXPECT_EQ(mFactory.GetEffectMap().size(), 0UL);
 }
 
 INSTANTIATE_TEST_SUITE_P(EffectFactoryTest, EffectFactoryTest,
@@ -226,26 +220,19 @@
     }
 
     void OpenEffects() {
-        auto open = [](const std::shared_ptr<IEffect>& effect) {
-            ScopedAStatus status = effect->open();
-            EXPECT_EQ(status.getExceptionCode(), EX_NONE);
-        };
+        auto open = [](const std::shared_ptr<IEffect>& effect) { EXPECT_IS_OK(effect->open()); };
         EXPECT_NO_FATAL_FAILURE(ForEachEffect(open));
     }
 
     void CloseEffects() {
-        auto close = [](const std::shared_ptr<IEffect>& effect) {
-            ScopedAStatus status = effect->close();
-            EXPECT_EQ(status.getExceptionCode(), EX_NONE);
-        };
+        auto close = [](const std::shared_ptr<IEffect>& effect) { EXPECT_IS_OK(effect->close()); };
         EXPECT_NO_FATAL_FAILURE(ForEachEffect(close));
     }
 
     void GetEffectDescriptors() {
         auto get = [](const std::shared_ptr<IEffect>& effect) {
             Descriptor desc;
-            ScopedAStatus status = effect->getDescriptor(&desc);
-            EXPECT_EQ(status.getExceptionCode(), EX_NONE);
+            EXPECT_IS_OK(effect->getDescriptor(&desc));
         };
         EXPECT_NO_FATAL_FAILURE(ForEachEffect(get));
     }
@@ -253,7 +240,6 @@
     template <typename Functor>
     void ForEachEffect(Functor functor) {
         auto effectMap = mFactory.GetEffectMap();
-        ScopedAStatus status;
         for (const auto& it : effectMap) {
             SCOPED_TRACE(it.second.toString());
             functor(it.first);
@@ -299,10 +285,9 @@
     auto checker = [&](const std::shared_ptr<IEffect>& effect) {
         Descriptor desc;
         std::vector<Descriptor::Identity> idList;
-        ScopedAStatus status = effect->getDescriptor(&desc);
-        EXPECT_EQ(status.getExceptionCode(), EX_NONE);
+        EXPECT_IS_OK(effect->getDescriptor(&desc));
         mFactory.QueryEffects(desc.common.id.type, desc.common.id.uuid, &idList);
-        EXPECT_EQ(static_cast<int>(idList.size()), 1);
+        EXPECT_EQ(idList.size(), 1UL);
     };
     EXPECT_NO_FATAL_FAILURE(ForEachEffect(checker));
 
@@ -313,7 +298,7 @@
     auto vec = mFactory.GetCompleteEffectIdList();
     std::unordered_set<Descriptor::Identity, decltype(stringHash)> idSet(0, stringHash);
     for (auto it : vec) {
-        EXPECT_EQ(static_cast<int>(idSet.count(it)), 0);
+        EXPECT_EQ(idSet.count(it), 0UL);
         idSet.insert(it);
     }
 }
diff --git a/audio/policy/1.0/xml/api/current.txt b/audio/policy/1.0/xml/api/current.txt
index 0b77d45..84a2b71 100644
--- a/audio/policy/1.0/xml/api/current.txt
+++ b/audio/policy/1.0/xml/api/current.txt
@@ -217,6 +217,10 @@
     enum_constant public static final audio.policy.V1_0.UsageEnumType AUDIO_USAGE_GAME;
     enum_constant public static final audio.policy.V1_0.UsageEnumType AUDIO_USAGE_MEDIA;
     enum_constant public static final audio.policy.V1_0.UsageEnumType AUDIO_USAGE_NOTIFICATION;
+    enum_constant public static final audio.policy.V1_0.UsageEnumType AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED;
+    enum_constant public static final audio.policy.V1_0.UsageEnumType AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT;
+    enum_constant public static final audio.policy.V1_0.UsageEnumType AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST;
+    enum_constant public static final audio.policy.V1_0.UsageEnumType AUDIO_USAGE_NOTIFICATION_EVENT;
     enum_constant public static final audio.policy.V1_0.UsageEnumType AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE;
     enum_constant public static final audio.policy.V1_0.UsageEnumType AUDIO_USAGE_UNKNOWN;
     enum_constant public static final audio.policy.V1_0.UsageEnumType AUDIO_USAGE_VIRTUAL_SOURCE;
diff --git a/audio/policy/1.0/xml/audio_policy_engine_configuration.xsd b/audio/policy/1.0/xml/audio_policy_engine_configuration.xsd
index 3ce12e7..b58a6c8 100644
--- a/audio/policy/1.0/xml/audio_policy_engine_configuration.xsd
+++ b/audio/policy/1.0/xml/audio_policy_engine_configuration.xsd
@@ -347,6 +347,11 @@
             <xs:enumeration value="AUDIO_USAGE_ALARM"/>
             <xs:enumeration value="AUDIO_USAGE_NOTIFICATION"/>
             <xs:enumeration value="AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE"/>
+            <!-- Note: the following 3 values were deprecated in Android T (13) SDK -->
+            <xs:enumeration value="AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST"/>
+            <xs:enumeration value="AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT"/>
+            <xs:enumeration value="AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED"/>
+            <xs:enumeration value="AUDIO_USAGE_NOTIFICATION_EVENT"/>
             <xs:enumeration value="AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY"/>
             <xs:enumeration value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE"/>
             <xs:enumeration value="AUDIO_USAGE_ASSISTANCE_SONIFICATION"/>
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index 9a939d1..9b8e560 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -213,7 +213,7 @@
             <instance>default</instance>
         </interface>
     </hal>
-    <hal format="hidl" optional="false">
+    <hal format="hidl" optional="true">
         <name>android.hardware.gatekeeper</name>
         <version>1.0</version>
         <interface>
@@ -222,6 +222,14 @@
         </interface>
     </hal>
     <hal format="aidl" optional="true">
+        <name>android.hardware.gatekeeper</name>
+        <version>1</version>
+        <interface>
+            <name>IGatekeeper</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="aidl" optional="true">
         <name>android.hardware.gnss</name>
         <version>2</version>
         <interface>
diff --git a/gatekeeper/OWNERS b/gatekeeper/OWNERS
new file mode 100644
index 0000000..d95b856
--- /dev/null
+++ b/gatekeeper/OWNERS
@@ -0,0 +1,2 @@
+swillden@google.com
+guangzhu@google.com
diff --git a/gatekeeper/aidl/Android.bp b/gatekeeper/aidl/Android.bp
new file mode 100644
index 0000000..6b1bc7e
--- /dev/null
+++ b/gatekeeper/aidl/Android.bp
@@ -0,0 +1,29 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_interfaces_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+aidl_interface {
+    name: "android.hardware.gatekeeper",
+    vendor_available: true,
+    imports: [
+        "android.hardware.security.keymint-V2",
+    ],
+    srcs: ["android/hardware/gatekeeper/*.aidl"],
+    stability: "vintf",
+    backend: {
+        java: {
+            platform_apis: true,
+        },
+        ndk: {
+            apps_enabled: false,
+        },
+        cpp: {
+            enabled: false,
+        },
+    },
+}
diff --git a/gatekeeper/aidl/aidl_api/android.hardware.gatekeeper/current/android/hardware/gatekeeper/GatekeeperEnrollResponse.aidl b/gatekeeper/aidl/aidl_api/android.hardware.gatekeeper/current/android/hardware/gatekeeper/GatekeeperEnrollResponse.aidl
new file mode 100644
index 0000000..ae64ffc
--- /dev/null
+++ b/gatekeeper/aidl/aidl_api/android.hardware.gatekeeper/current/android/hardware/gatekeeper/GatekeeperEnrollResponse.aidl
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.gatekeeper;
+@VintfStability
+parcelable GatekeeperEnrollResponse {
+  int statusCode;
+  int timeoutMs;
+  long secureUserId;
+  byte[] data;
+}
diff --git a/gatekeeper/aidl/aidl_api/android.hardware.gatekeeper/current/android/hardware/gatekeeper/GatekeeperVerifyResponse.aidl b/gatekeeper/aidl/aidl_api/android.hardware.gatekeeper/current/android/hardware/gatekeeper/GatekeeperVerifyResponse.aidl
new file mode 100644
index 0000000..f55da30
--- /dev/null
+++ b/gatekeeper/aidl/aidl_api/android.hardware.gatekeeper/current/android/hardware/gatekeeper/GatekeeperVerifyResponse.aidl
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.gatekeeper;
+@VintfStability
+parcelable GatekeeperVerifyResponse {
+  int statusCode;
+  int timeoutMs;
+  android.hardware.security.keymint.HardwareAuthToken hardwareAuthToken;
+}
diff --git a/gatekeeper/aidl/aidl_api/android.hardware.gatekeeper/current/android/hardware/gatekeeper/IGatekeeper.aidl b/gatekeeper/aidl/aidl_api/android.hardware.gatekeeper/current/android/hardware/gatekeeper/IGatekeeper.aidl
new file mode 100644
index 0000000..1a6f1ff
--- /dev/null
+++ b/gatekeeper/aidl/aidl_api/android.hardware.gatekeeper/current/android/hardware/gatekeeper/IGatekeeper.aidl
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.gatekeeper;
+@SensitiveData @VintfStability
+interface IGatekeeper {
+  void deleteAllUsers();
+  void deleteUser(in int uid);
+  android.hardware.gatekeeper.GatekeeperEnrollResponse enroll(in int uid, in byte[] currentPasswordHandle, in byte[] currentPassword, in byte[] desiredPassword);
+  android.hardware.gatekeeper.GatekeeperVerifyResponse verify(in int uid, in long challenge, in byte[] enrolledPasswordHandle, in byte[] providedPassword);
+  const int STATUS_REENROLL = 1;
+  const int STATUS_OK = 0;
+  const int ERROR_GENERAL_FAILURE = -1;
+  const int ERROR_RETRY_TIMEOUT = -2;
+  const int ERROR_NOT_IMPLEMENTED = -3;
+}
diff --git a/gatekeeper/aidl/android/hardware/gatekeeper/GatekeeperEnrollResponse.aidl b/gatekeeper/aidl/android/hardware/gatekeeper/GatekeeperEnrollResponse.aidl
new file mode 100644
index 0000000..04bacf0
--- /dev/null
+++ b/gatekeeper/aidl/android/hardware/gatekeeper/GatekeeperEnrollResponse.aidl
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+package android.hardware.gatekeeper;
+
+/**
+ * Gatekeeper response to enroll requests has this structure as mandatory part
+ */
+@VintfStability
+parcelable GatekeeperEnrollResponse {
+    /**
+     * Request completion status
+     */
+    int statusCode;
+    /**
+     * Retry timeout in ms, if code == ERROR_RETRY_TIMEOUT
+     * otherwise unused (0)
+     */
+    int timeoutMs;
+    /**
+     * secure user id.
+     */
+    long secureUserId;
+    /**
+     * optional crypto blob. Opaque to Android system.
+     */
+    byte[] data;
+}
diff --git a/gatekeeper/aidl/android/hardware/gatekeeper/GatekeeperVerifyResponse.aidl b/gatekeeper/aidl/android/hardware/gatekeeper/GatekeeperVerifyResponse.aidl
new file mode 100644
index 0000000..bcf2d76
--- /dev/null
+++ b/gatekeeper/aidl/android/hardware/gatekeeper/GatekeeperVerifyResponse.aidl
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+package android.hardware.gatekeeper;
+
+import android.hardware.security.keymint.HardwareAuthToken;
+
+/**
+ * Gatekeeper response to verify requests has this structure as mandatory part
+ */
+@VintfStability
+parcelable GatekeeperVerifyResponse {
+    /**
+     * Request completion status
+     */
+    int statusCode;
+    /**
+     * Retry timeout in ms, if code == ERROR_RETRY_TIMEOUT
+     * otherwise unused (0)
+     */
+    int timeoutMs;
+    /**
+     * On successful verification of the password,
+     * IGatekeeper implementations must return hardware auth token
+     * in the response.
+     */
+    HardwareAuthToken hardwareAuthToken;
+}
diff --git a/gatekeeper/aidl/android/hardware/gatekeeper/IGatekeeper.aidl b/gatekeeper/aidl/android/hardware/gatekeeper/IGatekeeper.aidl
new file mode 100644
index 0000000..927293e
--- /dev/null
+++ b/gatekeeper/aidl/android/hardware/gatekeeper/IGatekeeper.aidl
@@ -0,0 +1,146 @@
+/*
+ * 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.
+ */
+
+package android.hardware.gatekeeper;
+
+import android.hardware.gatekeeper.GatekeeperEnrollResponse;
+import android.hardware.gatekeeper.GatekeeperVerifyResponse;
+
+@VintfStability
+@SensitiveData
+interface IGatekeeper {
+    /**
+     * enroll and verify binder calls may return a ServiceSpecificException
+     * with the following error codes.
+     */
+    /* Success, but upper layers should re-enroll the verified password due to a version change. */
+    const int STATUS_REENROLL = 1;
+    /* operation is successful */
+    const int STATUS_OK = 0;
+    /* operation is successful. */
+    const int ERROR_GENERAL_FAILURE = -1;
+    /* operation should  be retried after timeout. */
+    const int ERROR_RETRY_TIMEOUT = -2;
+    /* operation is not implemented. */
+    const int ERROR_NOT_IMPLEMENTED = -3;
+
+    /**
+     * Deletes all the enrolled_password_handles for all uid's. Once called,
+     * no users must be enrolled on the device.
+     * This is an optional method.
+     *
+     * Service status return:
+     *
+     * OK if all the users are deleted successfully.
+     * ERROR_GENERAL_FAILURE on failure.
+     * ERROR_NOT_IMPLEMENTED if not implemented.
+     */
+    void deleteAllUsers();
+
+    /**
+     * Deletes the enrolledPasswordHandle associated with the uid. Once deleted
+     * the user cannot be verified anymore.
+     * This is an optional method.
+     *
+     * Service status return:
+     *
+     * OK if user is deleted successfully.
+     * ERROR_GENERAL_FAILURE on failure.
+     * ERROR_NOT_IMPLEMENTED if not implemented.
+     *
+     * @param uid The Android user identifier
+     */
+    void deleteUser(in int uid);
+
+    /**
+     * Enrolls desiredPassword, which may be derived from a user selected pin
+     * or password, with the private key used only for enrolling authentication
+     * factor data.
+     *
+     * If there was already a password enrolled, current password handle must be
+     * passed in currentPasswordHandle, and current password must be passed in
+     * currentPassword. Valid currentPassword must verify() against
+     * currentPasswordHandle.
+     *
+     * Service status return:
+     *
+     * OK if password is enrolled successfully.
+     * ERROR_GENERAL_FAILURE on failure.
+     * ERROR_NOT_IMPLEMENTED if not implemented.
+     *
+     * @param uid The Android user identifier
+     *
+     * @param currentPasswordHandle The currently enrolled password handle the user
+     *    wants to replace. May be empty only if there's no currently enrolled
+     *    password. Otherwise must be non-empty.
+     *
+     * @param currentPassword The user's current password in plain text.
+     *    it MUST verify against current_password_handle if the latter is not-empty
+     *
+     * @param desiredPassword The new password the user wishes to enroll in
+     *    plaintext.
+     *
+     * @return
+     *    On success, data buffer must contain the new password handle referencing
+     *    the password provided in desiredPassword.
+     *    This buffer can be used on subsequent calls to enroll or
+     *    verify. response.statusCode must contain either ERROR_RETRY_TIMEOUT or
+     *    STATUS_OK. On error, this buffer must be empty. This method may return
+     *    ERROR_GENERAL_FAILURE on failure.
+     *    If ERROR_RETRY_TIMEOUT is returned, response.timeout must be non-zero.
+     */
+    GatekeeperEnrollResponse enroll(in int uid, in byte[] currentPasswordHandle,
+            in byte[] currentPassword, in byte[] desiredPassword);
+
+    /**
+     * Verifies that providedPassword matches enrolledPasswordHandle.
+     *
+     * Implementations of this module may retain the result of this call
+     * to attest to the recency of authentication.
+     *
+     * On success, returns verification token in response.data, which shall be
+     * usable to attest password verification to other trusted services.
+     *
+     * Service status return:
+     *
+     * OK if password is enrolled successfully.
+     * ERROR_GENERAL_FAILURE on failure.
+     * ERROR_NOT_IMPLEMENTED if not implemented.
+     *
+     * @param uid The Android user identifier
+     *
+     * @param challenge An optional challenge to authenticate against, or 0.
+     *    Used when a separate authenticator requests password verification,
+     *    or for transactional password authentication.
+     *
+     * @param enrolledPasswordHandle The currently enrolled password handle that
+     *    user wishes to verify against. Must be non-empty.
+     *
+     * @param providedPassword The plaintext password to be verified against the
+     *    enrolledPasswordHandle
+     *
+     * @return
+     *    On success, a HardwareAuthToken resulting from this verification is returned.
+     *    response.statusCode must contain either ERROR_RETRY_TIMEOUT or
+     *    or STATUS_REENROLL or STATUS_OK.
+     *    On error, data buffer must be empty.
+     *    This method may return ERROR_GENERAL_FAILURE on failure.
+     *    If password re-enrollment is necessary, it must return STATUS_REENROLL.
+     *    If ERROR_RETRY_TIMEOUT is returned, response.timeout must be non-zero.
+     */
+    GatekeeperVerifyResponse verify(in int uid, in long challenge, in byte[] enrolledPasswordHandle,
+            in byte[] providedPassword);
+}
diff --git a/gatekeeper/aidl/vts/functional/Android.bp b/gatekeeper/aidl/vts/functional/Android.bp
new file mode 100644
index 0000000..2fa80de
--- /dev/null
+++ b/gatekeeper/aidl/vts/functional/Android.bp
@@ -0,0 +1,39 @@
+//
+// 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.
+//
+
+package {
+    // See: http://go/android-license-faq
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_test {
+    name: "VtsHalGatekeeperTargetTest",
+    defaults: [
+        "VtsHalTargetTestDefaults",
+        "use_libaidlvintf_gtest_helper_static",
+        "keymint_use_latest_hal_aidl_ndk_shared",
+    ],
+    srcs: ["VtsHalGatekeeperTargetTest.cpp"],
+    shared_libs: [
+        "libbinder_ndk",
+        "libbase",
+    ],
+    static_libs: ["android.hardware.gatekeeper-V1-ndk"],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
+}
diff --git a/gatekeeper/aidl/vts/functional/VtsHalGatekeeperTargetTest.cpp b/gatekeeper/aidl/vts/functional/VtsHalGatekeeperTargetTest.cpp
new file mode 100644
index 0000000..c89243b
--- /dev/null
+++ b/gatekeeper/aidl/vts/functional/VtsHalGatekeeperTargetTest.cpp
@@ -0,0 +1,413 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "gatekeeper_aidl_hal_test"
+
+#include <inttypes.h>
+#include <unistd.h>
+
+#include <algorithm>
+#include <cmath>
+#include <string>
+#include <vector>
+
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/gatekeeper/GatekeeperEnrollResponse.h>
+#include <aidl/android/hardware/gatekeeper/GatekeeperVerifyResponse.h>
+#include <aidl/android/hardware/gatekeeper/IGatekeeper.h>
+#include <aidl/android/hardware/security/keymint/HardwareAuthToken.h>
+#include <android-base/endian.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <hardware/hw_auth_token.h>
+
+#include <log/log.h>
+
+using aidl::android::hardware::gatekeeper::GatekeeperEnrollResponse;
+using aidl::android::hardware::gatekeeper::GatekeeperVerifyResponse;
+using aidl::android::hardware::gatekeeper::IGatekeeper;
+using aidl::android::hardware::security::keymint::HardwareAuthToken;
+using Status = ::ndk::ScopedAStatus;
+
+struct GatekeeperRequest {
+    uint32_t uid;
+    uint64_t challenge;
+    std::vector<uint8_t> curPwdHandle;
+    std::vector<uint8_t> curPwd;
+    std::vector<uint8_t> newPwd;
+    GatekeeperRequest() : uid(0), challenge(0) {}
+};
+
+// ASSERT_* macros generate return "void" internally
+// we have to use EXPECT_* if we return anything but "void"
+static void verifyAuthToken(GatekeeperVerifyResponse& rsp) {
+    uint32_t auth_type = static_cast<uint32_t>(rsp.hardwareAuthToken.authenticatorType);
+    uint64_t auth_tstamp = static_cast<uint64_t>(rsp.hardwareAuthToken.timestamp.milliSeconds);
+
+    EXPECT_EQ(HW_AUTH_PASSWORD, auth_type);
+    EXPECT_NE(UINT64_C(~0), auth_tstamp);
+    ALOGI("Authenticator ID: %016" PRIX64, rsp.hardwareAuthToken.authenticatorId);
+    EXPECT_NE(UINT32_C(0), rsp.hardwareAuthToken.userId);
+}
+
+// The main test class for Gatekeeper AIDL HAL.
+class GatekeeperAidlTest : public ::testing::TestWithParam<std::string> {
+  protected:
+    void setUid(uint32_t uid) { uid_ = uid; }
+
+    Status doEnroll(GatekeeperRequest& req, GatekeeperEnrollResponse& rsp) {
+        Status ret;
+        while (true) {
+            ret = gatekeeper_->enroll(uid_, req.curPwdHandle, req.curPwd, req.newPwd, &rsp);
+            if (ret.isOk()) break;
+            if (getReturnStatusCode(ret) != IGatekeeper::ERROR_RETRY_TIMEOUT) break;
+            ALOGI("%s: got retry code; retrying in 1 sec", __func__);
+            sleep(1);
+        }
+        return ret;
+    }
+
+    Status doVerify(GatekeeperRequest& req, GatekeeperVerifyResponse& rsp) {
+        Status ret;
+        while (true) {
+            ret = gatekeeper_->verify(uid_, req.challenge, req.curPwdHandle, req.newPwd, &rsp);
+            if (ret.isOk()) break;
+            if (getReturnStatusCode(ret) != IGatekeeper::ERROR_RETRY_TIMEOUT) break;
+            ALOGI("%s: got retry code; retrying in 1 sec", __func__);
+            sleep(1);
+        }
+        return ret;
+    }
+
+    Status doDeleteUser() { return gatekeeper_->deleteUser(uid_); }
+
+    Status doDeleteAllUsers() { return gatekeeper_->deleteAllUsers(); }
+
+    void generatePassword(std::vector<uint8_t>& password, uint8_t seed) {
+        password.resize(16);
+        memset(password.data(), seed, password.size());
+    }
+
+    void checkEnroll(GatekeeperEnrollResponse& rsp, Status& ret, bool expectSuccess) {
+        if (expectSuccess) {
+            EXPECT_TRUE(ret.isOk());
+            EXPECT_EQ(IGatekeeper::STATUS_OK, rsp.statusCode);
+            EXPECT_NE(nullptr, rsp.data.data());
+            EXPECT_GT(rsp.data.size(), UINT32_C(0));
+            EXPECT_NE(UINT32_C(0), rsp.secureUserId);
+        } else {
+            EXPECT_EQ(IGatekeeper::ERROR_GENERAL_FAILURE, getReturnStatusCode(ret));
+            EXPECT_EQ(UINT32_C(0), rsp.data.size());
+        }
+    }
+
+    void checkVerify(GatekeeperVerifyResponse& rsp, Status& ret, uint64_t challenge,
+                     bool expectSuccess) {
+        if (expectSuccess) {
+            EXPECT_TRUE(ret.isOk());
+            EXPECT_GE(rsp.statusCode, IGatekeeper::STATUS_OK);
+            EXPECT_LE(rsp.statusCode, IGatekeeper::STATUS_REENROLL);
+
+            verifyAuthToken(rsp);
+            EXPECT_EQ(challenge, rsp.hardwareAuthToken.challenge);
+        } else {
+            EXPECT_EQ(IGatekeeper::ERROR_GENERAL_FAILURE, getReturnStatusCode(ret));
+        }
+    }
+
+    void enrollNewPassword(std::vector<uint8_t>& password, GatekeeperEnrollResponse& rsp,
+                           bool expectSuccess) {
+        GatekeeperRequest req;
+        req.newPwd = password;
+        Status ret = doEnroll(req, rsp);
+        checkEnroll(rsp, ret, expectSuccess);
+    }
+
+    void verifyPassword(std::vector<uint8_t>& password, std::vector<uint8_t>& passwordHandle,
+                        uint64_t challenge, GatekeeperVerifyResponse& verifyRsp,
+                        bool expectSuccess) {
+        GatekeeperRequest verifyReq;
+
+        // build verify request for the same password (we want it to succeed)
+        verifyReq.newPwd = password;
+        // use enrolled password handle we've got
+        verifyReq.curPwdHandle = passwordHandle;
+        verifyReq.challenge = challenge;
+        Status ret = doVerify(verifyReq, verifyRsp);
+        checkVerify(verifyRsp, ret, challenge, expectSuccess);
+    }
+
+    int32_t getReturnStatusCode(const Status& result) {
+        if (!result.isOk()) {
+            if (result.getExceptionCode() == EX_SERVICE_SPECIFIC) {
+                return result.getServiceSpecificError();
+            }
+            return IGatekeeper::ERROR_GENERAL_FAILURE;
+        }
+        return IGatekeeper::STATUS_OK;
+    }
+
+  protected:
+    std::shared_ptr<IGatekeeper> gatekeeper_;
+    uint32_t uid_;
+
+  public:
+    GatekeeperAidlTest() : uid_(0) {}
+    virtual void SetUp() override {
+        gatekeeper_ = IGatekeeper::fromBinder(
+            ndk::SpAIBinder(AServiceManager_waitForService(GetParam().c_str())));
+        ASSERT_NE(nullptr, gatekeeper_.get());
+        doDeleteAllUsers();
+    }
+
+    virtual void TearDown() override { doDeleteAllUsers(); }
+};
+
+/**
+ * Ensure we can enroll new password
+ */
+TEST_P(GatekeeperAidlTest, EnrollSuccess) {
+    std::vector<uint8_t> password;
+    GatekeeperEnrollResponse rsp;
+    ALOGI("Testing Enroll (expected success)");
+    generatePassword(password, 0);
+    enrollNewPassword(password, rsp, true);
+    ALOGI("Testing Enroll done");
+}
+
+/**
+ * Ensure we can not enroll empty password
+ */
+TEST_P(GatekeeperAidlTest, EnrollNoPassword) {
+    std::vector<uint8_t> password;
+    GatekeeperEnrollResponse rsp;
+    ALOGI("Testing Enroll (expected failure)");
+    enrollNewPassword(password, rsp, false);
+    ALOGI("Testing Enroll done");
+}
+
+/**
+ * Ensure we can successfully verify previously enrolled password
+ */
+TEST_P(GatekeeperAidlTest, VerifySuccess) {
+    GatekeeperEnrollResponse enrollRsp;
+    GatekeeperVerifyResponse verifyRsp;
+    std::vector<uint8_t> password;
+
+    ALOGI("Testing Enroll+Verify (expected success)");
+    generatePassword(password, 0);
+    enrollNewPassword(password, enrollRsp, true);
+    verifyPassword(password, enrollRsp.data, 1, verifyRsp, true);
+
+    ALOGI("Testing unenrolled password doesn't verify");
+    verifyRsp = {0, 0, {}};
+    generatePassword(password, 1);
+    verifyPassword(password, enrollRsp.data, 1, verifyRsp, false);
+    ALOGI("Testing Enroll+Verify done");
+}
+
+/**
+ * Ensure we can securely update password (keep the same
+ * secure user_id) if we prove we know old password
+ */
+TEST_P(GatekeeperAidlTest, TrustedReenroll) {
+    GatekeeperEnrollResponse enrollRsp;
+    GatekeeperRequest reenrollReq;
+    GatekeeperEnrollResponse reenrollRsp;
+    GatekeeperVerifyResponse verifyRsp;
+    GatekeeperVerifyResponse reenrollVerifyRsp;
+    std::vector<uint8_t> password;
+    std::vector<uint8_t> newPassword;
+
+    generatePassword(password, 0);
+
+    ALOGI("Testing Trusted Reenroll (expected success)");
+    enrollNewPassword(password, enrollRsp, true);
+    verifyPassword(password, enrollRsp.data, 0, verifyRsp, true);
+    ALOGI("Primary Enroll+Verify done");
+
+    generatePassword(newPassword, 1);
+    reenrollReq.newPwd = newPassword;
+    reenrollReq.curPwd = password;
+    reenrollReq.curPwdHandle = enrollRsp.data;
+
+    Status ret = doEnroll(reenrollReq, reenrollRsp);
+    checkEnroll(reenrollRsp, ret, true);
+    verifyPassword(newPassword, reenrollRsp.data, 0, reenrollVerifyRsp, true);
+    ALOGI("Trusted ReEnroll+Verify done");
+
+    verifyAuthToken(verifyRsp);
+    verifyAuthToken(reenrollVerifyRsp);
+    EXPECT_EQ(verifyRsp.hardwareAuthToken.userId, reenrollVerifyRsp.hardwareAuthToken.userId);
+    ALOGI("Testing Trusted Reenroll done");
+}
+
+/**
+ * Ensure we can update password (and get new
+ * secure user_id) if we don't know old password
+ */
+TEST_P(GatekeeperAidlTest, UntrustedReenroll) {
+    GatekeeperEnrollResponse enrollRsp;
+    GatekeeperEnrollResponse reenrollRsp;
+    GatekeeperVerifyResponse verifyRsp;
+    GatekeeperVerifyResponse reenrollVerifyRsp;
+    std::vector<uint8_t> password;
+    std::vector<uint8_t> newPassword;
+
+    ALOGI("Testing Untrusted Reenroll (expected success)");
+    generatePassword(password, 0);
+    enrollNewPassword(password, enrollRsp, true);
+    verifyPassword(password, enrollRsp.data, 0, verifyRsp, true);
+    ALOGI("Primary Enroll+Verify done");
+
+    generatePassword(newPassword, 1);
+    enrollNewPassword(newPassword, reenrollRsp, true);
+    verifyPassword(newPassword, reenrollRsp.data, 0, reenrollVerifyRsp, true);
+    ALOGI("Untrusted ReEnroll+Verify done");
+
+    verifyAuthToken(verifyRsp);
+    verifyAuthToken(reenrollVerifyRsp);
+    EXPECT_NE(verifyRsp.hardwareAuthToken.userId, reenrollVerifyRsp.hardwareAuthToken.userId);
+    ALOGI("Testing Untrusted Reenroll done");
+}
+
+/**
+ * Ensure we don't get successful verify with invalid data
+ */
+TEST_P(GatekeeperAidlTest, VerifyNoData) {
+    std::vector<uint8_t> password;
+    std::vector<uint8_t> passwordHandle;
+    GatekeeperVerifyResponse verifyRsp;
+
+    ALOGI("Testing Verify (expected failure)");
+    verifyPassword(password, passwordHandle, 0, verifyRsp, false);
+    ALOGI("Testing Verify done");
+}
+
+/**
+ * Ensure we can not verify password after we enrolled it and then deleted user
+ */
+TEST_P(GatekeeperAidlTest, DeleteUserTest) {
+    std::vector<uint8_t> password;
+    GatekeeperEnrollResponse enrollRsp;
+    GatekeeperVerifyResponse verifyRsp;
+    ALOGI("Testing deleteUser (expected success)");
+    setUid(10001);
+    generatePassword(password, 0);
+    enrollNewPassword(password, enrollRsp, true);
+    verifyPassword(password, enrollRsp.data, 0, verifyRsp, true);
+    ALOGI("Enroll+Verify done");
+    auto result = doDeleteUser();
+    EXPECT_TRUE(result.isOk() ||
+                (getReturnStatusCode(result) == IGatekeeper::ERROR_NOT_IMPLEMENTED));
+    ALOGI("DeleteUser done");
+    if (result.isOk()) {
+        verifyRsp = {0, 0, {}};
+        verifyPassword(password, enrollRsp.data, 0, verifyRsp, false);
+        ALOGI("Verify after Delete done (must fail)");
+    }
+    ALOGI("Testing deleteUser done: rsp=%" PRIi32, getReturnStatusCode(result));
+}
+
+/**
+ * Ensure we can not delete a user that does not exist
+ */
+TEST_P(GatekeeperAidlTest, DeleteInvalidUserTest) {
+    std::vector<uint8_t> password;
+    GatekeeperEnrollResponse enrollRsp;
+    GatekeeperVerifyResponse verifyRsp;
+    ALOGI("Testing deleteUser (expected failure)");
+    setUid(10002);
+    generatePassword(password, 0);
+    enrollNewPassword(password, enrollRsp, true);
+    verifyPassword(password, enrollRsp.data, 0, verifyRsp, true);
+    ALOGI("Enroll+Verify done");
+
+    // Delete the user
+    Status result1 = doDeleteUser();
+    EXPECT_TRUE(result1.isOk() ||
+                (getReturnStatusCode(result1) == IGatekeeper::ERROR_NOT_IMPLEMENTED));
+
+    // Delete the user again
+    Status result2 = doDeleteUser();
+    int32_t retCode2 = getReturnStatusCode(result2);
+    EXPECT_TRUE((retCode2 == IGatekeeper::ERROR_NOT_IMPLEMENTED) ||
+                (retCode2 == IGatekeeper::ERROR_GENERAL_FAILURE));
+    ALOGI("DeleteUser done");
+    ALOGI("Testing deleteUser done: rsp=%" PRIi32, retCode2);
+}
+
+/**
+ * Ensure we can not verify passwords after we enrolled them and then deleted
+ * all users
+ */
+TEST_P(GatekeeperAidlTest, DeleteAllUsersTest) {
+    struct UserData {
+        uint32_t userId;
+        std::vector<uint8_t> password;
+        GatekeeperEnrollResponse enrollRsp;
+        GatekeeperVerifyResponse verifyRsp;
+        UserData(int id) { userId = id; }
+    } users[3]{10001, 10002, 10003};
+    ALOGI("Testing deleteAllUsers (expected success)");
+
+    // enroll multiple users
+    for (size_t i = 0; i < sizeof(users) / sizeof(users[0]); ++i) {
+        setUid(users[i].userId);
+        generatePassword(users[i].password, (i % 255) + 1);
+        enrollNewPassword(users[i].password, users[i].enrollRsp, true);
+    }
+    ALOGI("Multiple users enrolled");
+
+    // verify multiple users
+    for (size_t i = 0; i < sizeof(users) / sizeof(users[0]); ++i) {
+        setUid(users[i].userId);
+        verifyPassword(users[i].password, users[i].enrollRsp.data, 0, users[i].verifyRsp, true);
+    }
+    ALOGI("Multiple users verified");
+
+    Status result = doDeleteAllUsers();
+    EXPECT_TRUE(result.isOk() ||
+                (getReturnStatusCode(result) == IGatekeeper::ERROR_NOT_IMPLEMENTED));
+    ALOGI("All users deleted");
+
+    if (result.isOk()) {
+        // verify multiple users after they are deleted; all must fail
+        for (size_t i = 0; i < sizeof(users) / sizeof(users[0]); ++i) {
+            setUid(users[i].userId);
+            users[i].verifyRsp = {0, 0, {}};
+            verifyPassword(users[i].password, users[i].enrollRsp.data, 0, users[i].verifyRsp,
+                           false);
+        }
+        ALOGI("Multiple users verified after delete (all must fail)");
+    }
+
+    ALOGI("Testing deleteAllUsers done: rsp=%" PRIi32, getReturnStatusCode(result));
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GatekeeperAidlTest);
+INSTANTIATE_TEST_SUITE_P(
+    PerInstance, GatekeeperAidlTest,
+    testing::ValuesIn(android::getAidlHalInstanceNames(IGatekeeper::descriptor)),
+    android::PrintInstanceNameToString);
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    ABinderProcess_setThreadPoolMaxThreadCount(1);
+    ABinderProcess_startThreadPool();
+    return RUN_ALL_TESTS();
+}
diff --git a/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientWriter.h b/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientWriter.h
index 1d81f7b..775ae9f 100644
--- a/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientWriter.h
+++ b/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientWriter.h
@@ -59,13 +59,13 @@
 
 namespace aidl::android::hardware::graphics::composer3 {
 
-class ComposerClientWriter {
+class ComposerClientWriter final {
   public:
     static constexpr std::optional<ClockMonotonicTimestamp> kNoTimestamp = std::nullopt;
 
     ComposerClientWriter() { reset(); }
 
-    virtual ~ComposerClientWriter() { reset(); }
+    ~ComposerClientWriter() { reset(); }
 
     void reset() {
         mDisplayCommand.reset();
diff --git a/radio/aidl/OWNERS b/radio/aidl/OWNERS
new file mode 100644
index 0000000..7b01aad
--- /dev/null
+++ b/radio/aidl/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 20868
+include ../1.0/vts/OWNERS
+
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EmergencyRegResult.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EmergencyRegResult.aidl
index cb598f3..523d1aa 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EmergencyRegResult.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EmergencyRegResult.aidl
@@ -40,4 +40,6 @@
   boolean isEmcBearerSupported;
   byte nwProvidedEmc;
   byte nwProvidedEmf;
+  String mcc;
+  String mnc;
 }
diff --git a/radio/aidl/android/hardware/radio/network/EmergencyRegResult.aidl b/radio/aidl/android/hardware/radio/network/EmergencyRegResult.aidl
index cf5caa4..c22317a 100644
--- a/radio/aidl/android/hardware/radio/network/EmergencyRegResult.aidl
+++ b/radio/aidl/android/hardware/radio/network/EmergencyRegResult.aidl
@@ -54,4 +54,10 @@
      * This should not be set if UE is not in 5G mode.
      */
     byte nwProvidedEmf;
+
+    /** 3-digit Mobile Country Code, 000..999, empty string if unknown. */
+    String mcc;
+
+    /** 2 or 3-digit Mobile Network Code, 00..999, empty string if unknown. */
+    String mnc;
 }
diff --git a/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl b/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl
index d98a31b..243e949 100644
--- a/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl
+++ b/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl
@@ -580,7 +580,6 @@
      *
      * Valid errors returned:
      *   RadioError:NONE
-     *   RadioError:REQUEST_NOT_SUPPORTED
      *   RadioError:RADIO_NOT_AVAILABLE
      *   RadioError:MODEM_ERR
      *   RadioError:INVALID_ARGUMENTS
@@ -592,7 +591,6 @@
      *
      * Valid errors returned:
      *   RadioError:NONE
-     *   RadioError:REQUEST_NOT_SUPPORTED
      *   RadioError:RADIO_NOT_AVAILABLE
      *   RadioError:MODEM_ERR
      *   RadioError:INVALID_ARGUMENTS
@@ -604,7 +602,6 @@
      *
      * Valid errors returned:
      *   RadioError:NONE
-     *   RadioError:REQUEST_NOT_SUPPORTED
      *   RadioError:RADIO_NOT_AVAILABLE
      *   RadioError:MODEM_ERR
      */
@@ -615,7 +612,6 @@
      *
      * Valid errors returned:
      *   RadioError:NONE
-     *   RadioError:REQUEST_NOT_SUPPORTED
      *   RadioError:RADIO_NOT_AVAILABLE
      *   RadioError:MODEM_ERR
      */
diff --git a/radio/aidl/vts/OWNERS b/radio/aidl/vts/OWNERS
deleted file mode 100644
index e75c6c8..0000000
--- a/radio/aidl/vts/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-# Bug component: 20868
-include ../../1.0/vts/OWNERS
-
diff --git a/radio/aidl/vts/radio_network_test.cpp b/radio/aidl/vts/radio_network_test.cpp
index c83571e..25c42d3 100644
--- a/radio/aidl/vts/radio_network_test.cpp
+++ b/radio/aidl/vts/radio_network_test.cpp
@@ -1833,3 +1833,81 @@
     }
     LOG(DEBUG) << "supplyNetworkDepersonalization finished";
 }
+
+/*
+ * Test IRadioNetwork.setEmergencyMode() for the response returned.
+ */
+TEST_P(RadioNetworkTest, setEmergencyMode) {
+    LOG(DEBUG) << "setEmergencyMode";
+    serial = GetRandomSerialNumber();
+
+    radio_network->setEmergencyMode(serial, EmergencyMode::EMERGENCY_WWAN);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+    ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp_network->rspInfo.error,
+            {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE,
+             RadioError::MODEM_ERR, RadioError::INVALID_ARGUMENTS}));
+    LOG(DEBUG) << "setEmergencyMode finished";
+}
+
+/*
+ * Test IRadioNetwork.triggerEmergencyNetworkScan() for the response returned.
+ */
+TEST_P(RadioNetworkTest, triggerEmergencyNetworkScan) {
+    LOG(DEBUG) << "triggerEmergencyNetworkScan";
+    serial = GetRandomSerialNumber();
+
+    EmergencyNetworkScanTrigger scanRequest;
+    scanRequest.accessNetwork = {AccessNetwork::EUTRAN};
+    scanRequest.scanType = EmergencyScanType::NO_PREFERENCE;
+
+    radio_network->triggerEmergencyNetworkScan(serial, scanRequest);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+    ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp_network->rspInfo.error,
+            {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE,
+             RadioError::MODEM_ERR, RadioError::INVALID_ARGUMENTS}));
+    LOG(DEBUG) << "triggerEmergencyNetworkScan finished";
+}
+
+/*
+ * Test IRadioNetwork.cancelEmergencyNetworkScan() for the response returned.
+ */
+TEST_P(RadioNetworkTest, cancelEmergencyNetworkScan) {
+    LOG(DEBUG) << "cancelEmergencyNetworkScan";
+    serial = GetRandomSerialNumber();
+
+    radio_network->cancelEmergencyNetworkScan(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+    ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp_network->rspInfo.error,
+            {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::MODEM_ERR}));
+    LOG(DEBUG) << "cancelEmergencyNetworkScan finished";
+}
+
+/*
+ * Test IRadioNetwork.exitEmergencyMode() for the response returned.
+ */
+TEST_P(RadioNetworkTest, exitEmergencyMode) {
+    LOG(DEBUG) << "exitEmergencyMode";
+    serial = GetRandomSerialNumber();
+
+    radio_network->exitEmergencyMode(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+    ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp_network->rspInfo.error,
+            {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::MODEM_ERR}));
+    LOG(DEBUG) << "exitEmergencyMode finished";
+}
diff --git a/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp b/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
index 2e282e0..e1f65fe 100644
--- a/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
+++ b/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#include <memory>
+#include <string>
 #define LOG_TAG "VtsRemotelyProvisionableComponentTests"
 
 #include <AndroidRemotelyProvisionedComponentDevice.h>
@@ -58,26 +60,6 @@
 using namespace remote_prov;
 using namespace keymaster;
 
-std::set<std::string> getAllowedVbStates() {
-    return {"green", "yellow", "orange"};
-}
-
-std::set<std::string> getAllowedBootloaderStates() {
-    return {"locked", "unlocked"};
-}
-
-std::set<std::string> getAllowedSecurityLevels() {
-    return {"tee", "strongbox"};
-}
-
-std::set<std::string> getAllowedAttIdStates() {
-    return {"locked", "open"};
-}
-
-std::set<std::string> getAttestationIdEntrySet() {
-    return {"brand", "manufacturer", "product", "model", "device"};
-}
-
 bytevec string_to_bytevec(const char* s) {
     const uint8_t* p = reinterpret_cast<const uint8_t*>(s);
     return bytevec(p, p + strlen(s));
@@ -387,177 +369,6 @@
         }
     }
 
-    ErrMsgOr<bytevec> getSessionKey(ErrMsgOr<std::pair<bytevec, bytevec>>& senderPubkey) {
-        if (rpcHardwareInfo.supportedEekCurve == RpcHardwareInfo::CURVE_25519 ||
-            rpcHardwareInfo.supportedEekCurve == RpcHardwareInfo::CURVE_NONE) {
-            return x25519_HKDF_DeriveKey(testEekChain_.last_pubkey, testEekChain_.last_privkey,
-                                         senderPubkey->first, false /* senderIsA */);
-        } else {
-            return ECDH_HKDF_DeriveKey(testEekChain_.last_pubkey, testEekChain_.last_privkey,
-                                       senderPubkey->first, false /* senderIsA */);
-        }
-    }
-
-    void checkProtectedData(const DeviceInfo& deviceInfo, const cppbor::Array& keysToSign,
-                            const bytevec& keysToSignMac, const ProtectedData& protectedData,
-                            std::vector<BccEntryData>* bccOutput = nullptr) {
-        auto [parsedProtectedData, _, protDataErrMsg] = cppbor::parse(protectedData.protectedData);
-        ASSERT_TRUE(parsedProtectedData) << protDataErrMsg;
-        ASSERT_TRUE(parsedProtectedData->asArray());
-        ASSERT_EQ(parsedProtectedData->asArray()->size(), kCoseEncryptEntryCount);
-
-        auto senderPubkey = getSenderPubKeyFromCoseEncrypt(parsedProtectedData);
-        ASSERT_TRUE(senderPubkey) << senderPubkey.message();
-        EXPECT_EQ(senderPubkey->second, eekId_);
-
-        auto sessionKey = getSessionKey(senderPubkey);
-        ASSERT_TRUE(sessionKey) << sessionKey.message();
-
-        auto protectedDataPayload =
-                decryptCoseEncrypt(*sessionKey, parsedProtectedData.get(), bytevec{} /* aad */);
-        ASSERT_TRUE(protectedDataPayload) << protectedDataPayload.message();
-
-        auto [parsedPayload, __, payloadErrMsg] = cppbor::parse(*protectedDataPayload);
-        ASSERT_TRUE(parsedPayload) << "Failed to parse payload: " << payloadErrMsg;
-        ASSERT_TRUE(parsedPayload->asArray());
-        // Strongbox may contain additional certificate chain.
-        EXPECT_LE(parsedPayload->asArray()->size(), 3U);
-
-        auto& signedMac = parsedPayload->asArray()->get(0);
-        auto& bcc = parsedPayload->asArray()->get(1);
-        ASSERT_TRUE(signedMac && signedMac->asArray());
-        ASSERT_TRUE(bcc && bcc->asArray());
-
-        // BCC is [ pubkey, + BccEntry]
-        auto bccContents = validateBcc(bcc->asArray());
-        ASSERT_TRUE(bccContents) << "\n" << bccContents.message() << "\n" << prettyPrint(bcc.get());
-        ASSERT_GT(bccContents->size(), 0U);
-
-        auto [deviceInfoMap, __2, deviceInfoErrMsg] = cppbor::parse(deviceInfo.deviceInfo);
-        ASSERT_TRUE(deviceInfoMap) << "Failed to parse deviceInfo: " << deviceInfoErrMsg;
-        ASSERT_TRUE(deviceInfoMap->asMap());
-        checkDeviceInfo(*deviceInfoMap->asMap(), deviceInfo.deviceInfo);
-        auto& signingKey = bccContents->back().pubKey;
-        deviceInfoMap->asMap()->canonicalize();
-        auto macKey = verifyAndParseCoseSign1(signedMac->asArray(), signingKey,
-                                              cppbor::Array()  // SignedMacAad
-                                                      .add(challenge_)
-                                                      .add(std::move(deviceInfoMap))
-                                                      .add(keysToSignMac)
-                                                      .encode());
-        ASSERT_TRUE(macKey) << macKey.message();
-
-        auto coseMac0 = cppbor::Array()
-                                .add(cppbor::Map()  // protected
-                                             .add(ALGORITHM, HMAC_256)
-                                             .canonicalize()
-                                             .encode())
-                                .add(cppbor::Map())        // unprotected
-                                .add(keysToSign.encode())  // payload (keysToSign)
-                                .add(keysToSignMac);       // tag
-
-        auto macPayload = verifyAndParseCoseMac0(&coseMac0, *macKey);
-        ASSERT_TRUE(macPayload) << macPayload.message();
-
-        if (bccOutput) {
-            *bccOutput = std::move(*bccContents);
-        }
-    }
-
-    std::optional<std::string> assertAttribute(const cppbor::Map& devInfo,
-                                               cppbor::MajorType majorType, std::string entryName) {
-        const auto& val = devInfo.get(entryName);
-        if (!val) return entryName + " is missing.\n";
-        if (val->type() != majorType) return entryName + " has the wrong type.\n";
-        switch (majorType) {
-            case cppbor::TSTR:
-                if (val->asTstr()->value().size() <= 0) {
-                    return entryName + " is present but the value is empty.\n";
-                }
-                break;
-            case cppbor::BSTR:
-                if (val->asBstr()->value().size() <= 0) {
-                    return entryName + " is present but the value is empty.\n";
-                }
-                break;
-            default:
-                break;
-        }
-        return {};
-    }
-
-    void checkType(const cppbor::Map& devInfo, cppbor::MajorType majorType, std::string entryName) {
-        if (auto error = assertAttribute(devInfo, majorType, entryName)) {
-            FAIL() << *error;
-        }
-    }
-
-    void checkDeviceInfo(const cppbor::Map& deviceInfo, bytevec deviceInfoBytes) {
-        EXPECT_EQ(deviceInfo.clone()->asMap()->canonicalize().encode(), deviceInfoBytes)
-                << "DeviceInfo ordering is non-canonical.";
-        const auto& version = deviceInfo.get("version");
-        ASSERT_TRUE(version);
-        ASSERT_TRUE(version->asUint());
-        RpcHardwareInfo info;
-        provisionable_->getHardwareInfo(&info);
-        ASSERT_EQ(version->asUint()->value(), info.versionNumber);
-        std::set<std::string> allowList;
-        std::string problemEntries;
-        switch (version->asUint()->value()) {
-            // These fields became mandated in version 2.
-            case 2:
-                for (auto attId : getAttestationIdEntrySet()) {
-                    if (auto errMsg = assertAttribute(deviceInfo, cppbor::TSTR, attId)) {
-                        problemEntries += *errMsg;
-                    }
-                }
-                EXPECT_EQ("", problemEntries)
-                        << problemEntries
-                        << "Attestation IDs are missing or malprovisioned. If this test is being "
-                           "run against an early proto or EVT build, this error is probably WAI "
-                           "and indicates that Device IDs were not provisioned in the factory. If "
-                           "this error is returned on a DVT or later build revision, then "
-                           "something is likely wrong with the factory provisioning process.";
-                // TODO: Refactor the KeyMint code that validates these fields and include it here.
-                checkType(deviceInfo, cppbor::TSTR, "vb_state");
-                allowList = getAllowedVbStates();
-                EXPECT_NE(allowList.find(deviceInfo.get("vb_state")->asTstr()->value()),
-                          allowList.end());
-                checkType(deviceInfo, cppbor::TSTR, "bootloader_state");
-                allowList = getAllowedBootloaderStates();
-                EXPECT_NE(allowList.find(deviceInfo.get("bootloader_state")->asTstr()->value()),
-                          allowList.end());
-                checkType(deviceInfo, cppbor::BSTR, "vbmeta_digest");
-                checkType(deviceInfo, cppbor::UINT, "system_patch_level");
-                checkType(deviceInfo, cppbor::UINT, "boot_patch_level");
-                checkType(deviceInfo, cppbor::UINT, "vendor_patch_level");
-                checkType(deviceInfo, cppbor::UINT, "fused");
-                EXPECT_LT(deviceInfo.get("fused")->asUint()->value(), 2);  // Must be 0 or 1.
-                checkType(deviceInfo, cppbor::TSTR, "security_level");
-                allowList = getAllowedSecurityLevels();
-                EXPECT_NE(allowList.find(deviceInfo.get("security_level")->asTstr()->value()),
-                          allowList.end());
-                if (deviceInfo.get("security_level")->asTstr()->value() == "tee") {
-                    checkType(deviceInfo, cppbor::TSTR, "os_version");
-                }
-                break;
-            case 1:
-                checkType(deviceInfo, cppbor::TSTR, "security_level");
-                allowList = getAllowedSecurityLevels();
-                EXPECT_NE(allowList.find(deviceInfo.get("security_level")->asTstr()->value()),
-                          allowList.end());
-                if (version->asUint()->value() == 1) {
-                    checkType(deviceInfo, cppbor::TSTR, "att_id_state");
-                    allowList = getAllowedAttIdStates();
-                    EXPECT_NE(allowList.find(deviceInfo.get("att_id_state")->asTstr()->value()),
-                              allowList.end());
-                }
-                break;
-            default:
-                FAIL() << "Unrecognized version: " << version->asUint()->value();
-        }
-    }
-
     bytevec eekId_;
     size_t testEekLength_;
     EekChain testEekChain_;
@@ -584,7 +395,10 @@
                 &protectedData, &keysToSignMac);
         ASSERT_TRUE(status.isOk()) << status.getMessage();
 
-        checkProtectedData(deviceInfo, cppbor::Array(), keysToSignMac, protectedData);
+        auto result = verifyProductionProtectedData(
+                deviceInfo, cppbor::Array(), keysToSignMac, protectedData, testEekChain_, eekId_,
+                rpcHardwareInfo.supportedEekCurve, provisionable_.get(), challenge_);
+        ASSERT_TRUE(result) << result.message();
     }
 }
 
@@ -606,22 +420,24 @@
             &protectedData, &keysToSignMac);
     ASSERT_TRUE(status.isOk()) << status.getMessage();
 
-    std::vector<BccEntryData> firstBcc;
-    checkProtectedData(deviceInfo, /*keysToSign=*/cppbor::Array(), keysToSignMac, protectedData,
-                       &firstBcc);
+    auto firstBcc = verifyProductionProtectedData(
+            deviceInfo, /*keysToSign=*/cppbor::Array(), keysToSignMac, protectedData, testEekChain_,
+            eekId_, rpcHardwareInfo.supportedEekCurve, provisionable_.get(), challenge_);
+    ASSERT_TRUE(firstBcc) << firstBcc.message();
 
     status = provisionable_->generateCertificateRequest(
             testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo,
             &protectedData, &keysToSignMac);
     ASSERT_TRUE(status.isOk()) << status.getMessage();
 
-    std::vector<BccEntryData> secondBcc;
-    checkProtectedData(deviceInfo, /*keysToSign=*/cppbor::Array(), keysToSignMac, protectedData,
-                       &secondBcc);
+    auto secondBcc = verifyProductionProtectedData(
+            deviceInfo, /*keysToSign=*/cppbor::Array(), keysToSignMac, protectedData, testEekChain_,
+            eekId_, rpcHardwareInfo.supportedEekCurve, provisionable_.get(), challenge_);
+    ASSERT_TRUE(secondBcc) << secondBcc.message();
 
     // Verify that none of the keys in the first BCC are repeated in the second one.
-    for (const auto& i : firstBcc) {
-        for (auto& j : secondBcc) {
+    for (const auto& i : *firstBcc) {
+        for (auto& j : *secondBcc) {
             ASSERT_THAT(i.pubKey, testing::Not(testing::ElementsAreArray(j.pubKey)))
                     << "Found a repeated pubkey in two generateCertificateRequest test mode calls";
         }
@@ -664,7 +480,10 @@
                 &keysToSignMac);
         ASSERT_TRUE(status.isOk()) << status.getMessage();
 
-        checkProtectedData(deviceInfo, cborKeysToSign_, keysToSignMac, protectedData);
+        auto result = verifyProductionProtectedData(
+                deviceInfo, cborKeysToSign_, keysToSignMac, protectedData, testEekChain_, eekId_,
+                rpcHardwareInfo.supportedEekCurve, provisionable_.get(), challenge_);
+        ASSERT_TRUE(result) << result.message();
     }
 }
 
diff --git a/security/keymint/support/Android.bp b/security/keymint/support/Android.bp
index bf2ab02..3f48320 100644
--- a/security/keymint/support/Android.bp
+++ b/security/keymint/support/Android.bp
@@ -65,6 +65,7 @@
     ],
     shared_libs: [
         "libbase",
+        "libbinder_ndk",
         "libcppbor_external",
         "libcppcose_rkp",
         "libcrypto",
diff --git a/security/keymint/support/include/remote_prov/remote_prov_utils.h b/security/keymint/support/include/remote_prov/remote_prov_utils.h
index f3b8608..9ea20ac 100644
--- a/security/keymint/support/include/remote_prov/remote_prov_utils.h
+++ b/security/keymint/support/include/remote_prov/remote_prov_utils.h
@@ -16,7 +16,9 @@
 
 #pragma once
 
+#include <memory>
 #include <vector>
+#include "aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.h"
 
 #include <keymaster/cppcose/cppcose.h>
 
@@ -139,4 +141,40 @@
 JsonOutput jsonEncodeCsrWithBuild(const std::string instance_name,
                                   const cppbor::Array& csr);
 
+/**
+ * Parses a DeviceInfo structure from the given CBOR data. The parsed data is then validated to
+ * ensure it contains the minimum required data at the time of manufacturing. This is only a
+ * partial validation, as some fields may not be provisioned yet at the time this information
+ * is parsed in the manufacturing process.
+ */
+ErrMsgOr<std::unique_ptr<cppbor::Map>> parseAndValidateFactoryDeviceInfo(
+        const std::vector<uint8_t>& deviceInfoBytes, IRemotelyProvisionedComponent* provisionable);
+
+/**
+ * Parses a DeviceInfo structure from the given CBOR data. The parsed data is then validated to
+ * ensure it is formatted correctly and that it contains the required values for Remote Key
+ * Provisioning. This is a full validation, and assumes the device is provisioned as if it is
+ * suitable for the end user.
+ */
+ErrMsgOr<std::unique_ptr<cppbor::Map>> parseAndValidateProductionDeviceInfo(
+        const std::vector<uint8_t>& deviceInfoBytes, IRemotelyProvisionedComponent* provisionable);
+
+/**
+ * Verify the protected data as if the device is still early in the factory process and may not
+ * have all device identifiers provisioned yet.
+ */
+ErrMsgOr<std::vector<BccEntryData>> verifyFactoryProtectedData(
+        const DeviceInfo& deviceInfo, const cppbor::Array& keysToSign,
+        const std::vector<uint8_t>& keysToSignMac, const ProtectedData& protectedData,
+        const EekChain& eekChain, const std::vector<uint8_t>& eekId, int32_t supportedEekCurve,
+        IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge);
+/**
+ * Verify the protected data as if the device is a final production sample.
+ */
+ErrMsgOr<std::vector<BccEntryData>> verifyProductionProtectedData(
+        const DeviceInfo& deviceInfo, const cppbor::Array& keysToSign,
+        const std::vector<uint8_t>& keysToSignMac, const ProtectedData& protectedData,
+        const EekChain& eekChain, const std::vector<uint8_t>& eekId, int32_t supportedEekCurve,
+        IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge);
+
 }  // namespace aidl::android::hardware::security::keymint::remote_prov
diff --git a/security/keymint/support/remote_prov_utils.cpp b/security/keymint/support/remote_prov_utils.cpp
index 0dbea5b..0651496 100644
--- a/security/keymint/support/remote_prov_utils.cpp
+++ b/security/keymint/support/remote_prov_utils.cpp
@@ -15,7 +15,11 @@
  */
 
 #include <iterator>
+#include <memory>
+#include <set>
+#include <string>
 #include <tuple>
+#include "aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.h"
 
 #include <aidl/android/hardware/security/keymint/RpcHardwareInfo.h>
 #include <android-base/properties.h>
@@ -441,4 +445,293 @@
     return JsonOutput::Ok(Json::writeString(factory, json));
 }
 
-}  // namespace aidl::android::hardware::security::keymint::remote_prov
+std::string checkMapEntry(bool isFactory, const cppbor::Map& devInfo, cppbor::MajorType majorType,
+                          const std::string& entryName) {
+    const std::unique_ptr<cppbor::Item>& val = devInfo.get(entryName);
+    if (!val) {
+        return entryName + " is missing.\n";
+    }
+    if (val->type() != majorType) {
+        return entryName + " has the wrong type.\n";
+    }
+    if (isFactory) {
+        return "";
+    }
+    switch (majorType) {
+        case cppbor::TSTR:
+            if (val->asTstr()->value().size() <= 0) {
+                return entryName + " is present but the value is empty.\n";
+            }
+            break;
+        case cppbor::BSTR:
+            if (val->asBstr()->value().size() <= 0) {
+                return entryName + " is present but the value is empty.\n";
+            }
+            break;
+        default:
+            break;
+    }
+    return "";
+}
+
+std::string checkMapEntry(bool isFactory, const cppbor::Map& devInfo, cppbor::MajorType majorType,
+                          const std::string& entryName, const cppbor::Array& allowList) {
+    std::string error = checkMapEntry(isFactory, devInfo, majorType, entryName);
+    if (!error.empty()) {
+        return error;
+    }
+
+    if (isFactory) {
+        return "";
+    }
+
+    const std::unique_ptr<cppbor::Item>& val = devInfo.get(entryName);
+    for (auto i = allowList.begin(); i != allowList.end(); ++i) {
+        if (**i == *val) {
+            return "";
+        }
+    }
+    return entryName + " has an invalid value.\n";
+}
+
+ErrMsgOr<std::unique_ptr<cppbor::Map>> parseAndValidateDeviceInfo(
+        const std::vector<uint8_t>& deviceInfoBytes, IRemotelyProvisionedComponent* provisionable,
+        bool isFactory) {
+    const cppbor::Array kValidVbStates = {"green", "yellow", "orange"};
+    const cppbor::Array kValidBootloaderStates = {"locked", "unlocked"};
+    const cppbor::Array kValidSecurityLevels = {"tee", "strongbox"};
+    const cppbor::Array kValidAttIdStates = {"locked", "open"};
+    const cppbor::Array kValidFused = {0, 1};
+
+    struct AttestationIdEntry {
+        const char* id;
+        bool alwaysValidate;
+    };
+    constexpr AttestationIdEntry kAttestationIdEntrySet[] = {{"brand", false},
+                                                             {"manufacturer", true},
+                                                             {"product", false},
+                                                             {"model", false},
+                                                             {"device", false}};
+
+    auto [parsedVerifiedDeviceInfo, ignore1, errMsg] = cppbor::parse(deviceInfoBytes);
+    if (!parsedVerifiedDeviceInfo) {
+        return errMsg;
+    }
+
+    std::unique_ptr<cppbor::Map> parsed(parsedVerifiedDeviceInfo->asMap());
+    if (!parsed) {
+        return "DeviceInfo must be a CBOR map.";
+    }
+    parsedVerifiedDeviceInfo.release();
+
+    if (parsed->clone()->asMap()->canonicalize().encode() != deviceInfoBytes) {
+        return "DeviceInfo ordering is non-canonical.";
+    }
+    const std::unique_ptr<cppbor::Item>& version = parsed->get("version");
+    if (!version) {
+        return "Device info is missing version";
+    }
+    if (!version->asUint()) {
+        return "version must be an unsigned integer";
+    }
+    RpcHardwareInfo info;
+    provisionable->getHardwareInfo(&info);
+    if (version->asUint()->value() != info.versionNumber) {
+        return "DeviceInfo version (" + std::to_string(version->asUint()->value()) +
+               ") does not match the remotely provisioned component version (" +
+               std::to_string(info.versionNumber) + ").";
+    }
+    std::string error;
+    switch (version->asUint()->value()) {
+        case 2:
+            for (const auto& entry : kAttestationIdEntrySet) {
+                error += checkMapEntry(isFactory && !entry.alwaysValidate, *parsed, cppbor::TSTR,
+                                       entry.id);
+            }
+            if (!error.empty()) {
+                return error +
+                       "Attestation IDs are missing or malprovisioned. If this test is being\n"
+                       "run against an early proto or EVT build, this error is probably WAI\n"
+                       "and indicates that Device IDs were not provisioned in the factory. If\n"
+                       "this error is returned on a DVT or later build revision, then\n"
+                       "something is likely wrong with the factory provisioning process.";
+            }
+            // TODO: Refactor the KeyMint code that validates these fields and include it here.
+            error += checkMapEntry(isFactory, *parsed, cppbor::TSTR, "vb_state", kValidVbStates);
+            error += checkMapEntry(isFactory, *parsed, cppbor::TSTR, "bootloader_state",
+                                   kValidBootloaderStates);
+            error += checkMapEntry(isFactory, *parsed, cppbor::BSTR, "vbmeta_digest");
+            error += checkMapEntry(isFactory, *parsed, cppbor::UINT, "system_patch_level");
+            error += checkMapEntry(isFactory, *parsed, cppbor::UINT, "boot_patch_level");
+            error += checkMapEntry(isFactory, *parsed, cppbor::UINT, "vendor_patch_level");
+            error += checkMapEntry(isFactory, *parsed, cppbor::UINT, "fused", kValidFused);
+            error += checkMapEntry(isFactory, *parsed, cppbor::TSTR, "security_level",
+                                   kValidSecurityLevels);
+            if (parsed->get("security_level") && parsed->get("security_level")->asTstr() &&
+                parsed->get("security_level")->asTstr()->value() == "tee") {
+                error += checkMapEntry(isFactory, *parsed, cppbor::TSTR, "os_version");
+            }
+            break;
+        case 1:
+            error += checkMapEntry(isFactory, *parsed, cppbor::TSTR, "security_level",
+                                   kValidSecurityLevels);
+            error += checkMapEntry(isFactory, *parsed, cppbor::TSTR, "att_id_state",
+                                   kValidAttIdStates);
+            break;
+        default:
+            return "Unrecognized version: " + std::to_string(version->asUint()->value());
+    }
+
+    if (!error.empty()) {
+        return error;
+    }
+
+    return std::move(parsed);
+}
+
+ErrMsgOr<std::unique_ptr<cppbor::Map>> parseAndValidateFactoryDeviceInfo(
+        const std::vector<uint8_t>& deviceInfoBytes, IRemotelyProvisionedComponent* provisionable) {
+    return parseAndValidateDeviceInfo(deviceInfoBytes, provisionable, /*isFactory=*/true);
+}
+
+ErrMsgOr<std::unique_ptr<cppbor::Map>> parseAndValidateProductionDeviceInfo(
+        const std::vector<uint8_t>& deviceInfoBytes, IRemotelyProvisionedComponent* provisionable) {
+    return parseAndValidateDeviceInfo(deviceInfoBytes, provisionable, /*isFactory=*/false);
+}
+
+ErrMsgOr<bytevec> getSessionKey(ErrMsgOr<std::pair<bytevec, bytevec>>& senderPubkey,
+                                const EekChain& eekChain, int32_t supportedEekCurve) {
+    if (supportedEekCurve == RpcHardwareInfo::CURVE_25519 ||
+        supportedEekCurve == RpcHardwareInfo::CURVE_NONE) {
+        return x25519_HKDF_DeriveKey(eekChain.last_pubkey, eekChain.last_privkey,
+                                     senderPubkey->first, false /* senderIsA */);
+    } else {
+        return ECDH_HKDF_DeriveKey(eekChain.last_pubkey, eekChain.last_privkey, senderPubkey->first,
+                                   false /* senderIsA */);
+    }
+}
+
+ErrMsgOr<std::vector<BccEntryData>> verifyProtectedData(
+        const DeviceInfo& deviceInfo, const cppbor::Array& keysToSign,
+        const std::vector<uint8_t>& keysToSignMac, const ProtectedData& protectedData,
+        const EekChain& eekChain, const std::vector<uint8_t>& eekId, int32_t supportedEekCurve,
+        IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge,
+        bool isFactory) {
+    auto [parsedProtectedData, _, protDataErrMsg] = cppbor::parse(protectedData.protectedData);
+    if (!parsedProtectedData) {
+        return protDataErrMsg;
+    }
+    if (!parsedProtectedData->asArray()) {
+        return "Protected data is not a CBOR array.";
+    }
+    if (parsedProtectedData->asArray()->size() != kCoseEncryptEntryCount) {
+        return "The protected data COSE_encrypt structure must have " +
+               std::to_string(kCoseEncryptEntryCount) + " entries, but it only has " +
+               std::to_string(parsedProtectedData->asArray()->size());
+    }
+
+    auto senderPubkey = getSenderPubKeyFromCoseEncrypt(parsedProtectedData);
+    if (!senderPubkey) {
+        return senderPubkey.message();
+    }
+    if (senderPubkey->second != eekId) {
+        return "The COSE_encrypt recipient does not match the expected EEK identifier";
+    }
+
+    auto sessionKey = getSessionKey(senderPubkey, eekChain, supportedEekCurve);
+    if (!sessionKey) {
+        return sessionKey.message();
+    }
+
+    auto protectedDataPayload =
+            decryptCoseEncrypt(*sessionKey, parsedProtectedData.get(), bytevec{} /* aad */);
+    if (!protectedDataPayload) {
+        return protectedDataPayload.message();
+    }
+
+    auto [parsedPayload, __, payloadErrMsg] = cppbor::parse(*protectedDataPayload);
+    if (!parsedPayload) {
+        return "Failed to parse payload: " + payloadErrMsg;
+    }
+    if (!parsedPayload->asArray()) {
+        return "The protected data payload must be an Array.";
+    }
+    if (parsedPayload->asArray()->size() != 3U && parsedPayload->asArray()->size() != 2U) {
+        return "The protected data payload must contain SignedMAC and BCC. It may optionally "
+               "contain AdditionalDKSignatures. However, the parsed payload has " +
+               std::to_string(parsedPayload->asArray()->size()) + " entries.";
+    }
+
+    auto& signedMac = parsedPayload->asArray()->get(0);
+    auto& bcc = parsedPayload->asArray()->get(1);
+    if (!signedMac->asArray()) {
+        return "The SignedMAC in the protected data payload is not an Array.";
+    }
+    if (!bcc->asArray()) {
+        return "The BCC in the protected data payload is not an Array.";
+    }
+
+    // BCC is [ pubkey, + BccEntry]
+    auto bccContents = validateBcc(bcc->asArray());
+    if (!bccContents) {
+        return bccContents.message() + "\n" + prettyPrint(bcc.get());
+    }
+    if (bccContents->size() == 0U) {
+        return "The BCC is empty. It must contain at least one entry.";
+    }
+
+    auto deviceInfoResult =
+            parseAndValidateDeviceInfo(deviceInfo.deviceInfo, provisionable, isFactory);
+    if (!deviceInfoResult) {
+        return deviceInfoResult.message();
+    }
+    std::unique_ptr<cppbor::Map> deviceInfoMap = deviceInfoResult.moveValue();
+    auto& signingKey = bccContents->back().pubKey;
+    auto macKey = verifyAndParseCoseSign1(signedMac->asArray(), signingKey,
+                                          cppbor::Array()  // SignedMacAad
+                                                  .add(challenge)
+                                                  .add(std::move(deviceInfoMap))
+                                                  .add(keysToSignMac)
+                                                  .encode());
+    if (!macKey) {
+        return macKey.message();
+    }
+
+    auto coseMac0 = cppbor::Array()
+                            .add(cppbor::Map()  // protected
+                                         .add(ALGORITHM, HMAC_256)
+                                         .canonicalize()
+                                         .encode())
+                            .add(cppbor::Map())        // unprotected
+                            .add(keysToSign.encode())  // payload (keysToSign)
+                            .add(keysToSignMac);       // tag
+
+    auto macPayload = verifyAndParseCoseMac0(&coseMac0, *macKey);
+    if (!macPayload) {
+        return macPayload.message();
+    }
+
+    return *bccContents;
+}
+
+ErrMsgOr<std::vector<BccEntryData>> verifyFactoryProtectedData(
+        const DeviceInfo& deviceInfo, const cppbor::Array& keysToSign,
+        const std::vector<uint8_t>& keysToSignMac, const ProtectedData& protectedData,
+        const EekChain& eekChain, const std::vector<uint8_t>& eekId, int32_t supportedEekCurve,
+        IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge) {
+    return verifyProtectedData(deviceInfo, keysToSign, keysToSignMac, protectedData, eekChain,
+                               eekId, supportedEekCurve, provisionable, challenge,
+                               /*isFactory=*/true);
+}
+
+ErrMsgOr<std::vector<BccEntryData>> verifyProductionProtectedData(
+        const DeviceInfo& deviceInfo, const cppbor::Array& keysToSign,
+        const std::vector<uint8_t>& keysToSignMac, const ProtectedData& protectedData,
+        const EekChain& eekChain, const std::vector<uint8_t>& eekId, int32_t supportedEekCurve,
+        IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge) {
+    return verifyProtectedData(deviceInfo, keysToSign, keysToSignMac, protectedData, eekChain,
+                               eekId, supportedEekCurve, provisionable, challenge,
+                               /*isFactory=*/false);
+}
+
+}  // namespace aidl::android::hardware::security::keymint::remote_prov
\ No newline at end of file