Merge changes Ic51d603d,Ia50def0d,I22f65b8b,I8ce9f230,Id8455eb1, ... into main

* changes:
  audio: Query minimum buffer size before opening streams
  audio: Implement getters for hardware mixer controls
  audio: Clean up and fix the bluetooth HAL module
  audio: Provide a way for Module to specify nominal latency
  audio: Fix default remote submix HAL implementation and VTS
  CSD: Add default AIDL HAL implementation
diff --git a/audio/aidl/default/Android.bp b/audio/aidl/default/Android.bp
index 9aa86b5..3a8a781 100644
--- a/audio/aidl/default/Android.bp
+++ b/audio/aidl/default/Android.bp
@@ -40,29 +40,6 @@
 }
 
 cc_library {
-    name: "libaudioservicesounddoseimpl",
-    vendor: true,
-    defaults: [
-        "latest_android_media_audio_common_types_ndk_shared",
-        "latest_android_hardware_audio_core_sounddose_ndk_shared",
-        "latest_android_hardware_audio_sounddose_ndk_shared",
-    ],
-    export_include_dirs: ["include"],
-    srcs: [
-        "SoundDose.cpp",
-    ],
-    shared_libs: [
-        "libbase",
-        "libbinder_ndk",
-        "libcutils",
-        "libutils",
-    ],
-    visibility: [
-        "//hardware/interfaces/audio/aidl/sounddose/default",
-    ],
-}
-
-cc_library {
     name: "libaudioserviceexampleimpl",
     defaults: [
         "aidlaudioservice_defaults",
diff --git a/audio/aidl/vts/VtsHalLoudnessEnhancerTargetTest.cpp b/audio/aidl/vts/VtsHalLoudnessEnhancerTargetTest.cpp
index c5e2346..925f9ec 100644
--- a/audio/aidl/vts/VtsHalLoudnessEnhancerTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalLoudnessEnhancerTargetTest.cpp
@@ -32,27 +32,19 @@
 using aidl::android::hardware::audio::effect::Parameter;
 using android::hardware::audio::common::testing::detail::TestExecutionTracer;
 
-/**
- * Here we focus on specific parameter checking, general IEffect interfaces testing performed in
- * VtsAudioEffectTargetTest.
- */
-enum ParamName { PARAM_INSTANCE_NAME, PARAM_GAIN_MB };
-using LoudnessEnhancerParamTestParam =
-        std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int>;
+static constexpr float kMaxAudioSample = 1;
+static constexpr int kZeroGain = 0;
+static constexpr int kMaxGain = std::numeric_limits<int>::max();
+static constexpr int kMinGain = std::numeric_limits<int>::min();
+static constexpr float kAbsError = 0.0001;
 
 // Every int 32 bit value is a valid gain, so testing the corner cases and one regular value.
 // TODO : Update the test values once range/capability is updated by implementation.
-const std::vector<int> kGainMbValues = {std::numeric_limits<int>::min(), 100,
-                                        std::numeric_limits<int>::max()};
+static const std::vector<int> kGainMbValues = {kMinGain, -100, -50, kZeroGain, 50, 100, kMaxGain};
 
-class LoudnessEnhancerParamTest : public ::testing::TestWithParam<LoudnessEnhancerParamTestParam>,
-                                  public EffectHelper {
+class LoudnessEnhancerEffectHelper : public EffectHelper {
   public:
-    LoudnessEnhancerParamTest() : mParamGainMb(std::get<PARAM_GAIN_MB>(GetParam())) {
-        std::tie(mFactory, mDescriptor) = std::get<PARAM_INSTANCE_NAME>(GetParam());
-    }
-
-    void SetUp() override {
+    void SetUpLoudnessEnhancer() {
         ASSERT_NE(nullptr, mFactory);
         ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
 
@@ -60,13 +52,14 @@
         Parameter::Common common = EffectHelper::createParamCommon(
                 0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */,
                 kInputFrameCount /* iFrameCount */, kOutputFrameCount /* oFrameCount */);
-        IEffect::OpenEffectReturn ret;
-        ASSERT_NO_FATAL_FAILURE(open(mEffect, common, specific, &ret, EX_NONE));
+        ASSERT_NO_FATAL_FAILURE(open(mEffect, common, specific, &mOpenEffectReturn, EX_NONE));
         ASSERT_NE(nullptr, mEffect);
     }
-    void TearDown() override {
+
+    void TearDownLoudnessEnhancer() {
         ASSERT_NO_FATAL_FAILURE(close(mEffect));
         ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
+        mOpenEffectReturn = IEffect::OpenEffectReturn{};
     }
 
     Parameter::Specific getDefaultParamSpecific() {
@@ -76,52 +69,230 @@
         return specific;
     }
 
-    static const long kInputFrameCount = 0x100, kOutputFrameCount = 0x100;
-    std::shared_ptr<IFactory> mFactory;
-    std::shared_ptr<IEffect> mEffect;
-    Descriptor mDescriptor;
-    int mParamGainMb = 0;
+    Parameter createLoudnessParam(int gainMb) {
+        LoudnessEnhancer le;
+        le.set<LoudnessEnhancer::gainMb>(gainMb);
+        Parameter param;
+        Parameter::Specific specific;
+        specific.set<Parameter::Specific::loudnessEnhancer>(le);
+        param.set<Parameter::specific>(specific);
+        return param;
+    }
 
-    void SetAndGetParameters() {
-        for (auto& it : mTags) {
-            auto& tag = it.first;
-            auto& le = it.second;
-
-            // set parameter
-            Parameter expectParam;
-            Parameter::Specific specific;
-            specific.set<Parameter::Specific::loudnessEnhancer>(le);
-            expectParam.set<Parameter::specific>(specific);
-            // All values are valid, set parameter should succeed
-            EXPECT_STATUS(EX_NONE, mEffect->setParameter(expectParam)) << expectParam.toString();
-
-            // get parameter
-            Parameter getParam;
-            Parameter::Id id;
-            LoudnessEnhancer::Id leId;
-            leId.set<LoudnessEnhancer::Id::commonTag>(tag);
-            id.set<Parameter::Id::loudnessEnhancerTag>(leId);
-            EXPECT_STATUS(EX_NONE, mEffect->getParameter(id, &getParam));
-
-            EXPECT_EQ(expectParam, getParam) << "\nexpect:" << expectParam.toString()
-                                             << "\ngetParam:" << getParam.toString();
+    binder_exception_t isGainValid(int gainMb) {
+        LoudnessEnhancer le;
+        le.set<LoudnessEnhancer::gainMb>(gainMb);
+        if (isParameterValid<LoudnessEnhancer, Range::loudnessEnhancer>(le, mDescriptor)) {
+            return EX_NONE;
+        } else {
+            return EX_ILLEGAL_ARGUMENT;
         }
     }
 
-    void addGainMbParam(int gainMb) {
-        LoudnessEnhancer le;
-        le.set<LoudnessEnhancer::gainMb>(gainMb);
-        mTags.push_back({LoudnessEnhancer::gainMb, le});
+    void setParameters(int gain, binder_exception_t expected) {
+        // set parameter
+        auto param = createLoudnessParam(gain);
+        EXPECT_STATUS(expected, mEffect->setParameter(param)) << param.toString();
     }
 
-  private:
-    std::vector<std::pair<LoudnessEnhancer::Tag, LoudnessEnhancer>> mTags;
-    void CleanUp() { mTags.clear(); }
+    void validateParameters(int gain) {
+        // get parameter
+        LoudnessEnhancer::Id leId;
+        Parameter getParam;
+        Parameter::Id id;
+
+        LoudnessEnhancer::Tag tag(LoudnessEnhancer::gainMb);
+        leId.set<LoudnessEnhancer::Id::commonTag>(tag);
+        id.set<Parameter::Id::loudnessEnhancerTag>(leId);
+        EXPECT_STATUS(EX_NONE, mEffect->getParameter(id, &getParam));
+        auto expectedParam = createLoudnessParam(gain);
+        EXPECT_EQ(expectedParam, getParam) << "\nexpectedParam:" << expectedParam.toString()
+                                           << "\ngetParam:" << getParam.toString();
+    }
+
+    static const long kInputFrameCount = 0x100, kOutputFrameCount = 0x100;
+    IEffect::OpenEffectReturn mOpenEffectReturn;
+    std::shared_ptr<IFactory> mFactory;
+    std::shared_ptr<IEffect> mEffect;
+    Descriptor mDescriptor;
+};
+
+/**
+ * Here we focus on specific parameter checking, general IEffect interfaces testing performed in
+ * VtsAudioEffectTargetTest.
+ */
+enum ParamName { PARAM_INSTANCE_NAME, PARAM_GAIN_MB };
+using LoudnessEnhancerParamTestParam =
+        std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int>;
+
+class LoudnessEnhancerParamTest : public ::testing::TestWithParam<LoudnessEnhancerParamTestParam>,
+                                  public LoudnessEnhancerEffectHelper {
+  public:
+    LoudnessEnhancerParamTest() : mParamGainMb(std::get<PARAM_GAIN_MB>(GetParam())) {
+        std::tie(mFactory, mDescriptor) = std::get<PARAM_INSTANCE_NAME>(GetParam());
+    }
+
+    void SetUp() override { SetUpLoudnessEnhancer(); }
+    void TearDown() override { TearDownLoudnessEnhancer(); }
+    int mParamGainMb = 0;
 };
 
 TEST_P(LoudnessEnhancerParamTest, SetAndGetGainMb) {
-    EXPECT_NO_FATAL_FAILURE(addGainMbParam(mParamGainMb));
-    SetAndGetParameters();
+    binder_exception_t expected = isGainValid(mParamGainMb);
+    setParameters(mParamGainMb, expected);
+    if (expected == EX_NONE) {
+        validateParameters(mParamGainMb);
+    }
+}
+
+using LoudnessEnhancerDataTestParam = std::pair<std::shared_ptr<IFactory>, Descriptor>;
+
+class LoudnessEnhancerDataTest : public ::testing::TestWithParam<LoudnessEnhancerDataTestParam>,
+                                 public LoudnessEnhancerEffectHelper {
+  public:
+    LoudnessEnhancerDataTest() {
+        std::tie(mFactory, mDescriptor) = GetParam();
+        generateInputBuffer();
+        mOutputBuffer.resize(kBufferSize);
+    }
+
+    void SetUp() override {
+        SetUpLoudnessEnhancer();
+
+        // Creating AidlMessageQueues
+        mStatusMQ = std::make_unique<EffectHelper::StatusMQ>(mOpenEffectReturn.statusMQ);
+        mInputMQ = std::make_unique<EffectHelper::DataMQ>(mOpenEffectReturn.inputDataMQ);
+        mOutputMQ = std::make_unique<EffectHelper::DataMQ>(mOpenEffectReturn.outputDataMQ);
+    }
+
+    void TearDown() override { TearDownLoudnessEnhancer(); }
+
+    // Fill inputBuffer with random values between -kMaxAudioSample to kMaxAudioSample
+    void generateInputBuffer() {
+        for (size_t i = 0; i < kBufferSize; i++) {
+            mInputBuffer.push_back(((static_cast<float>(std::rand()) / RAND_MAX) * 2 - 1) *
+                                   kMaxAudioSample);
+        }
+    }
+
+    // Add gains to the mInputBuffer and store processed output to mOutputBuffer
+    void processAndWriteToOutput() {
+        // Check AidlMessageQueues are not null
+        ASSERT_TRUE(mStatusMQ->isValid());
+        ASSERT_TRUE(mInputMQ->isValid());
+        ASSERT_TRUE(mOutputMQ->isValid());
+
+        // Enabling the process
+        ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START));
+        ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::PROCESSING));
+
+        // Write from buffer to message queues and calling process
+        EXPECT_NO_FATAL_FAILURE(EffectHelper::writeToFmq(mStatusMQ, mInputMQ, mInputBuffer));
+
+        // Read the updated message queues into buffer
+        EXPECT_NO_FATAL_FAILURE(EffectHelper::readFromFmq(mStatusMQ, 1, mOutputMQ,
+                                                          mOutputBuffer.size(), mOutputBuffer));
+
+        // Disable the process
+        ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::STOP));
+    }
+
+    void assertGreaterGain(const std::vector<float>& first, const std::vector<float>& second) {
+        for (size_t i = 0; i < first.size(); i++) {
+            if (first[i] != 0) {
+                ASSERT_GT(abs(first[i]), abs(second[i]));
+
+            } else {
+                ASSERT_EQ(first[i], second[i]);
+            }
+        }
+    }
+
+    void assertSequentialGains(const std::vector<int>& gainValues, bool isIncreasing) {
+        std::vector<float> baseOutput(kBufferSize);
+
+        // Process a reference output buffer with 0 gain which gives compressed input values
+        binder_exception_t expected;
+        expected = isGainValid(kZeroGain);
+        ASSERT_EQ(expected, EX_NONE);
+        setParameters(kZeroGain, expected);
+        ASSERT_NO_FATAL_FAILURE(processAndWriteToOutput());
+        baseOutput = mOutputBuffer;
+
+        // Compare the outputs for increasing gain
+        for (int gain : gainValues) {
+            // Setting the parameters
+            binder_exception_t expected = isGainValid(gain);
+            if (expected != EX_NONE) {
+                GTEST_SKIP() << "Gains not supported.";
+            }
+            setParameters(gain, expected);
+            ASSERT_NO_FATAL_FAILURE(processAndWriteToOutput());
+
+            // Compare the mOutputBuffer values with baseOutput and update it
+            if (isIncreasing) {
+                ASSERT_NO_FATAL_FAILURE(assertGreaterGain(mOutputBuffer, baseOutput));
+            } else {
+                ASSERT_NO_FATAL_FAILURE(assertGreaterGain(baseOutput, mOutputBuffer));
+            }
+
+            baseOutput = mOutputBuffer;
+        }
+    }
+
+    std::unique_ptr<StatusMQ> mStatusMQ;
+    std::unique_ptr<DataMQ> mInputMQ;
+    std::unique_ptr<DataMQ> mOutputMQ;
+
+    std::vector<float> mInputBuffer;
+    std::vector<float> mOutputBuffer;
+    static constexpr float kBufferSize = 128;
+};
+
+TEST_P(LoudnessEnhancerDataTest, IncreasingGains) {
+    static const std::vector<int> kIncreasingGains = {50, 100};
+
+    assertSequentialGains(kIncreasingGains, true /*isIncreasing*/);
+}
+
+TEST_P(LoudnessEnhancerDataTest, DecreasingGains) {
+    static const std::vector<int> kDecreasingGains = {-50, -100};
+
+    assertSequentialGains(kDecreasingGains, false /*isIncreasing*/);
+}
+
+TEST_P(LoudnessEnhancerDataTest, MinimumGain) {
+    // Setting the parameters
+    binder_exception_t expected = isGainValid(kMinGain);
+    if (expected != EX_NONE) {
+        GTEST_SKIP() << "Minimum integer value not supported";
+    }
+    setParameters(kMinGain, expected);
+    ASSERT_NO_FATAL_FAILURE(processAndWriteToOutput());
+
+    // Validate that mOutputBuffer has 0 values for INT_MIN gain
+    for (size_t i = 0; i < mOutputBuffer.size(); i++) {
+        ASSERT_FLOAT_EQ(mOutputBuffer[i], 0);
+    }
+}
+
+TEST_P(LoudnessEnhancerDataTest, MaximumGain) {
+    // Setting the parameters
+    binder_exception_t expected = isGainValid(kMaxGain);
+    if (expected != EX_NONE) {
+        GTEST_SKIP() << "Maximum integer value not supported";
+    }
+    setParameters(kMaxGain, expected);
+    ASSERT_NO_FATAL_FAILURE(processAndWriteToOutput());
+
+    // Validate that mOutputBuffer reaches to kMaxAudioSample for INT_MAX gain
+    for (size_t i = 0; i < mOutputBuffer.size(); i++) {
+        if (mInputBuffer[i] != 0) {
+            EXPECT_NEAR(kMaxAudioSample, abs(mOutputBuffer[i]), kAbsError);
+        } else {
+            ASSERT_EQ(mOutputBuffer[i], mInputBuffer[i]);
+        }
+    }
 }
 
 INSTANTIATE_TEST_SUITE_P(
@@ -140,6 +311,20 @@
 
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(LoudnessEnhancerParamTest);
 
+INSTANTIATE_TEST_SUITE_P(
+        LoudnessEnhancerTest, LoudnessEnhancerDataTest,
+        testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
+                IFactory::descriptor, getEffectTypeUuidLoudnessEnhancer())),
+        [](const testing::TestParamInfo<LoudnessEnhancerDataTest::ParamType>& info) {
+            auto descriptor = info.param;
+            std::string name = getPrefix(descriptor.second);
+            std::replace_if(
+                    name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
+            return name;
+        });
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(LoudnessEnhancerDataTest);
+
 int main(int argc, char** argv) {
     ::testing::InitGoogleTest(&argc, argv);
     ::testing::UnitTest::GetInstance()->listeners().Append(new TestExecutionTracer());
diff --git a/camera/device/default/ExternalCameraUtils.cpp b/camera/device/default/ExternalCameraUtils.cpp
index cfb95f2..30c216f 100644
--- a/camera/device/default/ExternalCameraUtils.cpp
+++ b/camera/device/default/ExternalCameraUtils.cpp
@@ -402,7 +402,10 @@
         buffer_handle_t buf,
         /*out*/ buffer_handle_t** outBufPtr) {
     using ::aidl::android::hardware::camera::common::Status;
-    if (buf == nullptr && bufId == BUFFER_ID_NO_BUFFER) {
+    // AIDL does not have null NativeHandles. It sends empty handles instead.
+    // We check for when the buf is empty instead of when buf is null.
+    bool isBufEmpty = buf == nullptr || (buf->numFds == 0 && buf->numInts == 0);
+    if (isBufEmpty && bufId == BUFFER_ID_NO_BUFFER) {
         ALOGE("%s: bufferId %" PRIu64 " has null buffer handle!", __FUNCTION__, bufId);
         return Status::ILLEGAL_ARGUMENT;
     }
@@ -857,4 +860,4 @@
 }  // namespace device
 }  // namespace camera
 }  // namespace hardware
-}  // namespace android
\ No newline at end of file
+}  // namespace android
diff --git a/compatibility_matrices/Android.bp b/compatibility_matrices/Android.bp
index 7844ac8..712f28a 100644
--- a/compatibility_matrices/Android.bp
+++ b/compatibility_matrices/Android.bp
@@ -22,6 +22,19 @@
 }
 
 vintf_compatibility_matrix {
+    name: "framework_compatibility_matrix.4.xml",
+    stem: "compatibility_matrix.4.xml",
+    srcs: [
+        "compatibility_matrix.4.xml",
+    ],
+    kernel_configs: [
+        "kernel_config_q_4.14",
+        "kernel_config_q_4.19",
+    ],
+    core_hals: "only",
+}
+
+vintf_compatibility_matrix {
     name: "framework_compatibility_matrix.5.xml",
     stem: "compatibility_matrix.5.xml",
     srcs: [
diff --git a/compatibility_matrices/Android.mk b/compatibility_matrices/Android.mk
index d145f9e..d356cf3 100644
--- a/compatibility_matrices/Android.mk
+++ b/compatibility_matrices/Android.mk
@@ -101,6 +101,7 @@
 endif # DEVICE_PRODUCT_COMPATIBILITY_MATRIX_FILE
 
 my_system_matrix_deps := \
+    framework_compatibility_matrix.4.xml \
     framework_compatibility_matrix.5.xml \
     framework_compatibility_matrix.6.xml \
     framework_compatibility_matrix.7.xml \
diff --git a/compatibility_matrices/compatibility_matrix.4.xml b/compatibility_matrices/compatibility_matrix.4.xml
new file mode 100644
index 0000000..bb7637a
--- /dev/null
+++ b/compatibility_matrices/compatibility_matrix.4.xml
@@ -0,0 +1,525 @@
+<compatibility-matrix version="1.0" type="framework" level="4">
+    <hal format="hidl" optional="true">
+        <name>android.hardware.atrace</name>
+        <version>1.0</version>
+        <interface>
+            <name>IAtraceDevice</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.audio</name>
+        <version>5.0</version>
+        <interface>
+            <name>IDevicesFactory</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.audio.effect</name>
+        <version>5.0</version>
+        <interface>
+            <name>IEffectsFactory</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.authsecret</name>
+        <version>1.0</version>
+        <interface>
+            <name>IAuthSecret</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.automotive.audiocontrol</name>
+        <version>1.0</version>
+        <interface>
+            <name>IAudioControl</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.automotive.evs</name>
+        <version>1.0</version>
+        <interface>
+            <name>IEvsEnumerator</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.automotive.vehicle</name>
+        <version>2.0</version>
+        <interface>
+            <name>IVehicle</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.biometrics.face</name>
+        <version>1.0</version>
+        <interface>
+            <name>IBiometricsFace</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.biometrics.fingerprint</name>
+        <version>2.1</version>
+        <interface>
+            <name>IBiometricsFingerprint</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.bluetooth</name>
+        <version>1.0</version>
+        <interface>
+            <name>IBluetoothHci</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.bluetooth.audio</name>
+        <version>2.0</version>
+        <interface>
+            <name>IBluetoothAudioProvidersFactory</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.boot</name>
+        <version>1.0</version>
+        <interface>
+            <name>IBootControl</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.broadcastradio</name>
+        <version>1.0-1</version>
+        <interface>
+            <name>IBroadcastRadioFactory</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.broadcastradio</name>
+        <version>2.0</version>
+        <interface>
+            <name>IBroadcastRadio</name>
+            <regex-instance>.*</regex-instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.camera.provider</name>
+        <version>2.4-5</version>
+        <interface>
+            <name>ICameraProvider</name>
+            <regex-instance>[^/]+/[0-9]+</regex-instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.cas</name>
+        <version>1.1</version>
+        <interface>
+            <name>IMediaCasService</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.configstore</name>
+        <version>1.1</version>
+        <interface>
+            <name>ISurfaceFlingerConfigs</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.confirmationui</name>
+        <version>1.0</version>
+        <interface>
+            <name>IConfirmationUI</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.contexthub</name>
+        <version>1.0</version>
+        <interface>
+            <name>IContexthub</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.drm</name>
+        <version>1.0-2</version>
+        <interface>
+            <name>ICryptoFactory</name>
+            <regex-instance>.*</regex-instance>
+        </interface>
+        <interface>
+            <name>IDrmFactory</name>
+            <regex-instance>.*</regex-instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.dumpstate</name>
+        <version>1.0</version>
+        <interface>
+            <name>IDumpstateDevice</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.gatekeeper</name>
+        <version>1.0</version>
+        <interface>
+            <name>IGatekeeper</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.gnss</name>
+        <version>2.0</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" optional="true">
+        <name>android.hardware.graphics.allocator</name>
+        <version>2.0</version>
+        <version>3.0</version>
+        <interface>
+            <name>IAllocator</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.graphics.composer</name>
+        <version>2.1-3</version>
+        <interface>
+            <name>IComposer</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.graphics.mapper</name>
+        <version>2.1</version>
+        <version>3.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.0.
+         See DeviceManifestTest.HealthHal -->
+    <hal format="hidl" optional="true">
+        <name>android.hardware.health</name>
+        <version>2.0</version>
+        <interface>
+            <name>IHealth</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.health.storage</name>
+        <version>1.0</version>
+        <interface>
+            <name>IStorage</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.ir</name>
+        <version>1.0</version>
+        <interface>
+            <name>IConsumerIr</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.input.classifier</name>
+        <version>1.0</version>
+        <interface>
+            <name>IInputClassifier</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.keymaster</name>
+        <version>3.0</version>
+        <version>4.0</version>
+        <interface>
+            <name>IKeymasterDevice</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.keymaster</name>
+        <version>4.0</version>
+        <interface>
+            <name>IKeymasterDevice</name>
+            <instance>strongbox</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.light</name>
+        <version>2.0</version>
+        <interface>
+            <name>ILight</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.media.c2</name>
+        <version>1.0</version>
+        <interface>
+            <name>IComponentStore</name>
+            <instance>software</instance>
+            <regex-instance>default[0-9]*</regex-instance>
+            <regex-instance>vendor[0-9]*_software</regex-instance>
+        </interface>
+        <interface>
+            <name>IConfigurable</name>
+            <instance>default</instance>
+            <instance>software</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <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" optional="true">
+        <name>android.hardware.memtrack</name>
+        <version>1.0</version>
+        <interface>
+            <name>IMemtrack</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.neuralnetworks</name>
+        <version>1.0-2</version>
+        <interface>
+            <name>IDevice</name>
+            <regex-instance>.*</regex-instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.nfc</name>
+        <version>1.2</version>
+        <interface>
+            <name>INfc</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.oemlock</name>
+        <version>1.0</version>
+        <interface>
+            <name>IOemLock</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.power</name>
+        <version>1.0-3</version>
+        <interface>
+            <name>IPower</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.power.stats</name>
+        <version>1.0</version>
+        <interface>
+            <name>IPowerStats</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.radio</name>
+        <version>1.4</version>
+        <interface>
+            <name>IRadio</name>
+            <instance>slot1</instance>
+            <instance>slot2</instance>
+            <instance>slot3</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.radio</name>
+        <version>1.2</version>
+        <interface>
+            <name>ISap</name>
+            <instance>slot1</instance>
+            <instance>slot2</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.radio.config</name>
+        <!--
+        Note: Devices launching with target-level 4, if implementing the
+        radio config HAL, must provide an implementation of 1.1 IRadioConfig
+        that can handle version 1.2 of IRadioConfigResponse and
+        IRadioConfigIndication.
+        -->
+        <version>1.1</version>
+        <interface>
+            <name>IRadioConfig</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.renderscript</name>
+        <version>1.0</version>
+        <interface>
+            <name>IDevice</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.secure_element</name>
+        <version>1.0</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" optional="true">
+        <name>android.hardware.sensors</name>
+        <version>1.0</version>
+        <version>2.0</version>
+        <interface>
+            <name>ISensors</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.soundtrigger</name>
+        <version>2.0-2</version>
+        <interface>
+            <name>ISoundTriggerHw</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.tetheroffload.config</name>
+        <version>1.0</version>
+        <interface>
+            <name>IOffloadConfig</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.tetheroffload.control</name>
+        <version>1.0</version>
+        <interface>
+            <name>IOffloadControl</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.thermal</name>
+        <version>2.0</version>
+        <interface>
+            <name>IThermal</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.tv.cec</name>
+        <version>1.0</version>
+        <interface>
+            <name>IHdmiCec</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.tv.input</name>
+        <version>1.0</version>
+        <interface>
+            <name>ITvInput</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.usb</name>
+        <version>1.0-2</version>
+        <interface>
+            <name>IUsb</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.usb.gadget</name>
+        <version>1.0</version>
+        <interface>
+            <name>IUsbGadget</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.vibrator</name>
+        <version>1.0-3</version>
+        <interface>
+            <name>IVibrator</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.vr</name>
+        <version>1.0</version>
+        <interface>
+            <name>IVr</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.weaver</name>
+        <version>1.0</version>
+        <interface>
+            <name>IWeaver</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.wifi</name>
+        <version>1.0-3</version>
+        <interface>
+            <name>IWifi</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.wifi.hostapd</name>
+        <version>1.0-1</version>
+        <interface>
+            <name>IHostapd</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.wifi.supplicant</name>
+        <version>1.0-2</version>
+        <interface>
+            <name>ISupplicant</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+</compatibility-matrix>
diff --git a/compatibility_matrices/compatibility_matrix.9.xml b/compatibility_matrices/compatibility_matrix.9.xml
index da31888..6ed8e8f 100644
--- a/compatibility_matrices/compatibility_matrix.9.xml
+++ b/compatibility_matrices/compatibility_matrix.9.xml
@@ -509,6 +509,14 @@
         </interface>
     </hal>
     <hal format="aidl" optional="true" updatable-via-apex="true">
+        <name>android.hardware.security.authgraph</name>
+        <version>1</version>
+        <interface>
+            <name>IAuthGraphKeyExchange</name>
+            <instance>nonsecure</instance>
+        </interface>
+    </hal>
+    <hal format="aidl" optional="true" updatable-via-apex="true">
         <name>android.hardware.security.secureclock</name>
         <version>1</version>
         <interface>
diff --git a/compatibility_matrices/exclude/fcm_exclude.cpp b/compatibility_matrices/exclude/fcm_exclude.cpp
index bb4cf78..d92c0b9 100644
--- a/compatibility_matrices/exclude/fcm_exclude.cpp
+++ b/compatibility_matrices/exclude/fcm_exclude.cpp
@@ -84,26 +84,6 @@
             "android.hardware.thermal@1.0",
             "android.hardware.thermal@1.1",
             "android.hardware.wifi.offload@1.0",
-
-            // TODO(b/279809679): File bugs for the HALs deprecated in Q
-            "android.hardware.audio.effect@5.0",
-            "android.hardware.audio@5.0",
-            "android.hardware.boot@1.0",
-            "android.hardware.configstore@1.1",
-            "android.hardware.drm@1.0",
-            "android.hardware.drm@1.1",
-            "android.hardware.drm@1.2",
-            "android.hardware.dumpstate@1.0",
-            "android.hardware.health@2.0",
-            "android.hardware.light@2.0",
-            "android.hardware.power@1.0",
-            "android.hardware.power@1.1",
-            "android.hardware.power@1.2",
-            "android.hardware.power@1.3",
-            "android.hardware.vibrator@1.0",
-            "android.hardware.vibrator@1.1",
-            "android.hardware.vibrator@1.2",
-            "android.hardware.vibrator@1.3",
     };
 
     auto package_has_prefix = [&](const std::string& prefix) {
diff --git a/gatekeeper/aidl/Android.bp b/gatekeeper/aidl/Android.bp
index b050f6a..169a7d5 100644
--- a/gatekeeper/aidl/Android.bp
+++ b/gatekeeper/aidl/Android.bp
@@ -25,6 +25,9 @@
         cpp: {
             enabled: false,
         },
+        rust: {
+            enabled: true,
+        },
     },
     versions_with_info: [
         {
diff --git a/gnss/aidl/default/Android.bp b/gnss/aidl/default/Android.bp
index ca5a41f..7310922 100644
--- a/gnss/aidl/default/Android.bp
+++ b/gnss/aidl/default/Android.bp
@@ -26,12 +26,7 @@
 cc_binary {
     name: "android.hardware.gnss-service.example",
     relative_install_path: "hw",
-    init_rc: [
-        "gnss-default.rc",
-    ],
-    vintf_fragments: [
-        "gnss-default.xml",
-    ],
+    installable: false, // install APEX instead
     vendor: true,
     cflags: [
         "-Wall",
@@ -73,3 +68,35 @@
         "android.hardware.gnss@common-default-lib",
     ],
 }
+
+prebuilt_etc {
+    name: "gnss-default.rc",
+    src: "gnss-default.rc",
+    installable: false,
+}
+
+prebuilt_etc {
+    name: "gnss-default.xml",
+    src: "gnss-default.xml",
+    sub_dir: "vintf",
+    installable: false,
+}
+
+apex {
+    name: "com.android.hardware.gnss",
+    manifest: "apex_manifest.json",
+    file_contexts: "apex_file_contexts",
+    key: "com.android.hardware.key",
+    certificate: ":com.android.hardware.certificate",
+    updatable: false,
+    vendor: true,
+
+    binaries: [
+        "android.hardware.gnss-service.example",
+    ],
+    prebuilts: [
+        "gnss-default.rc",
+        "gnss-default.xml",
+        "android.hardware.location.gps.prebuilt.xml", // permission
+    ],
+}
diff --git a/gnss/aidl/default/apex_file_contexts b/gnss/aidl/default/apex_file_contexts
new file mode 100644
index 0000000..83b01ed
--- /dev/null
+++ b/gnss/aidl/default/apex_file_contexts
@@ -0,0 +1,3 @@
+(/.*)?                                                          u:object_r:vendor_file:s0
+/etc(/.*)?                                                      u:object_r:vendor_configs_file:s0
+/bin/hw/android\.hardware\.gnss-service\.example                u:object_r:hal_gnss_default_exec:s0
diff --git a/gnss/aidl/default/apex_manifest.json b/gnss/aidl/default/apex_manifest.json
new file mode 100644
index 0000000..9b2db23
--- /dev/null
+++ b/gnss/aidl/default/apex_manifest.json
@@ -0,0 +1,4 @@
+{
+    "name": "com.android.hardware.gnss",
+    "version": 1
+}
diff --git a/gnss/aidl/default/gnss-default.rc b/gnss/aidl/default/gnss-default.rc
index fe179c3..d47b3a5 100644
--- a/gnss/aidl/default/gnss-default.rc
+++ b/gnss/aidl/default/gnss-default.rc
@@ -1,4 +1,4 @@
-service vendor.gnss-default /vendor/bin/hw/android.hardware.gnss-service.example
+service vendor.gnss-default /apex/com.android.hardware.gnss/bin/hw/android.hardware.gnss-service.example
     class hal
     user nobody
     group nobody
diff --git a/security/authgraph/aidl/Android.bp b/security/authgraph/aidl/Android.bp
new file mode 100644
index 0000000..d94f640
--- /dev/null
+++ b/security/authgraph/aidl/Android.bp
@@ -0,0 +1,88 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_interfaces_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+aidl_interface {
+    name: "android.hardware.security.authgraph",
+    vendor_available: true,
+    srcs: [
+        "android/hardware/security/authgraph/*.aidl",
+    ],
+    stability: "vintf",
+    frozen: false,
+    backend: {
+        java: {
+            platform_apis: true,
+        },
+        ndk: {
+            apps_enabled: false,
+        },
+        rust: {
+            enabled: true,
+            apex_available: [
+                "//apex_available:platform",
+                "com.android.virt",
+            ],
+        },
+    },
+}
+
+// cc_defaults that includes the latest Authgraph AIDL library.
+// Modules that depend on Authgraph directly can include this cc_defaults to avoid
+// managing dependency versions explicitly.
+cc_defaults {
+    name: "authgraph_use_latest_hal_aidl_ndk_static",
+    static_libs: [
+        "android.hardware.security.authgraph-V1-ndk",
+    ],
+}
+
+cc_defaults {
+    name: "authgraph_use_latest_hal_aidl_ndk_shared",
+    shared_libs: [
+        "android.hardware.security.authgraph-V1-ndk",
+    ],
+}
+
+cc_defaults {
+    name: "authgraph_use_latest_hal_aidl_cpp_static",
+    static_libs: [
+        "android.hardware.security.authgraph-V1-cpp",
+    ],
+}
+
+cc_defaults {
+    name: "authgraph_use_latest_hal_aidl_cpp_shared",
+    shared_libs: [
+        "android.hardware.security.authgraph-V1-cpp",
+    ],
+}
+
+// A rust_defaults that includes the latest Authgraph AIDL library.
+// Modules that depend on Authgraph directly can include this rust_defaults to avoid
+// managing dependency versions explicitly.
+rust_defaults {
+    name: "authgraph_use_latest_hal_aidl_rust",
+    rustlibs: [
+        "android.hardware.security.authgraph-V1-rust",
+    ],
+}
diff --git a/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/Arc.aidl b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/Arc.aidl
new file mode 100644
index 0000000..dc86fbd
--- /dev/null
+++ b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/Arc.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2023 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.security.authgraph;
+/* @hide */
+@RustDerive(Clone=true, Eq=true, PartialEq=true) @VintfStability
+parcelable Arc {
+  byte[] arc;
+}
diff --git a/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/Error.aidl b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/Error.aidl
new file mode 100644
index 0000000..1a78b54
--- /dev/null
+++ b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/Error.aidl
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2023 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.security.authgraph;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum Error {
+  OK = 0,
+  INVALID_PEER_NONCE = (-1) /* -1 */,
+  INVALID_PEER_KE_KEY = (-2) /* -2 */,
+  INVALID_IDENTITY = (-3) /* -3 */,
+  INVALID_CERT_CHAIN = (-4) /* -4 */,
+  INVALID_SIGNATURE = (-5) /* -5 */,
+  INVALID_KE_KEY = (-6) /* -6 */,
+  INVALID_PUB_KEY_IN_KEY = (-7) /* -7 */,
+  INVALID_PRIV_KEY_ARC_IN_KEY = (-8) /* -8 */,
+  INVALID_SHARED_KEY_ARCS = (-9) /* -9 */,
+  MEMORY_ALLOCATION_FAILED = (-10) /* -10 */,
+  INCOMPATIBLE_PROTOCOL_VERSION = (-11) /* -11 */,
+}
diff --git a/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/IAuthGraphKeyExchange.aidl b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/IAuthGraphKeyExchange.aidl
new file mode 100644
index 0000000..2c56f33
--- /dev/null
+++ b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/IAuthGraphKeyExchange.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2023 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.security.authgraph;
+/* @hide */
+@VintfStability
+interface IAuthGraphKeyExchange {
+  android.hardware.security.authgraph.SessionInitiationInfo create();
+  android.hardware.security.authgraph.KeInitResult init(in android.hardware.security.authgraph.PubKey peerPubKey, in android.hardware.security.authgraph.Identity peerId, in byte[] peerNonce, in int peerVersion);
+  android.hardware.security.authgraph.SessionInfo finish(in android.hardware.security.authgraph.PubKey peerPubKey, in android.hardware.security.authgraph.Identity peerId, in android.hardware.security.authgraph.SessionIdSignature peerSignature, in byte[] peerNonce, in int peerVersion, in android.hardware.security.authgraph.Key ownKey);
+  android.hardware.security.authgraph.Arc[2] authenticationComplete(in android.hardware.security.authgraph.SessionIdSignature peerSignature, in android.hardware.security.authgraph.Arc[2] sharedKeys);
+}
diff --git a/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/Identity.aidl b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/Identity.aidl
new file mode 100644
index 0000000..bd5453e
--- /dev/null
+++ b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/Identity.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2023 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.security.authgraph;
+@RustDerive(Clone=true, Eq=true, PartialEq=true) @VintfStability
+parcelable Identity {
+  byte[] identity;
+}
diff --git a/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/KeInitResult.aidl b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/KeInitResult.aidl
new file mode 100644
index 0000000..8c91523
--- /dev/null
+++ b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/KeInitResult.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2023 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.security.authgraph;
+@RustDerive(Clone=true, Eq=true, PartialEq=true) @VintfStability
+parcelable KeInitResult {
+  android.hardware.security.authgraph.SessionInitiationInfo sessionInitiationInfo;
+  android.hardware.security.authgraph.SessionInfo sessionInfo;
+}
diff --git a/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/Key.aidl b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/Key.aidl
new file mode 100644
index 0000000..5b4ebbf
--- /dev/null
+++ b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/Key.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2023 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.security.authgraph;
+@RustDerive(Clone=true, Eq=true, PartialEq=true) @VintfStability
+parcelable Key {
+  @nullable android.hardware.security.authgraph.PubKey pubKey;
+  @nullable android.hardware.security.authgraph.Arc arcFromPBK;
+}
diff --git a/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/PlainPubKey.aidl b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/PlainPubKey.aidl
new file mode 100644
index 0000000..f070bfa
--- /dev/null
+++ b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/PlainPubKey.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2023 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.security.authgraph;
+@RustDerive(Clone=true, Eq=true, PartialEq=true) @VintfStability
+parcelable PlainPubKey {
+  byte[] plainPubKey;
+}
diff --git a/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/PubKey.aidl b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/PubKey.aidl
new file mode 100644
index 0000000..4c3376e
--- /dev/null
+++ b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/PubKey.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2023 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.security.authgraph;
+@RustDerive(Clone=true, Eq=true, PartialEq=true) @VintfStability
+union PubKey {
+  android.hardware.security.authgraph.PlainPubKey plainKey;
+  android.hardware.security.authgraph.SignedPubKey signedKey;
+}
diff --git a/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/SessionIdSignature.aidl b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/SessionIdSignature.aidl
new file mode 100644
index 0000000..6dabc0a
--- /dev/null
+++ b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/SessionIdSignature.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2023 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.security.authgraph;
+@RustDerive(Clone=true, Eq=true, PartialEq=true) @VintfStability
+parcelable SessionIdSignature {
+  byte[] signature;
+}
diff --git a/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/SessionInfo.aidl b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/SessionInfo.aidl
new file mode 100644
index 0000000..427962b
--- /dev/null
+++ b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/SessionInfo.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2023 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.security.authgraph;
+@RustDerive(Clone=true, Eq=true, PartialEq=true) @VintfStability
+parcelable SessionInfo {
+  android.hardware.security.authgraph.Arc[2] sharedKeys;
+  byte[] sessionId;
+  android.hardware.security.authgraph.SessionIdSignature signature;
+}
diff --git a/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/SessionInitiationInfo.aidl b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/SessionInitiationInfo.aidl
new file mode 100644
index 0000000..bf55e74
--- /dev/null
+++ b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/SessionInitiationInfo.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2023 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.security.authgraph;
+@RustDerive(Clone=true, Eq=true, PartialEq=true) @VintfStability
+parcelable SessionInitiationInfo {
+  android.hardware.security.authgraph.Key key;
+  android.hardware.security.authgraph.Identity identity;
+  byte[] nonce;
+  int version;
+}
diff --git a/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/SignedPubKey.aidl b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/SignedPubKey.aidl
new file mode 100644
index 0000000..3dbaed8
--- /dev/null
+++ b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/SignedPubKey.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2023 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.security.authgraph;
+@RustDerive(Clone=true, Eq=true, PartialEq=true) @VintfStability
+parcelable SignedPubKey {
+  byte[] signedPubKey;
+}
diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/Arc.aidl b/security/authgraph/aidl/android/hardware/security/authgraph/Arc.aidl
new file mode 100644
index 0000000..855ce5c
--- /dev/null
+++ b/security/authgraph/aidl/android/hardware/security/authgraph/Arc.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.security.authgraph;
+
+/**
+ * This is the definition of the data format of an Arc.
+ * @hide
+ */
+@VintfStability
+@RustDerive(Clone=true, Eq=true, PartialEq=true)
+parcelable Arc {
+    /**
+     * The messages exchanged between the domains in the AuthGraph protocol are called Arcs.
+     * An arc is simply AES-GCM. Encryption of a payload P with a key K and additional
+     * authentication data (AAD) D: (i.e. Arc = Enc(K, P, D)).
+     *
+     * Data is CBOR-encoded according to the `Arc` CDDL definition in Arc.cddl.
+     */
+    byte[] arc;
+}
diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/Arc.cddl b/security/authgraph/aidl/android/hardware/security/authgraph/Arc.cddl
new file mode 100644
index 0000000..4c1b965
--- /dev/null
+++ b/security/authgraph/aidl/android/hardware/security/authgraph/Arc.cddl
@@ -0,0 +1,115 @@
+;
+; Copyright (C) 2023 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.
+;
+Arc = [                            ; COSE_Encrypt0 [RFC9052 s5.2]
+    protected : bstr .cbor ArcProtectedHeaders,
+    unprotected : {
+        5 : bstr .size 12          ; IV
+    },
+    ciphertext : bstr    ; Enc(K, bstr .cbor Payload, encoded ArcEncStruct)
+]
+
+ArcProtectedHeaders = {
+           1 : 3,                  ; Algorithm: AES-GCM mode w/ 256-bit key, 128-bit tag
+    ? -70001 : { + Permission }, ; One or more Permissions
+    ? -70002 : { + Limitation }, ; One or more Limitations
+    ? -70003 : int,   ; Timestamp in milliseconds since some starting point (generally
+                      ; the most recent device boot) which all of the applications within
+                      ; the secure domain must agree upon
+    ? -70004 : bstr .size 16,      ; Nonce used in key exchange methods
+    ? -70005 : PayloadType,        ; Payload type, if needed to disambiguate, when processing an arc
+    ? -70006 : int,                ; Version of the payload structure (if applicable)
+    ? -70007 : int,                ; Sequence number (if needed to prevent replay attacks)
+    ? -70008 : Direction           ; Direction of the encryption key (i.e. whether it is used to
+                                   ; encrypt incoming messages or outgoing messages)
+    ? -70009 : bool,               ; "authentication_completed" - this is used during authenticated
+                                   ; key exchange indicate whether signature verification is done
+    ? -70010 : bstr .size 32       ; "session_id" computed during key exchange protocol
+}
+
+; Permissions indicate what an arc can be used with. Permissions are added to an arc during the
+; `create()` primitive operation and are propagated during `mint` and `snap` primitive operations.
+Permission = &(
+    -4770552 : IdentityEncoded,  ; "source_id" - in the operations performed by a source, the
+                                 ; source adds its own identity to the permissions of an arc.
+    -4770553 : IdentityEncoded,  ; "sink_id" - in the operations performed by a sink, the sink
+                                 ; adds its own identity to the permissions of an arc.
+    -4770555 : [ +IdentityEncoded ]  ; "minting_allowed" - defines the set of TA identities
+                                     ; to whom the payload key is allowed to be minted.
+    -4770556 : bool                  ; "deleted_on_biometric_change" - A Boolean value that
+                                     ; indicates whether an auth key issued from a biometric TA is
+                                     ; invalidated on new biometric enrollment or removal of all
+                                     ; biometrics.
+)
+
+; Limitations indicate what restrictions are applied on the usage of an arc. Permissions are added
+; to an arc during the `create` primitive operation and are propagated during `snap` primitive
+; operation.
+Limitation = &(
+    -4770554 : bstr,      ; "challenge" - is added to an arc that transfers an auth key to a channel
+                          ; key, in order to ensure the freshness of the authentication.
+                          ; A challenge is issued by a sink (e.g. Keymint TA, Biometric TAs).
+)
+
+; INCLUDE Identity.cddl for: Identity
+IdentityEncoded = bstr .cbor Identity
+
+Direction = &(
+    In:  1,
+    Out: 2,
+)
+
+PayloadType = &(
+    SecretKey: 1,
+    Arc: 2,
+    ; Any other payload types should also be defined here
+)
+
+Payload = &(
+    SecretKey,
+    Arc,
+    ; Any other payload formats should also be defined here
+)
+
+SecretKey = &(                     ; One of the payload types of an Arc is a secret key
+    SymmetricKey,
+    ECPrivateKey,    ; Private key of a key pair generated for key exchange
+)
+
+ECPrivateKey = {              ; COSE_Key [RFC9052 s7]
+    1 : 2,                    ; Key type : EC2
+    3 : -25,                  ; Algorithm: ECDH ES w/ HKDF 256 - generate key directly
+ ?  4 : [7],                  ; Key_ops: [derive key]
+   -1 : 1,                    ; Curve: P-256
+ ? -2 : bstr,                 ; x coordinate
+ ? -3 : bstr,                 ; y coordinate
+   -4 : bstr,                 ; private key (d)
+}
+
+SymmetricKey = {              ; COSE_Key [RFC9052 s7] - For symmetric key encryption
+    1 : 4,                    ; Key type : Symmetric
+    3 : 3,                    ; Algorithm : AES-GCM mode w/ 256-bit key, 128-bit tag
+    4 : [ 4 ],                ; Key_ops: [decrypt]
+   -1 : bstr .size 32,        ; Key value (k)
+}
+
+ArcEncStruct = [              ; COSE_Enc_structure [RFC9052 s5.3]
+    context   : "Encrypt0",
+    protected : bstr .cbor ArcProtectedHeaders,
+    external_aad : bstr .size 0,
+]
+
+; INCLUDE generateCertificateRequestV2.cddl for: PubKeyEd25519, PubKeyECDSA256, PubKeyECDSA384
+; from hardware/interfaces/security/rkp/aidl/android/hardware/security/keymint/
diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/DicePolicy.cddl b/security/authgraph/aidl/android/hardware/security/authgraph/DicePolicy.cddl
new file mode 100644
index 0000000..a7dcbc6
--- /dev/null
+++ b/security/authgraph/aidl/android/hardware/security/authgraph/DicePolicy.cddl
@@ -0,0 +1,33 @@
+;
+; Copyright (C) 2023 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.
+;
+DicePolicy = [
+    1, ; dice policy version
+    + nodeConstraintList ; for each entry in dice chain
+]
+
+nodeConstraintList = [
+    * nodeConstraint
+]
+
+; We may add a hashConstraint item later
+nodeConstraint = exactMatchConstraint / geConstraint
+
+exactMatchConstraint = [1, keySpec, value]
+geConstraint = [2, keySpec, int]
+
+keySpec = [value+]
+
+value = bool / int / tstr / bstr
\ No newline at end of file
diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/Error.aidl b/security/authgraph/aidl/android/hardware/security/authgraph/Error.aidl
new file mode 100644
index 0000000..1ad6054
--- /dev/null
+++ b/security/authgraph/aidl/android/hardware/security/authgraph/Error.aidl
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.security.authgraph;
+
+/**
+ * AuthGraph error codes. Aidl will return these error codes as service specific errors in
+ * EX_SERVICE_SPECIFIC.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum Error {
+    /* Success */
+    OK = 0,
+    /* Invalid peer nonce for key exchange */
+    INVALID_PEER_NONCE = -1,
+    /* Invalid key exchange public key by the peer */
+    INVALID_PEER_KE_KEY = -2,
+    /* Invalid identity of the peer */
+    INVALID_IDENTITY = -3,
+    /* Invalid certificate chain in the identity of the peer */
+    INVALID_CERT_CHAIN = -4,
+    /* Invalid signature by the peer */
+    INVALID_SIGNATURE = -5,
+    /* Invalid key exchange key created by a particular party themselves to be used as a handle */
+    INVALID_KE_KEY = -6,
+    /* Invalid public key in the `Key` struct */
+    INVALID_PUB_KEY_IN_KEY = -7,
+    /* Invalid private key arc in the `Key` struct */
+    INVALID_PRIV_KEY_ARC_IN_KEY = -8,
+    /* Invalid shared key arcs */
+    INVALID_SHARED_KEY_ARCS = -9,
+    /* Memory allocation failed */
+    MEMORY_ALLOCATION_FAILED = -10,
+    /* The protocol version negotiated with the sink is incompatible */
+    INCOMPATIBLE_PROTOCOL_VERSION = -11,
+}
diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/ExplicitKeyDiceCertChain.cddl b/security/authgraph/aidl/android/hardware/security/authgraph/ExplicitKeyDiceCertChain.cddl
new file mode 100644
index 0000000..3de5617
--- /dev/null
+++ b/security/authgraph/aidl/android/hardware/security/authgraph/ExplicitKeyDiceCertChain.cddl
@@ -0,0 +1,30 @@
+;
+; Copyright (C) 2023 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.
+;
+ExplicitKeyDiceCertChain = [
+    1, ; version, hopefully will never change
+    DiceCertChainInitialPayload,
+    * DiceChainEntry
+]
+
+DiceCertChainInitialPayload = {
+    -4670552 : bstr .cbor PubKeyEd25519 /
+               bstr .cbor PubKeyECDSA256 /
+               bstr .cbor PubKeyECDSA384 ; subjectPublicKey
+}
+
+; INCLUDE generateCertificateRequestV2.cddl for: PubKeyEd25519, PubKeyECDSA256, PubKeyECDSA384,
+;                                                DiceChainEntry
+; from hardware/interfaces/security/rkp/aidl/android/hardware/security/keymint/
diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/IAuthGraphKeyExchange.aidl b/security/authgraph/aidl/android/hardware/security/authgraph/IAuthGraphKeyExchange.aidl
new file mode 100644
index 0000000..6ceb09c
--- /dev/null
+++ b/security/authgraph/aidl/android/hardware/security/authgraph/IAuthGraphKeyExchange.aidl
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.security.authgraph;
+
+import android.hardware.security.authgraph.Arc;
+import android.hardware.security.authgraph.Identity;
+import android.hardware.security.authgraph.KeInitResult;
+import android.hardware.security.authgraph.Key;
+import android.hardware.security.authgraph.PubKey;
+import android.hardware.security.authgraph.SessionIdSignature;
+import android.hardware.security.authgraph.SessionInfo;
+import android.hardware.security.authgraph.SessionInitiationInfo;
+
+/**
+ * AuthGraph interface definition for authenticated key exchange between two parties: P1 (source)
+ * and P2 (sink).
+ * Pre-requisites: each participant should have a:
+ *     1. Persistent identity - e.g. a signing key pair with a self signed certificate or a DICE
+ *        certificate chain.
+ *     2. A symmetric encryption key kept in memory with per-boot life time of the participant
+ *        (a.k.a per-boot key)
+ *
+ * ErrorCodes are defined in android.hardware.security.authgraph.ErrorCode.aidl.
+ * @hide
+ */
+@VintfStability
+interface IAuthGraphKeyExchange {
+    /**
+     * This method is invoked on P1 (source).
+     * Create an ephermeral EC key pair on NIST curve P-256 and a nonce (of 16 bytes) for
+     * key exchange.
+     *
+     * @return SessionInitiationInfo including the `Key` containing the public key of the created
+     * key pair and an arc from the per-boot key to the private key, the nonce, the persistent
+     * identity and the latest protocol version (i.e. AIDL version) supported.
+     *
+     * Note: The arc from the per-boot key to the private key in `Key` of the return type:
+     * `SessionInitiationInfo` serves two purposes:
+     * i. A mapping to correlate `create` and `finish` calls to P1 in a particular instance of the
+     *    key exchange protocol.
+     * ii.A way to minimize the in-memory storage (P1 can include the nonce in the protected headers
+     *    of the arc).
+     * However, P1 should maintain some form of in-memory record to be able to verify that the input
+     * `Key` sent to `finish` is from an unfinished instance of a key exchange protocol, to prevent
+     * any replay attacks in `finish`.
+     */
+    SessionInitiationInfo create();
+
+    /**
+     * This method is invoked on P2 (sink).
+     * Perform the following steps for key exchange:
+     *     0. If either `peerPubKey`, `peerId`, `peerNonce` is not in the expected format, return
+     *        errors: INVALID_PEER_KE_KEY, INVALID_IDENTITY, INVALID_PEER_NONCE respectively.
+     *     1. Create an ephemeral EC key pair on NIST curve P-256.
+     *     2. Create a nonce (of 16 bytes).
+     *     3. Compute the diffie-hellman shared secret: Z.
+     *     4. Compute a salt = bstr .cbor [
+     *            source_version:    int,                    ; from input `peerVersion`
+     *            sink_pub_key:      bstr .cbor PlainPubKey, ; from step #1
+     *            source_pub_key:    bstr .cbor PlainPubKey, ; from input `peerPubKey`
+     *            sink_nonce:        bstr .size 16,          ; from step #2
+     *            source_nonce:      bstr .size 16,          ; from input `peerNonce`
+     *            sink_cert_chain:   bstr .cbor ExplicitKeyDiceCertChain, ; from own identity
+     *            source_cert_chain: bstr .cbor ExplicitKeyDiceCertChain, ; from input `peerId`
+     *        ]
+     *     5. Extract a cryptographic secret S from Z, using the salt from #4 above.
+     *     6. Derive two symmetric encryption keys of 256 bits with:
+     *        i. b"KE_ENCRYPTION_KEY_SOURCE_TO_SINK" as context for the key used to encrypt incoming
+     *           messages
+     *       ii. b"KE_ENCRYPTION_KEY_SINK_TO_SOURCE" as context for the key used to encrypt outgoing
+     *           messages
+     *     7. Create arcs from the per-boot key to each of the two shared keys from step #6 and
+     *        mark authentication_complete = false in arcs' protected headers.
+     *     8. Derive a MAC key with b"KE_HMAC_KEY" as the context.
+     *     9. Compute session_id_input = bstr .cbor [
+     *            sink_nonce:     bstr .size 16,
+     *            source_nonce:   bstr .size 16,
+     *        ],
+     *     10.Compute a session_id as a 256 bits HMAC over the session_id_input from step#9 with
+     *        the key from step #8.
+     *     11.Create a signature over the session_id from step #10, using the signing key which is
+     *        part of the party's identity.
+     *
+     * @param peerPubKey - the public key of the key pair created by the peer (P1) for key exchange
+     *
+     * @param peerId - the persistent identity of the peer
+     *
+     * @param peerNonce - nonce created by the peer
+     *
+     * @param peerVersion - an integer representing the latest protocol version (i.e. AIDL version)
+     *                      supported by the peer
+     *
+     * @return KeInitResult including the `Key` containing the public key of the created key pair,
+     * the nonce, the persistent identity, two shared key arcs from step #7, session id, signature
+     * over the session id and the negotiated protocol version. The negotiated protocol version
+     * should be less than or equal to the peer's version.
+     *
+     * Note: The two shared key arcs in the return type: `KeInitResult` serves two purposes:
+     * i. A mapping to correlate `init` and `authenticationComplete` calls to P2 in a particular
+     *    instance of the key exchange protocol.
+     * ii.A way to minimize the in-memory storage of P2 allocated for key exchange.
+     * However, P2 should maintain some in-memory record to be able to verify that the input
+     * `sharedkeys` sent to `authenticationComplete` and to any subsequent AuthGraph protocol
+     * methods are valid shared keys agreed with the party identified by `peerId`, to prevent
+     * any replay attacks in `authenticationComplete` and in any subsequent AuthGraph protocol
+     * methods which use the shared keys to encrypt the secret messages.
+     */
+    KeInitResult init(
+            in PubKey peerPubKey, in Identity peerId, in byte[] peerNonce, in int peerVersion);
+
+    /**
+     * This method is invoked on P1 (source).
+     * Perform the following steps:
+     *     0. If either `peerPubKey`, `peerId`, `peerNonce` is not in the expected format, return
+     *        errors: INVALID_PEER_KE_KEY, INVALID_IDENTITY, INVALID_PEER_NONCE respectively. If
+     *        `peerVersion` is greater than the version advertised in `create`, return error:
+     *        INCOMPATIBLE_PROTOCOL_VERSION.
+     *        If `ownKey` is not in the in-memory records for unfinished instances of a key
+     *        exchange protocol, return error: INVALID_KE_KEY. Similarly, if the public key or the
+     *        arc containing the private key in `ownKey` is invalid, return INVALID_PUB_KEY_IN_KEY
+     *        and INVALID_PRIV_KEY_ARC_IN_KEY respectively.
+     *     1. Compute the diffie-hellman shared secret: Z.
+     *     2. Compute a salt = bstr .cbor [
+     *            source_version:    int,                    ; the protocol version used in `create`
+     *            sink_pub_key:      bstr .cbor PlainPubKey, ; from input `peerPubKey`
+     *            source_pub_key:    bstr .cbor PlainPubKey, ; from the output of `create`
+     *            sink_nonce:        bstr .size 16,          ; from input `peerNonce`
+     *            source_nonce:      bstr .size 16,          ; from the output of `create`
+     *            sink_cert_chain:   bstr .cbor ExplicitKeyDiceCertChain, ; from input `peerId`
+     *            source_cert_chain: bstr .cbor ExplicitKeyDiceCertChain, ; from own identity
+     *        ]
+     *     3. Extract a cryptographic secret S from Z, using the salt from #2 above.
+     *     4. Derive two symmetric encryption keys of 256 bits with:
+     *        i. b"KE_ENCRYPTION_KEY_SOURCE_TO_SINK" as context for the key used to encrypt outgoing
+     *           messages
+     *       ii. b"KE_ENCRYPTION_KEY_SINK_TO_SOURCE" as context for the key used to encrypt incoming
+     *           messages
+     *     5. Derive a MAC key with b"KE_HMAC_KEY" as the context.
+     *     6. Compute session_id_input = bstr .cbor [
+     *            sink_nonce:     bstr .size 16,
+     *            source_nonce:   bstr .size 16,
+     *        ],
+     *     7. Compute a session_id as a 256 bits HMAC over the session_id_input from step #6 with
+     *        the key from step #5.
+     *     8. Verify the peer's signature over the session_id from step #7. If successful, proceed,
+     *        otherwise, return error: INVALID_SIGNATURE.
+     *     9. Create arcs from the per-boot key to each of the two shared keys from step #4 and
+     *        mark authentication_complete = true in arcs' protected headers.
+     *     10.Create a signature over the session_id from step #7, using the signing key which is
+     *        part of the party's identity.
+     *
+     * @param peerPubKey - the public key of the key pair created by the peer (P2) for key exchange
+     *
+     * @param peerId - the persistent identity of the peer
+     *
+     * @param peerSignature - the signature created by the peer over the session id computed by the
+     *                        peer
+     *
+     * @param peerNonce - nonce created by the peer
+     *
+     * @param peerVersion - an integer representing the protocol version (i.e. AIDL version)
+     *                      negotiated with the peer
+     *
+     * @param ownKey - the key created by P1 (source) in `create()` for key exchange
+     *
+     * @return SessionInfo including the two shared key arcs from step #9, session id and the
+     * signature over the session id.
+     *
+     * Note: The two shared key arcs in the return type: `SessionInfo` serves two purposes:
+     * i. A mapping to correlate the key exchange protocol taken place with a particular peer and
+     *    subsequent AuthGraph protocols execued with the same peer.
+     * ii.A way to minimize the in-memory storage for shared keys.
+     * However, P1 should maintain some in-memory record to be able to verify that the shared key
+     * arcs sent to any subsequent AuthGraph protocol methods are valid shared keys agreed with the
+     * party identified by `peerId`, to prevent any replay attacks.
+     */
+    SessionInfo finish(in PubKey peerPubKey, in Identity peerId,
+            in SessionIdSignature peerSignature, in byte[] peerNonce, in int peerVersion,
+            in Key ownKey);
+
+    /**
+     * This method is invoked on P2 (sink).
+     * Perform the following steps:
+     *   0. If input `sharedKeys` is invalid (i.e. they cannot be decrypted with P2's per-boot key
+     *      or they are not in P2's in-memory records as valid shared keys agreed with the party
+     *      identified by `peerId`), return error: INVALID_SHARED_KEY_ARCS.
+     *   1. Verify that both shared key arcs have the same session id and peer identity.
+     *   2. Verify the peer's signature over the session id attached to the shared key arcs'
+     *      headers. If successful, proceed, otherwise, return error: INVALID_SIGNATURE.
+     *   3. Mark authentication_complete = true in the shared key arcs' headers
+     *
+     * @param peerSignature - the signature created by the peer over the session id computed by the
+     *                        peer
+     *
+     * @param sharedKeys - two shared key arcs created by P2 in `init`. P2 obtains from the arcs'
+     *                     protected headers, the session id and the peer's identity to verify the
+     *                     peer's signature over the session id.
+     *
+     * @return Arc[] - an array of two updated shared key arcs
+     */
+    Arc[2] authenticationComplete(in SessionIdSignature peerSignature, in Arc[2] sharedKeys);
+}
diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/Identity.aidl b/security/authgraph/aidl/android/hardware/security/authgraph/Identity.aidl
new file mode 100644
index 0000000..9e350e8
--- /dev/null
+++ b/security/authgraph/aidl/android/hardware/security/authgraph/Identity.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.security.authgraph;
+
+/**
+ * Persistent (versioned) identity of a participant of Authgraph key exchange.
+ * Identity consists of two main parts:
+ *     1. a certificate chain (e.g. a DICE certificate chain)
+ *     2. (optional) a policy specifying how to verify the certificate chain - if a policy is not
+ *        provided, a simple byte-to-byte comparison of the certificate chain is assumed.
+ *
+ * During identity verification, the certificate chain of the identity attached to the access
+ * request is compared against the policy of the identity attached to the persistent resources.
+ *
+ * The usage of policy based identity verification in Authgraph is three-fold:
+ *        1. Retain access to persistent resources for the newer versions of the party who
+ *           created them, even when parts of the certificate chain are updated in the new version.
+ *        2. Deny access to the new persistent resources for the older versions of the party
+ *           who created the new persistent resources.
+ *        3. Trigger rotation of critical keys encrypted in persistent arcs created by the previous
+ *           version of the party, by including an updated policy in the identity attached to the
+ *           access request.
+ */
+@VintfStability
+@RustDerive(Clone=true, Eq=true, PartialEq=true)
+parcelable Identity {
+    /* Data is CBOR-encoded according to the `Identity` CDDL definition in Identity.cddl */
+    byte[] identity;
+}
diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/Identity.cddl b/security/authgraph/aidl/android/hardware/security/authgraph/Identity.cddl
new file mode 100644
index 0000000..0419421
--- /dev/null
+++ b/security/authgraph/aidl/android/hardware/security/authgraph/Identity.cddl
@@ -0,0 +1,23 @@
+;
+; Copyright (C) 2023 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.
+;
+Identity = [
+    1, ; Version
+    cert_chain: bstr .cbor ExplicitKeyDiceCertChain,
+    policy: bstr .cbor DicePolicy / nil,
+]
+
+; INCLUDE ExplicitKeyDiceCertChain.cddl for: ExplicitKeyDiceCertChain
+; INCLUDE DicePolicy.cddl for: DicePolicy
diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/KeInitResult.aidl b/security/authgraph/aidl/android/hardware/security/authgraph/KeInitResult.aidl
new file mode 100644
index 0000000..b4ae451
--- /dev/null
+++ b/security/authgraph/aidl/android/hardware/security/authgraph/KeInitResult.aidl
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.security.authgraph;
+
+import android.hardware.security.authgraph.SessionInfo;
+import android.hardware.security.authgraph.SessionInitiationInfo;
+
+/**
+ * The return type for the init() step of authenticated key exchange.
+ */
+@VintfStability
+@RustDerive(Clone=true, Eq=true, PartialEq=true)
+parcelable KeInitResult {
+    /**
+     * Session initiation information.
+     */
+    SessionInitiationInfo sessionInitiationInfo;
+
+    /**
+     * Session information.
+     */
+    SessionInfo sessionInfo;
+}
diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/Key.aidl b/security/authgraph/aidl/android/hardware/security/authgraph/Key.aidl
new file mode 100644
index 0000000..11fe174
--- /dev/null
+++ b/security/authgraph/aidl/android/hardware/security/authgraph/Key.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.security.authgraph;
+
+import android.hardware.security.authgraph.Arc;
+import android.hardware.security.authgraph.PubKey;
+
+/**
+ * The type that encapsulates a key. Key can be either a symmetric key or an asymmetric key.
+ * If it is an asymmetric key, it is used for key exchange.
+ */
+@VintfStability
+@RustDerive(Clone=true, Eq=true, PartialEq=true)
+parcelable Key {
+    /**
+     * If the Key is an asymmetric key, public key should be present.
+     */
+    @nullable PubKey pubKey;
+
+    /**
+     * Arc from the per-boot key to the payload key. The payload key is either the symmetric key
+     * or the private key of an asymmetric key, based on the type of the key being created.
+     * This is marked as optional because there are instances where only the public key is returned,
+     * e.g. `init` method in the key exchange protocol.
+     */
+    @nullable Arc arcFromPBK;
+}
diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/PlainPubKey.aidl b/security/authgraph/aidl/android/hardware/security/authgraph/PlainPubKey.aidl
new file mode 100644
index 0000000..5483ec5
--- /dev/null
+++ b/security/authgraph/aidl/android/hardware/security/authgraph/PlainPubKey.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.security.authgraph;
+
+/**
+ * One of the two enum variants of the enum type: `PubKey`. This represents the plain public key
+ * material encoded as a COSE_Key.
+ */
+@VintfStability
+@RustDerive(Clone=true, Eq=true, PartialEq=true)
+parcelable PlainPubKey {
+    /* Data is CBOR-encoded according to the `PlainPubKey` CDDL definition in PlainPubKey.cddl */
+    byte[] plainPubKey;
+}
diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/PlainPubKey.cddl b/security/authgraph/aidl/android/hardware/security/authgraph/PlainPubKey.cddl
new file mode 100644
index 0000000..34b316b
--- /dev/null
+++ b/security/authgraph/aidl/android/hardware/security/authgraph/PlainPubKey.cddl
@@ -0,0 +1,24 @@
+;
+; Copyright (C) 2023 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.
+;
+
+; P-256 public key for key exchange.
+PlainPubKey = [ ; COSE_Key [RFC9052 s7]
+    1 : 2,                       ; Key type : EC2
+    3 : -27,                     ; Algorithm : ECDH-SS + HKDF-256
+    -1 : 1,                      ; Curve: P256
+    -2 : bstr,                   ; X coordinate, big-endian
+    -3 : bstr                    ; Y coordinate, big-endian
+]
diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/PubKey.aidl b/security/authgraph/aidl/android/hardware/security/authgraph/PubKey.aidl
new file mode 100644
index 0000000..8640871
--- /dev/null
+++ b/security/authgraph/aidl/android/hardware/security/authgraph/PubKey.aidl
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.security.authgraph;
+
+import android.hardware.security.authgraph.PlainPubKey;
+import android.hardware.security.authgraph.SignedPubKey;
+
+/**
+ * The enum type representing the public key of an asymmetric key pair.
+ */
+@VintfStability
+@RustDerive(Clone=true, Eq=true, PartialEq=true)
+union PubKey {
+    /**
+     * Plain public key material encoded as a COSE_Key.
+     */
+    PlainPubKey plainKey;
+
+    /**
+     * Public key signed with the long term signing key of the party.
+     */
+    SignedPubKey signedKey;
+}
diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/SessionIdSignature.aidl b/security/authgraph/aidl/android/hardware/security/authgraph/SessionIdSignature.aidl
new file mode 100644
index 0000000..2fa8b4c
--- /dev/null
+++ b/security/authgraph/aidl/android/hardware/security/authgraph/SessionIdSignature.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.security.authgraph;
+
+/**
+ * Signature computed by a party over the session id during authenticated key exchange.
+ */
+@VintfStability
+@RustDerive(Clone=true, Eq=true, PartialEq=true)
+parcelable SessionIdSignature {
+    /* Data is CBOR-encoded according to the `SessionIdSignature` CDDL definition in
+     * SessionIdSignature.cddl */
+    byte[] signature;
+}
diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/SessionIdSignature.cddl b/security/authgraph/aidl/android/hardware/security/authgraph/SessionIdSignature.cddl
new file mode 100644
index 0000000..038a0f0
--- /dev/null
+++ b/security/authgraph/aidl/android/hardware/security/authgraph/SessionIdSignature.cddl
@@ -0,0 +1,33 @@
+;
+; Copyright (C) 2023 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.
+;
+SessionIdSignature = [ ; COSE_Sign1 (untagged) [RFC9052 s4.2]
+    protected: bstr .cbor SessionIdSignatureProtected,
+    unprotected: {},
+    payload: nil,       ; session ID payload to be transported separately
+    signature: bstr     ; PureEd25519(privateKey, SessionIdSignatureSigStruct) /
+                        ; ECDSA(privateKey, SessionIdSignatureSigStruct)
+]
+
+SessionIdSignatureProtected = {
+    1 : AlgorithmEdDSA / AlgorithmES256,
+}
+
+SessionIdSignatureSigStruct = [ ; Sig_structure for SessionIdSignature [ RFC9052 s4.4]
+    context: "Signature1",
+    protected: bstr SessionIdSignatureProtected,
+    external_aad: bstr .size 0,
+    payload: bstr,       ; session ID payload provided separately
+]
diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/SessionInfo.aidl b/security/authgraph/aidl/android/hardware/security/authgraph/SessionInfo.aidl
new file mode 100644
index 0000000..ef49a1a
--- /dev/null
+++ b/security/authgraph/aidl/android/hardware/security/authgraph/SessionInfo.aidl
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.security.authgraph;
+
+import android.hardware.security.authgraph.Arc;
+import android.hardware.security.authgraph.SessionIdSignature;
+
+/**
+ * Session information returned as part of authenticated key exchange.
+ */
+@VintfStability
+@RustDerive(Clone=true, Eq=true, PartialEq=true)
+parcelable SessionInfo {
+    /**
+     * The arcs that encrypt the two derived symmetric encryption keys (for two-way communication)
+     * from the party's per-boot key.
+     */
+    Arc[2] sharedKeys;
+
+    /**
+     * The value of the session id computed by the two parties during the authenticate key
+     * exchange. Apart from the usage of the session id by the two peers, session id is also useful
+     * to verify (by a third party) that the key exchange was successful.
+     */
+    byte[] sessionId;
+
+    /**
+     * The signature over the session id, created by the party who computed the session id.
+     *
+     * If there is one or more `DiceChainEntry` in the `ExplicitKeyDiceCertChain` of the party's
+     * identity, the signature is verified with the public key in the leaf of the chain of
+     * DiceChainEntries (i.e the public key in the last of the array of DiceChainEntries).
+     * Otherwise, the signature is verified with the `DiceCertChainInitialPayload`.
+     */
+    SessionIdSignature signature;
+}
diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/SessionInitiationInfo.aidl b/security/authgraph/aidl/android/hardware/security/authgraph/SessionInitiationInfo.aidl
new file mode 100644
index 0000000..c630d91
--- /dev/null
+++ b/security/authgraph/aidl/android/hardware/security/authgraph/SessionInitiationInfo.aidl
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.security.authgraph;
+
+import android.hardware.security.authgraph.Arc;
+import android.hardware.security.authgraph.Identity;
+import android.hardware.security.authgraph.Key;
+
+/**
+ * Session initiation information returned as part of authenticated key exchange.
+ */
+@VintfStability
+@RustDerive(Clone=true, Eq=true, PartialEq=true)
+parcelable SessionInitiationInfo {
+    /**
+     * An ephemeral EC key created for the ECDH process.
+     */
+    Key key;
+
+    /**
+     * The identity of the party who created the Diffie-Hellman key exchange key.
+     */
+    Identity identity;
+
+    /**
+     * Nonce value specific to this session. The nonce serves three purposes:
+     * 1. freshness of key exchange
+     * 2. creating a session id (a publicly known value related to the exchanged keys)
+     * 3. usage as salt into the HKDF-EXTRACT function during key derivation from the shared DH key
+     */
+    byte[] nonce;
+
+    /**
+     * The protocol version (i.e. AIDL version) - This is used to prevent version downgrade attacks
+     * as follows:
+     * 1. In `create`, the source advertises the latest protocol version supported by the source,
+     *    which is given as input to the `init` call on the sink in the input parameter:
+     *    `peerVersion`.
+     * 2. In `init`, the sink includes the `peerVersion` in the inputs to the derivation of the
+     *    shared keys. Then the sink returns the latest protocol version supported by the sink,
+     *    which is given as input to the `finish` call on the source in the input parameter:
+     *    `peerVersion`.
+     * 3. In `finish`, the source first checks whether the sink's version is equal or less than the
+     *    source's version and includes in the source's version in the inputs to the derivation of
+     *    the shared keys.
+     * Analysis: if an attacker-in-the-middle wanted the two parties to use an older (vulnerable)
+     * version of the protocol, they can invoke `init` with a version that is lower than the version
+     * advertised by the source in `create`. However, since both parties include the source's
+     * version in the inputs to the derivation of the shared keys, the two parties won't end up with
+     * the same shared keys in the presence of such an attack. This is detected when checking the
+     * signature on the session id in `finish`, at which point the protocol aborts. Therefore,
+     * an attacker cannot successfully launch a version downgrade attack on this protocol.
+     */
+    int version;
+}
diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/SignedPubKey.aidl b/security/authgraph/aidl/android/hardware/security/authgraph/SignedPubKey.aidl
new file mode 100644
index 0000000..72ee219
--- /dev/null
+++ b/security/authgraph/aidl/android/hardware/security/authgraph/SignedPubKey.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.security.authgraph;
+
+/**
+ * One of the two enum variants of the enum type: `PubKey`. This represents the public key signed
+ * with the long term signing key of the party.
+ */
+@VintfStability
+@RustDerive(Clone=true, Eq=true, PartialEq=true)
+parcelable SignedPubKey {
+    /* Data is CBOR-encoded according to the `SignedPubKey` CDDL definition in SignedPubKey.cddl */
+    byte[] signedPubKey;
+}
diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/SignedPubKey.cddl b/security/authgraph/aidl/android/hardware/security/authgraph/SignedPubKey.cddl
new file mode 100644
index 0000000..f23a492
--- /dev/null
+++ b/security/authgraph/aidl/android/hardware/security/authgraph/SignedPubKey.cddl
@@ -0,0 +1,41 @@
+;
+; Copyright (C) 2023 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.
+;
+SignedPubKey = [ ; COSE_Sign1 (untagged) [RFC9052 s4.2]
+    protected: bstr .cbor SignedPubKeyProtected,
+    unprotected: {},
+    payload: bstr .cbor PlainPubKey,
+    signature: bstr     ; PureEd25519(privateKey, SignedPubKeySigStruct) /
+                        ; ECDSA(privateKey, SignedPubKeySigStruct)
+]
+
+SignedPubKeyProtected = {
+           1 : AlgorithmEdDSA / AlgorithmES256,
+    ? -70011 : Identity,        ; the party who performs the signing operation adds its own
+                                ; identity to the protected headers.
+}
+
+SignedPubKeySigStruct = [ ; Sig_structure for SignedPubKey [ RFC9052 s4.4]
+    context: "Signature1",
+    protected: bstr SignedPubKeyProtected,
+    external_aad: bstr .size 0,
+    payload: bstr .cbor PlainPubKey,
+]
+
+AlgorithmES256 = -7              ; [RFC9053 s2.1]
+AlgorithmEdDSA = -8              ; [RFC9053 s2.2]
+
+; INCLUDE PlainPubKey.cddl for: PlainPubKey
+; INCLUDE Identity.cddl for: Identity
\ No newline at end of file
diff --git a/security/authgraph/aidl/vts/functional/Android.bp b/security/authgraph/aidl/vts/functional/Android.bp
new file mode 100644
index 0000000..fc13759
--- /dev/null
+++ b/security/authgraph/aidl/vts/functional/Android.bp
@@ -0,0 +1,48 @@
+//
+// Copyright (C) 2023 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_interfaces_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_test {
+    name: "VtsAidlAuthGraphSessionTest",
+    defaults: [
+        "VtsHalTargetTestDefaults",
+        "authgraph_use_latest_hal_aidl_ndk_static",
+        "use_libaidlvintf_gtest_helper_static",
+    ],
+    cflags: [
+        "-Wall",
+        "-Wextra",
+    ],
+    srcs: [
+        "AuthGraphSessionTest.cpp",
+    ],
+    shared_libs: [
+        "libbinder_ndk",
+        "libcrypto",
+    ],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
+}
diff --git a/security/authgraph/aidl/vts/functional/AuthGraphSessionTest.cpp b/security/authgraph/aidl/vts/functional/AuthGraphSessionTest.cpp
new file mode 100644
index 0000000..d9dea77
--- /dev/null
+++ b/security/authgraph/aidl/vts/functional/AuthGraphSessionTest.cpp
@@ -0,0 +1,375 @@
+/*
+ * Copyright (C) 2023 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 "authgraph_session_test"
+#include <android-base/logging.h>
+
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/security/authgraph/Error.h>
+#include <aidl/android/hardware/security/authgraph/IAuthGraphKeyExchange.h>
+#include <android/binder_manager.h>
+#include <binder/ProcessState.h>
+#include <gtest/gtest.h>
+#include <vector>
+
+namespace aidl::android::hardware::security::authgraph::test {
+using ::aidl::android::hardware::security::authgraph::Error;
+
+namespace {
+
+// Check that the signature in the encoded COSE_Sign1 data is correct, and that the payload matches.
+// TODO: maybe drop separate payload, and extract it from cose_sign1.payload (and return it).
+void CheckSignature(std::vector<uint8_t>& /*pub_cose_key*/, std::vector<uint8_t>& /*payload*/,
+                    std::vector<uint8_t>& /*cose_sign1*/) {
+    // TODO: implement me
+}
+
+void CheckSignature(std::vector<uint8_t>& pub_cose_key, std::vector<uint8_t>& payload,
+                    SessionIdSignature& signature) {
+    return CheckSignature(pub_cose_key, payload, signature.signature);
+}
+
+std::vector<uint8_t> SigningKeyFromIdentity(const Identity& identity) {
+    // TODO: This is a CBOR-encoded `Identity` which currently happens to be a COSE_Key with the
+    // pubkey This will change in future.
+    return identity.identity;
+}
+
+}  // namespace
+
+class AuthGraphSessionTest : public ::testing::TestWithParam<std::string> {
+  public:
+    enum ErrorType { AIDL_ERROR, BINDER_ERROR };
+
+    union ErrorValue {
+        Error aidl_error;
+        int32_t binder_error;
+    };
+
+    struct ReturnedError {
+        ErrorType err_type;
+        ErrorValue err_val;
+
+        friend bool operator==(const ReturnedError& lhs, const ReturnedError& rhs) {
+            return lhs.err_type == rhs.err_type;
+            switch (lhs.err_type) {
+                case ErrorType::AIDL_ERROR:
+                    return lhs.err_val.aidl_error == rhs.err_val.aidl_error;
+                case ErrorType::BINDER_ERROR:
+                    return lhs.err_val.binder_error == rhs.err_val.binder_error;
+            }
+        }
+    };
+
+    const ReturnedError OK = {.err_type = ErrorType::AIDL_ERROR, .err_val.aidl_error = Error::OK};
+
+    ReturnedError GetReturnError(const ::ndk::ScopedAStatus& result) {
+        if (result.isOk()) {
+            return OK;
+        }
+        int32_t exception_code = result.getExceptionCode();
+        int32_t error_code = result.getServiceSpecificError();
+        if (exception_code == EX_SERVICE_SPECIFIC && error_code != 0) {
+            ReturnedError re = {.err_type = ErrorType::AIDL_ERROR,
+                                .err_val.aidl_error = static_cast<Error>(error_code)};
+            return re;
+        }
+        ReturnedError re = {.err_type = ErrorType::BINDER_ERROR,
+                            .err_val.binder_error = exception_code};
+        return re;
+    }
+
+    // Build the parameters for the VTS test by enumerating the available HAL instances
+    static std::vector<std::string> build_params() {
+        auto params = ::android::getAidlHalInstanceNames(IAuthGraphKeyExchange::descriptor);
+        return params;
+    }
+
+    void SetUp() override {
+        ASSERT_TRUE(AServiceManager_isDeclared(GetParam().c_str()))
+                << "No instance declared for " << GetParam();
+        ::ndk::SpAIBinder binder(AServiceManager_waitForService(GetParam().c_str()));
+        authNode_ = IAuthGraphKeyExchange::fromBinder(binder);
+        ASSERT_NE(authNode_, nullptr) << "Failed to get Binder reference for " << GetParam();
+    }
+
+    void TearDown() override {}
+
+  protected:
+    std::shared_ptr<IAuthGraphKeyExchange> authNode_;
+};
+
+TEST_P(AuthGraphSessionTest, Mainline) {
+    std::shared_ptr<IAuthGraphKeyExchange> source = authNode_;
+    std::shared_ptr<IAuthGraphKeyExchange> sink = authNode_;
+
+    // Step 1: create an ephemeral ECDH key at the source.
+    SessionInitiationInfo source_init_info;
+    ASSERT_EQ(OK, GetReturnError(source->create(&source_init_info)));
+    ASSERT_TRUE(source_init_info.key.pubKey.has_value());
+    ASSERT_TRUE(source_init_info.key.arcFromPBK.has_value());
+
+    // Step 2: pass the source's ECDH public key and other session info to the sink.
+    KeInitResult init_result;
+    ASSERT_EQ(OK, GetReturnError(sink->init(source_init_info.key.pubKey.value(),
+                                            source_init_info.identity, source_init_info.nonce,
+                                            source_init_info.version, &init_result)));
+    SessionInitiationInfo sink_init_info = init_result.sessionInitiationInfo;
+    ASSERT_TRUE(sink_init_info.key.pubKey.has_value());
+    // The sink_init_info.arcFromPBK need not be populated, as the ephemeral key agreement
+    // key is no longer needed.
+
+    SessionInfo sink_info = init_result.sessionInfo;
+    ASSERT_EQ((int)sink_info.sharedKeys.size(), 2) << "Expect two symmetric keys from init()";
+    ASSERT_GT((int)sink_info.sessionId.size(), 0) << "Expect non-empty session ID from sink";
+    std::vector<uint8_t> sink_signing_key = SigningKeyFromIdentity(sink_init_info.identity);
+    CheckSignature(sink_signing_key, sink_info.sessionId, sink_info.signature);
+
+    // Step 3: pass the sink's ECDH public key and other session info to the source, so it can
+    // calculate the same pair of symmetric keys.
+    SessionInfo source_info;
+    ASSERT_EQ(OK, GetReturnError(source->finish(sink_init_info.key.pubKey.value(),
+                                                sink_init_info.identity, sink_info.signature,
+                                                sink_init_info.nonce, sink_init_info.version,
+                                                source_init_info.key, &source_info)));
+    ASSERT_EQ((int)source_info.sharedKeys.size(), 2) << "Expect two symmetric keys from finsh()";
+    ASSERT_GT((int)source_info.sessionId.size(), 0) << "Expect non-empty session ID from source";
+    std::vector<uint8_t> source_signing_key = SigningKeyFromIdentity(source_init_info.identity);
+    CheckSignature(source_signing_key, source_info.sessionId, source_info.signature);
+
+    // Both ends should agree on the session ID.
+    ASSERT_EQ(source_info.sessionId, sink_info.sessionId);
+
+    // Step 4: pass the source's session ID info back to the sink, so it can check it and
+    // update the symmetric keys so they're marked as authentication complete.
+    std::array<Arc, 2> auth_complete_result;
+    ASSERT_EQ(OK, GetReturnError(sink->authenticationComplete(
+                          source_info.signature, sink_info.sharedKeys, &auth_complete_result)));
+    ASSERT_EQ((int)auth_complete_result.size(), 2)
+            << "Expect two symmetric keys from authComplete()";
+    sink_info.sharedKeys = auth_complete_result;
+
+    // At this point the sink and source have agreed on the same pair of symmetric keys,
+    // encoded as `sink_info.sharedKeys` and `source_info.sharedKeys`.
+}
+
+TEST_P(AuthGraphSessionTest, ParallelSink) {
+    std::shared_ptr<IAuthGraphKeyExchange> source = authNode_;
+    std::shared_ptr<IAuthGraphKeyExchange> sink1 = authNode_;
+    std::shared_ptr<IAuthGraphKeyExchange> sink2 = authNode_;
+
+    // Step 1: create ephemeral ECDH keys at the source.
+    SessionInitiationInfo source_init1_info;
+    ASSERT_EQ(OK, GetReturnError(source->create(&source_init1_info)));
+    ASSERT_TRUE(source_init1_info.key.pubKey.has_value());
+    ASSERT_TRUE(source_init1_info.key.arcFromPBK.has_value());
+    SessionInitiationInfo source_init2_info;
+    ASSERT_EQ(OK, GetReturnError(source->create(&source_init2_info)));
+    ASSERT_TRUE(source_init2_info.key.pubKey.has_value());
+    ASSERT_TRUE(source_init2_info.key.arcFromPBK.has_value());
+
+    // Step 2: pass the source's ECDH public keys and other session info to the sinks.
+    KeInitResult init1_result;
+    ASSERT_EQ(OK, GetReturnError(sink1->init(source_init1_info.key.pubKey.value(),
+                                             source_init1_info.identity, source_init1_info.nonce,
+                                             source_init1_info.version, &init1_result)));
+    SessionInitiationInfo sink1_init_info = init1_result.sessionInitiationInfo;
+    ASSERT_TRUE(sink1_init_info.key.pubKey.has_value());
+
+    SessionInfo sink1_info = init1_result.sessionInfo;
+    ASSERT_EQ((int)sink1_info.sharedKeys.size(), 2) << "Expect two symmetric keys from init()";
+    ASSERT_GT((int)sink1_info.sessionId.size(), 0) << "Expect non-empty session ID from sink";
+    std::vector<uint8_t> sink1_signing_key = SigningKeyFromIdentity(sink1_init_info.identity);
+    CheckSignature(sink1_signing_key, sink1_info.sessionId, sink1_info.signature);
+    KeInitResult init2_result;
+    ASSERT_EQ(OK, GetReturnError(sink2->init(source_init2_info.key.pubKey.value(),
+                                             source_init2_info.identity, source_init2_info.nonce,
+                                             source_init2_info.version, &init2_result)));
+    SessionInitiationInfo sink2_init_info = init2_result.sessionInitiationInfo;
+    ASSERT_TRUE(sink2_init_info.key.pubKey.has_value());
+
+    SessionInfo sink2_info = init2_result.sessionInfo;
+    ASSERT_EQ((int)sink2_info.sharedKeys.size(), 2) << "Expect two symmetric keys from init()";
+    ASSERT_GT((int)sink2_info.sessionId.size(), 0) << "Expect non-empty session ID from sink";
+    std::vector<uint8_t> sink2_signing_key = SigningKeyFromIdentity(sink2_init_info.identity);
+    CheckSignature(sink2_signing_key, sink2_info.sessionId, sink2_info.signature);
+
+    // Step 3: pass each sink's ECDH public key and other session info to the source, so it can
+    // calculate the same pair of symmetric keys.
+    SessionInfo source_info1;
+    ASSERT_EQ(OK, GetReturnError(source->finish(sink1_init_info.key.pubKey.value(),
+                                                sink1_init_info.identity, sink1_info.signature,
+                                                sink1_init_info.nonce, sink1_init_info.version,
+                                                source_init1_info.key, &source_info1)));
+    ASSERT_EQ((int)source_info1.sharedKeys.size(), 2) << "Expect two symmetric keys from finsh()";
+    ASSERT_GT((int)source_info1.sessionId.size(), 0) << "Expect non-empty session ID from source";
+    std::vector<uint8_t> source_signing_key1 = SigningKeyFromIdentity(source_init1_info.identity);
+    CheckSignature(source_signing_key1, source_info1.sessionId, source_info1.signature);
+    SessionInfo source_info2;
+    ASSERT_EQ(OK, GetReturnError(source->finish(sink2_init_info.key.pubKey.value(),
+                                                sink2_init_info.identity, sink2_info.signature,
+                                                sink2_init_info.nonce, sink2_init_info.version,
+                                                source_init2_info.key, &source_info2)));
+    ASSERT_EQ((int)source_info2.sharedKeys.size(), 2) << "Expect two symmetric keys from finsh()";
+    ASSERT_GT((int)source_info2.sessionId.size(), 0) << "Expect non-empty session ID from source";
+    std::vector<uint8_t> source_signing_key2 = SigningKeyFromIdentity(source_init2_info.identity);
+    CheckSignature(source_signing_key2, source_info2.sessionId, source_info2.signature);
+
+    // Both ends should agree on the session ID.
+    ASSERT_EQ(source_info1.sessionId, sink1_info.sessionId);
+    ASSERT_EQ(source_info2.sessionId, sink2_info.sessionId);
+
+    // Step 4: pass the source's session ID info back to the sink, so it can check it and
+    // update the symmetric keys so they're marked as authentication complete.
+    std::array<Arc, 2> auth_complete_result1;
+    ASSERT_EQ(OK, GetReturnError(sink1->authenticationComplete(
+                          source_info1.signature, sink1_info.sharedKeys, &auth_complete_result1)));
+    ASSERT_EQ((int)auth_complete_result1.size(), 2)
+            << "Expect two symmetric keys from authComplete()";
+    sink1_info.sharedKeys = auth_complete_result1;
+    std::array<Arc, 2> auth_complete_result2;
+    ASSERT_EQ(OK, GetReturnError(sink2->authenticationComplete(
+                          source_info2.signature, sink2_info.sharedKeys, &auth_complete_result2)));
+    ASSERT_EQ((int)auth_complete_result2.size(), 2)
+            << "Expect two symmetric keys from authComplete()";
+    sink2_info.sharedKeys = auth_complete_result2;
+}
+
+TEST_P(AuthGraphSessionTest, ParallelSource) {
+    std::shared_ptr<IAuthGraphKeyExchange> source1 = authNode_;
+    std::shared_ptr<IAuthGraphKeyExchange> source2 = authNode_;
+    std::shared_ptr<IAuthGraphKeyExchange> sink = authNode_;
+
+    // Step 1: create an ephemeral ECDH key at each of the sources.
+    SessionInitiationInfo source1_init_info;
+    ASSERT_EQ(OK, GetReturnError(source1->create(&source1_init_info)));
+    ASSERT_TRUE(source1_init_info.key.pubKey.has_value());
+    ASSERT_TRUE(source1_init_info.key.arcFromPBK.has_value());
+    SessionInitiationInfo source2_init_info;
+    ASSERT_EQ(OK, GetReturnError(source1->create(&source2_init_info)));
+    ASSERT_TRUE(source2_init_info.key.pubKey.has_value());
+    ASSERT_TRUE(source2_init_info.key.arcFromPBK.has_value());
+
+    // Step 2: pass each source's ECDH public key and other session info to the sink.
+    KeInitResult init1_result;
+    ASSERT_EQ(OK, GetReturnError(sink->init(source1_init_info.key.pubKey.value(),
+                                            source1_init_info.identity, source1_init_info.nonce,
+                                            source1_init_info.version, &init1_result)));
+    SessionInitiationInfo sink_init1_info = init1_result.sessionInitiationInfo;
+    ASSERT_TRUE(sink_init1_info.key.pubKey.has_value());
+
+    SessionInfo sink_info1 = init1_result.sessionInfo;
+    ASSERT_EQ((int)sink_info1.sharedKeys.size(), 2) << "Expect two symmetric keys from init()";
+    ASSERT_GT((int)sink_info1.sessionId.size(), 0) << "Expect non-empty session ID from sink";
+    std::vector<uint8_t> sink_signing_key1 = SigningKeyFromIdentity(sink_init1_info.identity);
+    CheckSignature(sink_signing_key1, sink_info1.sessionId, sink_info1.signature);
+
+    KeInitResult init2_result;
+    ASSERT_EQ(OK, GetReturnError(sink->init(source2_init_info.key.pubKey.value(),
+                                            source2_init_info.identity, source2_init_info.nonce,
+                                            source2_init_info.version, &init2_result)));
+    SessionInitiationInfo sink_init2_info = init2_result.sessionInitiationInfo;
+    ASSERT_TRUE(sink_init2_info.key.pubKey.has_value());
+
+    SessionInfo sink_info2 = init2_result.sessionInfo;
+    ASSERT_EQ((int)sink_info2.sharedKeys.size(), 2) << "Expect two symmetric keys from init()";
+    ASSERT_GT((int)sink_info2.sessionId.size(), 0) << "Expect non-empty session ID from sink";
+    std::vector<uint8_t> sink_signing_key2 = SigningKeyFromIdentity(sink_init2_info.identity);
+    CheckSignature(sink_signing_key2, sink_info2.sessionId, sink_info2.signature);
+
+    // Step 3: pass the sink's ECDH public keys and other session info to the each of the sources.
+    SessionInfo source1_info;
+    ASSERT_EQ(OK, GetReturnError(source1->finish(sink_init1_info.key.pubKey.value(),
+                                                 sink_init1_info.identity, sink_info1.signature,
+                                                 sink_init1_info.nonce, sink_init1_info.version,
+                                                 source1_init_info.key, &source1_info)));
+    ASSERT_EQ((int)source1_info.sharedKeys.size(), 2) << "Expect two symmetric keys from finsh()";
+    ASSERT_GT((int)source1_info.sessionId.size(), 0) << "Expect non-empty session ID from source";
+    std::vector<uint8_t> source1_signing_key = SigningKeyFromIdentity(source1_init_info.identity);
+    CheckSignature(source1_signing_key, source1_info.sessionId, source1_info.signature);
+
+    SessionInfo source2_info;
+    ASSERT_EQ(OK, GetReturnError(source2->finish(sink_init2_info.key.pubKey.value(),
+                                                 sink_init2_info.identity, sink_info2.signature,
+                                                 sink_init2_info.nonce, sink_init2_info.version,
+                                                 source2_init_info.key, &source2_info)));
+    ASSERT_EQ((int)source2_info.sharedKeys.size(), 2) << "Expect two symmetric keys from finsh()";
+    ASSERT_GT((int)source2_info.sessionId.size(), 0) << "Expect non-empty session ID from source";
+    std::vector<uint8_t> source2_signing_key = SigningKeyFromIdentity(source2_init_info.identity);
+    CheckSignature(source2_signing_key, source2_info.sessionId, source2_info.signature);
+
+    // Both ends should agree on the session ID.
+    ASSERT_EQ(source1_info.sessionId, sink_info1.sessionId);
+    ASSERT_EQ(source2_info.sessionId, sink_info2.sessionId);
+
+    // Step 4: pass the each source's session ID info back to the sink, so it can check it and
+    // update the symmetric keys so they're marked as authentication complete.
+    std::array<Arc, 2> auth_complete_result1;
+    ASSERT_EQ(OK, GetReturnError(sink->authenticationComplete(
+                          source1_info.signature, sink_info1.sharedKeys, &auth_complete_result1)));
+    ASSERT_EQ((int)auth_complete_result1.size(), 2)
+            << "Expect two symmetric keys from authComplete()";
+    sink_info1.sharedKeys = auth_complete_result1;
+    std::array<Arc, 2> auth_complete_result2;
+    ASSERT_EQ(OK, GetReturnError(sink->authenticationComplete(
+                          source2_info.signature, sink_info2.sharedKeys, &auth_complete_result2)));
+    ASSERT_EQ((int)auth_complete_result2.size(), 2)
+            << "Expect two symmetric keys from authComplete()";
+    sink_info2.sharedKeys = auth_complete_result2;
+}
+
+TEST_P(AuthGraphSessionTest, FreshNonces) {
+    std::shared_ptr<IAuthGraphKeyExchange> source = authNode_;
+    std::shared_ptr<IAuthGraphKeyExchange> sink = authNode_;
+
+    SessionInitiationInfo source_init_info1;
+    ASSERT_EQ(OK, GetReturnError(source->create(&source_init_info1)));
+    SessionInitiationInfo source_init_info2;
+    ASSERT_EQ(OK, GetReturnError(source->create(&source_init_info2)));
+
+    // Two calls to create() should result in the same identity but different nonce values.
+    ASSERT_EQ(source_init_info1.identity, source_init_info2.identity);
+    ASSERT_NE(source_init_info1.nonce, source_init_info2.nonce);
+    ASSERT_NE(source_init_info1.key.pubKey, source_init_info2.key.pubKey);
+    ASSERT_NE(source_init_info1.key.arcFromPBK, source_init_info2.key.arcFromPBK);
+
+    KeInitResult init_result1;
+    ASSERT_EQ(OK, GetReturnError(sink->init(source_init_info1.key.pubKey.value(),
+                                            source_init_info1.identity, source_init_info1.nonce,
+                                            source_init_info1.version, &init_result1)));
+    KeInitResult init_result2;
+    ASSERT_EQ(OK, GetReturnError(sink->init(source_init_info2.key.pubKey.value(),
+                                            source_init_info2.identity, source_init_info2.nonce,
+                                            source_init_info2.version, &init_result2)));
+
+    // Two calls to init() should result in the same identity buf different nonces and session IDs.
+    ASSERT_EQ(init_result1.sessionInitiationInfo.identity,
+              init_result2.sessionInitiationInfo.identity);
+    ASSERT_NE(init_result1.sessionInitiationInfo.nonce, init_result2.sessionInitiationInfo.nonce);
+    ASSERT_NE(init_result1.sessionInfo.sessionId, init_result2.sessionInfo.sessionId);
+}
+
+INSTANTIATE_TEST_SUITE_P(PerInstance, AuthGraphSessionTest,
+                         testing::ValuesIn(AuthGraphSessionTest::build_params()),
+                         ::android::PrintInstanceNameToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AuthGraphSessionTest);
+
+}  // namespace aidl::android::hardware::security::authgraph::test
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    return RUN_ALL_TESTS();
+}
diff --git a/security/authgraph/default/Android.bp b/security/authgraph/default/Android.bp
new file mode 100644
index 0000000..9de3bc1
--- /dev/null
+++ b/security/authgraph/default/Android.bp
@@ -0,0 +1,46 @@
+//
+// Copyright (C) 2023 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_interfaces_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+rust_binary {
+    name: "android.hardware.security.authgraph-service.nonsecure",
+    relative_install_path: "hw",
+    vendor: true,
+    init_rc: ["authgraph.rc"],
+    vintf_fragments: ["authgraph.xml"],
+    defaults: [
+        "authgraph_use_latest_hal_aidl_rust",
+    ],
+    rustlibs: [
+        "libandroid_logger",
+        "libauthgraph_core",
+        "libauthgraph_boringssl",
+        "libauthgraph_hal",
+        "libbinder_rs",
+        "liblibc",
+        "liblog_rust",
+    ],
+    srcs: [
+        "src/main.rs",
+    ],
+}
diff --git a/security/authgraph/default/authgraph.rc b/security/authgraph/default/authgraph.rc
new file mode 100644
index 0000000..0222994
--- /dev/null
+++ b/security/authgraph/default/authgraph.rc
@@ -0,0 +1,5 @@
+service vendor.authgraph /vendor/bin/hw/android.hardware.security.authgraph-service.nonsecure
+    interface aidl android.hardware.security.authgraph.IAuthGraph/nonsecure
+    class hal
+    user nobody
+    group nobody
diff --git a/security/authgraph/default/authgraph.xml b/security/authgraph/default/authgraph.xml
new file mode 100644
index 0000000..9529a0a
--- /dev/null
+++ b/security/authgraph/default/authgraph.xml
@@ -0,0 +1,10 @@
+<manifest version="1.0" type="device">
+    <hal format="aidl">
+        <name>android.hardware.security.authgraph</name>
+        <version>1</version>
+        <interface>
+            <name>IAuthGraphKeyExchange</name>
+            <instance>nonsecure</instance>
+        </interface>
+    </hal>
+</manifest>
diff --git a/security/authgraph/default/src/main.rs b/security/authgraph/default/src/main.rs
new file mode 100644
index 0000000..2112e58
--- /dev/null
+++ b/security/authgraph/default/src/main.rs
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+//! Default implementation of the AuthGraph key exchange HAL.
+//!
+//! This implementation of the HAL is only intended to allow testing and policy compliance.  A real
+//! implementation of the AuthGraph HAL would be implemented in a secure environment, and would not
+//! be independently registered with service manager (a secure component that uses AuthGraph would
+//! expose an entrypoint that allowed retrieval of the specific IAuthGraphKeyExchange instance that
+//! is correlated with the component).
+
+use android_hardware_security_authgraph::aidl::android::hardware::security::authgraph::{
+    Arc::Arc, IAuthGraphKeyExchange::BnAuthGraphKeyExchange,
+    IAuthGraphKeyExchange::IAuthGraphKeyExchange, Identity::Identity, KeInitResult::KeInitResult,
+    Key::Key, PubKey::PubKey, SessionIdSignature::SessionIdSignature, SessionInfo::SessionInfo,
+    SessionInitiationInfo::SessionInitiationInfo,
+};
+use authgraph_boringssl as boring;
+use authgraph_core::{key::MillisecondsSinceEpoch, keyexchange as ke, traits};
+use authgraph_hal::{err_to_binder, Innto, TryInnto};
+use log::{error, info};
+use std::ffi::CString;
+use std::sync::Mutex;
+
+static SERVICE_NAME: &str = "android.hardware.security.authgraph.IAuthGraphKeyExchange";
+static SERVICE_INSTANCE: &str = "nonsecure";
+
+/// Local error type for failures in the HAL service.
+#[derive(Debug, Clone)]
+struct HalServiceError(String);
+
+impl From<String> for HalServiceError {
+    fn from(s: String) -> Self {
+        Self(s)
+    }
+}
+
+fn main() {
+    if let Err(e) = inner_main() {
+        panic!("HAL service failed: {:?}", e);
+    }
+}
+
+fn inner_main() -> Result<(), HalServiceError> {
+    // Initialize Android logging.
+    android_logger::init_once(
+        android_logger::Config::default()
+            .with_tag("authgraph-hal-nonsecure")
+            .with_min_level(log::Level::Info)
+            .with_log_id(android_logger::LogId::System),
+    );
+    // Redirect panic messages to logcat.
+    std::panic::set_hook(Box::new(|panic_info| {
+        error!("{}", panic_info);
+    }));
+
+    info!("Insecure AuthGraph key exchange HAL service is starting.");
+
+    info!("Starting thread pool now.");
+    binder::ProcessState::start_thread_pool();
+
+    // Register the service
+    let service = AuthGraphService::new_as_binder();
+    let service_name = format!("{}/{}", SERVICE_NAME, SERVICE_INSTANCE);
+    binder::add_service(&service_name, service.as_binder()).map_err(|e| {
+        format!(
+            "Failed to register service {} because of {:?}.",
+            service_name, e
+        )
+    })?;
+
+    info!("Successfully registered AuthGraph HAL services.");
+    binder::ProcessState::join_thread_pool();
+    info!("AuthGraph HAL service is terminating."); // should not reach here
+    Ok(())
+}
+
+/// Non-secure implementation of the AuthGraph key exchange service.
+struct AuthGraphService {
+    imp: Mutex<traits::TraitImpl>,
+}
+
+impl AuthGraphService {
+    /// Create a new instance.
+    fn new() -> Self {
+        Self {
+            imp: Mutex::new(traits::TraitImpl {
+                aes_gcm: Box::new(boring::BoringAes),
+                ecdh: Box::new(boring::BoringEcDh),
+                ecdsa: Box::new(boring::BoringEcDsa),
+                hmac: Box::new(boring::BoringHmac),
+                hkdf: Box::new(boring::BoringHkdf),
+                sha256: Box::new(boring::BoringSha256),
+                rng: Box::new(boring::BoringRng),
+                device: Box::<boring::test_device::AgDevice>::default(),
+                clock: Some(Box::new(StdClock)),
+            }),
+        }
+    }
+
+    /// Create a new instance wrapped in a proxy object.
+    pub fn new_as_binder() -> binder::Strong<dyn IAuthGraphKeyExchange> {
+        BnAuthGraphKeyExchange::new_binder(Self::new(), binder::BinderFeatures::default())
+    }
+}
+
+impl binder::Interface for AuthGraphService {}
+
+/// Extract (and require) an unsigned public key as bytes from a [`PubKey`].
+fn unsigned_pub_key(pub_key: &PubKey) -> binder::Result<&[u8]> {
+    match pub_key {
+        PubKey::PlainKey(key) => Ok(&key.plainPubKey),
+        PubKey::SignedKey(_) => Err(binder::Status::new_exception(
+            binder::ExceptionCode::ILLEGAL_ARGUMENT,
+            Some(&CString::new("expected unsigned public key").unwrap()),
+        )),
+    }
+}
+
+/// This nonsecure implementation of the AuthGraph HAL interface directly calls the AuthGraph
+/// reference implementation library code; a real implementation requires the AuthGraph
+/// code to run in a secure environment, not within Android.
+impl IAuthGraphKeyExchange for AuthGraphService {
+    fn create(&self) -> binder::Result<SessionInitiationInfo> {
+        info!("create()");
+        let mut imp = self.imp.lock().unwrap();
+        let info = ke::create(&mut *imp).map_err(err_to_binder)?;
+        Ok(info.innto())
+    }
+    fn init(
+        &self,
+        peer_pub_key: &PubKey,
+        peer_id: &Identity,
+        peer_nonce: &[u8],
+        peer_version: i32,
+    ) -> binder::Result<KeInitResult> {
+        info!("init(v={peer_version})");
+        let mut imp = self.imp.lock().unwrap();
+        let peer_pub_key = unsigned_pub_key(peer_pub_key)?;
+        let result = ke::init(
+            &mut *imp,
+            peer_pub_key,
+            &peer_id.identity,
+            &peer_nonce,
+            peer_version,
+        )
+        .map_err(err_to_binder)?;
+        Ok(result.innto())
+    }
+
+    fn finish(
+        &self,
+        peer_pub_key: &PubKey,
+        peer_id: &Identity,
+        peer_signature: &SessionIdSignature,
+        peer_nonce: &[u8],
+        peer_version: i32,
+        own_key: &Key,
+    ) -> binder::Result<SessionInfo> {
+        info!("finish(v={peer_version})");
+        let mut imp = self.imp.lock().unwrap();
+        let peer_pub_key = unsigned_pub_key(peer_pub_key)?;
+        let own_key: Key = own_key.clone();
+        let own_key: authgraph_core::key::Key = own_key.try_innto()?;
+        let session_info = ke::finish(
+            &mut *imp,
+            peer_pub_key,
+            &peer_id.identity,
+            &peer_signature.signature,
+            &peer_nonce,
+            peer_version,
+            own_key,
+        )
+        .map_err(err_to_binder)?;
+        Ok(session_info.innto())
+    }
+
+    fn authenticationComplete(
+        &self,
+        peer_signature: &SessionIdSignature,
+        shared_keys: &[Arc; 2],
+    ) -> binder::Result<[Arc; 2]> {
+        info!("authComplete()");
+        let mut imp = self.imp.lock().unwrap();
+        let shared_keys = [shared_keys[0].arc.clone(), shared_keys[1].arc.clone()];
+        let arcs = ke::authentication_complete(&mut *imp, &peer_signature.signature, shared_keys)
+            .map_err(err_to_binder)?;
+        Ok(arcs.map(|arc| Arc { arc }))
+    }
+}
+
+/// Monotonic clock.
+#[derive(Default)]
+pub struct StdClock;
+
+impl traits::MonotonicClock for StdClock {
+    fn now(&self) -> authgraph_core::key::MillisecondsSinceEpoch {
+        let mut time = libc::timespec {
+            tv_sec: 0,  // libc::time_t
+            tv_nsec: 0, // libc::c_long
+        };
+        let rc =
+        // Safety: `time` is a valid structure.
+            unsafe { libc::clock_gettime(libc::CLOCK_BOOTTIME, &mut time as *mut libc::timespec) };
+        if rc < 0 {
+            log::warn!("failed to get time!");
+            return MillisecondsSinceEpoch(0);
+        }
+        // The types in `libc::timespec` may be different on different architectures,
+        // so allow conversion to `i64`.
+        #[allow(clippy::unnecessary_cast)]
+        MillisecondsSinceEpoch((time.tv_sec as i64 * 1000) + (time.tv_nsec as i64 / 1000 / 1000))
+    }
+}
diff --git a/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl b/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl
index 36f0106..aa7bf28 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl
@@ -643,6 +643,8 @@
      * Tag::ATTESTATION_CHALLENGE is used to deliver a "challenge" value to the attested key
      * generation/import methods, which must place the value in the KeyDescription SEQUENCE of the
      * attestation extension.
+     * The challenge value may be up to 128 bytes. If the caller provides a bigger challenge,
+     * INVALID_INPUT_LENGTH error should be returned.
      *
      * Must never appear in KeyCharacteristics.
      */
diff --git a/sensors/aidl/vts/VtsAidlHalSensorsTargetTest.cpp b/sensors/aidl/vts/VtsAidlHalSensorsTargetTest.cpp
index 618acbb..be11b87 100644
--- a/sensors/aidl/vts/VtsAidlHalSensorsTargetTest.cpp
+++ b/sensors/aidl/vts/VtsAidlHalSensorsTargetTest.cpp
@@ -41,6 +41,7 @@
 using aidl::android::hardware::sensors::SensorInfo;
 using aidl::android::hardware::sensors::SensorStatus;
 using aidl::android::hardware::sensors::SensorType;
+using aidl::android::hardware::sensors::AdditionalInfo;
 using android::ProcessState;
 using std::chrono::duration_cast;
 
@@ -629,6 +630,15 @@
     Event additionalInfoEvent;
     additionalInfoEvent.sensorType = SensorType::ADDITIONAL_INFO;
     additionalInfoEvent.timestamp = android::elapsedRealtimeNano();
+    AdditionalInfo info;
+    info.type = AdditionalInfo::AdditionalInfoType::AINFO_BEGIN;
+    info.serial = 1;
+    AdditionalInfo::AdditionalInfoPayload::Int32Values infoData;
+    for (int32_t i = 0; i < 14; i++) {
+        infoData.values[i] = i;
+    }
+    info.payload.set<AdditionalInfo::AdditionalInfoPayload::Tag::dataInt32>(infoData);
+    additionalInfoEvent.payload.set<Event::EventPayload::Tag::additional>(info);
 
     Event injectedEvent;
     injectedEvent.timestamp = android::elapsedRealtimeNano();
diff --git a/tv/tuner/aidl/vts/functional/FilterTests.cpp b/tv/tuner/aidl/vts/functional/FilterTests.cpp
index 53afef7..533d0e6 100644
--- a/tv/tuner/aidl/vts/functional/FilterTests.cpp
+++ b/tv/tuner/aidl/vts/functional/FilterTests.cpp
@@ -305,13 +305,18 @@
     ndk::ScopedAStatus status;
 
     status = mFilters[filterId]->configureMonitorEvent(monitorEventTypes);
+    return AssertionResult(status.isOk());
+}
+
+AssertionResult FilterTests::testMonitorEvent(uint64_t filterId, uint32_t monitorEventTypes) {
+    EXPECT_TRUE(mFilterCallbacks[filterId]) << "Test with getNewlyOpenedFilterId first.";
     if (monitorEventTypes & static_cast<int32_t>(DemuxFilterMonitorEventType::SCRAMBLING_STATUS)) {
         mFilterCallbacks[filterId]->testFilterScramblingEvent();
     }
     if (monitorEventTypes & static_cast<int32_t>(DemuxFilterMonitorEventType::IP_CID_CHANGE)) {
         mFilterCallbacks[filterId]->testFilterIpCidEvent();
     }
-    return AssertionResult(status.isOk());
+    return AssertionResult(true);
 }
 
 AssertionResult FilterTests::startIdTest(int64_t filterId) {
diff --git a/tv/tuner/aidl/vts/functional/FilterTests.h b/tv/tuner/aidl/vts/functional/FilterTests.h
index f579441..f57093e 100644
--- a/tv/tuner/aidl/vts/functional/FilterTests.h
+++ b/tv/tuner/aidl/vts/functional/FilterTests.h
@@ -124,6 +124,7 @@
     AssertionResult configAvFilterStreamType(AvStreamType type, int64_t filterId);
     AssertionResult configIpFilterCid(int32_t ipCid, int64_t filterId);
     AssertionResult configureMonitorEvent(int64_t filterId, int32_t monitorEventTypes);
+    AssertionResult testMonitorEvent(uint64_t filterId, uint32_t monitorEventTypes);
     AssertionResult getFilterMQDescriptor(int64_t filterId, bool getMqDesc);
     AssertionResult startFilter(int64_t filterId);
     AssertionResult stopFilter(int64_t filterId);
diff --git a/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.cpp b/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.cpp
index 9db82c8..3664b6c 100644
--- a/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.cpp
+++ b/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.cpp
@@ -60,6 +60,11 @@
     }
     ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId, filterConf.getMqDesc));
     ASSERT_TRUE(mFilterTests.startFilter(filterId));
+    ASSERT_TRUE(mFrontendTests.tuneFrontend(frontendConf, true /*testWithDemux*/));
+    if (filterConf.monitorEventTypes > 0) {
+        ASSERT_TRUE(mFilterTests.testMonitorEvent(filterId, filterConf.monitorEventTypes));
+    }
+    ASSERT_TRUE(mFrontendTests.stopTuneFrontend(true /*testWithDemux*/));
     ASSERT_TRUE(mFilterTests.stopFilter(filterId));
     ASSERT_TRUE(mFilterTests.closeFilter(filterId));
     ASSERT_TRUE(mDemuxTests.closeDemux());