Merge "Add changes to Radio V1 AIDL interfaces" into tm-dev
diff --git a/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp b/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp
index f25c391..dfc2386 100644
--- a/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp
@@ -715,7 +715,7 @@
             sink.base.channelMask.value(getConfig().base.channelMask);
             sink.ext.mix({});
             sink.ext.mix().ioHandle = helper.getIoHandle();
-            sink.ext.mix().useCase.source(toString(xsd::AudioSource::AUDIO_SOURCE_MIC));
+            sink.ext.mix().useCase.source(initMetadata.tracks[0].source);
             EXPECT_OK(getDevice()->createAudioPatch(hidl_vec<AudioPortConfig>{source},
                                                     hidl_vec<AudioPortConfig>{sink},
                                                     returnIn(res, mPatchHandle)));
diff --git a/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h b/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
index 38d6eff..38e9e5f 100644
--- a/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
+++ b/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
@@ -1239,23 +1239,30 @@
     : public OpenStreamTest<::android::hardware::audio::CORE_TYPES_CPP_VERSION::IStreamIn> {
     void SetUp() override {
         ASSERT_NO_FATAL_FAILURE(OpenStreamTest::SetUp());  // setup base
+        auto flags = getInputFlags();
 #if MAJOR_VERSION <= 6
         address.device = AudioDevice::IN_DEFAULT;
 #elif MAJOR_VERSION >= 7
         auto maybeSourceAddress = getCachedPolicyConfig().getSourceDeviceForMixPort(
                 getDeviceName(), getMixPortName());
+        auto& metadata = initMetadata.tracks[0];
         if (maybeSourceAddress.has_value() &&
             !xsd::isTelephonyDevice(maybeSourceAddress.value().deviceType)) {
             address = maybeSourceAddress.value();
-            auto& metadata = initMetadata.tracks[0];
             metadata.source = toString(xsd::AudioSource::AUDIO_SOURCE_UNPROCESSED);
             metadata.channelMask = getConfig().base.channelMask;
         } else {
             address.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_IN_DEFAULT);
         }
-#endif
+#if MAJOR_VERSION == 7 && MINOR_VERSION >= 1
+        auto flagsIt = std::find(flags.begin(), flags.end(),
+                                 toString(xsd::AudioInOutFlag::AUDIO_INPUT_FLAG_ULTRASOUND));
+        if (flagsIt != flags.end()) {
+            metadata.source = toString(xsd::AudioSource::AUDIO_SOURCE_ULTRASOUND);
+        }
+#endif  // 7.1
+#endif  // MAJOR_VERSION >= 7
         const AudioConfig& config = getConfig();
-        auto flags = getInputFlags();
         testOpen(
                 [&](AudioIoHandle handle, AudioConfig config, auto cb) {
                     return getDevice()->openInputStream(handle, address, config, flags,
diff --git a/audio/effect/all-versions/default/Android.bp b/audio/effect/all-versions/default/Android.bp
index 1e01ffb..a3c3ed6 100644
--- a/audio/effect/all-versions/default/Android.bp
+++ b/audio/effect/all-versions/default/Android.bp
@@ -30,6 +30,7 @@
     ],
 
     shared_libs: [
+        "libaudioutils",
         "libbase",
         "libcutils",
         "libeffects",
@@ -48,6 +49,7 @@
         "libeffects_headers",
         "libhardware_headers",
         "libmedia_headers",
+        "libmediautils_headers",
     ],
 }
 
diff --git a/audio/effect/all-versions/default/Effect.cpp b/audio/effect/all-versions/default/Effect.cpp
index 49f6bf2..3baafc9 100644
--- a/audio/effect/all-versions/default/Effect.cpp
+++ b/audio/effect/all-versions/default/Effect.cpp
@@ -22,13 +22,11 @@
 #include "Effect.h"
 #include "common/all-versions/default/EffectMap.h"
 
-#include <memory.h>
-
 #define ATRACE_TAG ATRACE_TAG_AUDIO
-
 #include <HidlUtils.h>
 #include <android/log.h>
 #include <media/EffectsFactoryApi.h>
+#include <mediautils/ScopedStatistics.h>
 #include <util/EffectUtils.h>
 #include <utils/Trace.h>
 
@@ -49,21 +47,27 @@
 
 namespace {
 
+#define SCOPED_STATS()                                                       \
+    ::android::mediautils::ScopedStatistics scopedStatistics {               \
+        std::string("EffectHal::").append(__func__), mEffectHal->mStatistics \
+    }
+
 class ProcessThread : public Thread {
    public:
     // ProcessThread's lifespan never exceeds Effect's lifespan.
-    ProcessThread(std::atomic<bool>* stop, effect_handle_t effect,
-                  std::atomic<audio_buffer_t*>* inBuffer, std::atomic<audio_buffer_t*>* outBuffer,
-                  Effect::StatusMQ* statusMQ, EventFlag* efGroup)
-        : Thread(false /*canCallJava*/),
-          mStop(stop),
-          mEffect(effect),
-          mHasProcessReverse((*mEffect)->process_reverse != NULL),
-          mInBuffer(inBuffer),
-          mOutBuffer(outBuffer),
-          mStatusMQ(statusMQ),
-          mEfGroup(efGroup) {}
-    virtual ~ProcessThread() {}
+     ProcessThread(std::atomic<bool>* stop, effect_handle_t effect,
+                   std::atomic<audio_buffer_t*>* inBuffer, std::atomic<audio_buffer_t*>* outBuffer,
+                   Effect::StatusMQ* statusMQ, EventFlag* efGroup, Effect* effectHal)
+         : Thread(false /*canCallJava*/),
+           mStop(stop),
+           mEffect(effect),
+           mHasProcessReverse((*mEffect)->process_reverse != NULL),
+           mInBuffer(inBuffer),
+           mOutBuffer(outBuffer),
+           mStatusMQ(statusMQ),
+           mEfGroup(efGroup),
+           mEffectHal(effectHal) {}
+     virtual ~ProcessThread() {}
 
    private:
     std::atomic<bool>* mStop;
@@ -73,6 +77,7 @@
     std::atomic<audio_buffer_t*>* mOutBuffer;
     Effect::StatusMQ* mStatusMQ;
     EventFlag* mEfGroup;
+    Effect* const mEffectHal;
 
     bool threadLoop() override;
 };
@@ -102,6 +107,9 @@
             audio_buffer_t* outBuffer =
                 std::atomic_load_explicit(mOutBuffer, std::memory_order_relaxed);
             if (inBuffer != nullptr && outBuffer != nullptr) {
+                // Time this effect process
+                SCOPED_STATS();
+
                 if (efState & static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_PROCESS)) {
                     processResult = (*mEffect)->process(mEffect, inBuffer, outBuffer);
                 } else {
@@ -359,7 +367,7 @@
 
     // Create and launch the thread.
     mProcessThread = new ProcessThread(&mStopProcessThread, mHandle, &mHalInBufferPtr,
-                                       &mHalOutBufferPtr, tempStatusMQ.get(), mEfGroup);
+                                       &mHalOutBufferPtr, tempStatusMQ.get(), mEfGroup, this);
     status = mProcessThread->run("effect", PRIORITY_URGENT_AUDIO);
     if (status != OK) {
         ALOGW("failed to start effect processing thread: %s", strerror(-status));
@@ -749,6 +757,8 @@
     if (fd.getNativeHandle() != nullptr && fd->numFds == 1) {
         uint32_t cmdData = fd->data[0];
         (void)sendCommand(EFFECT_CMD_DUMP, "DUMP", sizeof(cmdData), &cmdData);
+        const std::string s = mStatistics->dump();
+        if (s.size() != 0) write(cmdData, s.c_str(), s.size());
     }
     return Void();
 }
diff --git a/audio/effect/all-versions/default/Effect.h b/audio/effect/all-versions/default/Effect.h
index f9a6796..011544d 100644
--- a/audio/effect/all-versions/default/Effect.h
+++ b/audio/effect/all-versions/default/Effect.h
@@ -29,6 +29,7 @@
 #include <fmq/MessageQueue.h>
 #include <hidl/MQDescriptor.h>
 #include <hidl/Status.h>
+#include <mediautils/MethodStatistics.h>
 #include <utils/Thread.h>
 
 #include <hardware/audio_effect.h>
@@ -169,7 +170,11 @@
     Result setParameterImpl(uint32_t paramSize, const void* paramData, uint32_t valueSize,
                             const void* valueData);
 
-   private:
+    // process execution statistics
+    const std::shared_ptr<mediautils::MethodStatistics<std::string>> mStatistics =
+            std::make_shared<mediautils::MethodStatistics<std::string>>();
+
+  private:
     friend struct VirtualizerEffect;  // for getParameterImpl
     friend struct VisualizerEffect;   // to allow executing commands
 
diff --git a/automotive/evs/aidl/vts/VtsHalEvsTargetTest.cpp b/automotive/evs/aidl/vts/VtsHalEvsTargetTest.cpp
index 09e1088..9c6c573 100644
--- a/automotive/evs/aidl/vts/VtsHalEvsTargetTest.cpp
+++ b/automotive/evs/aidl/vts/VtsHalEvsTargetTest.cpp
@@ -19,9 +19,11 @@
 
 #include <aidl/Gtest.h>
 #include <aidl/Vintf.h>
+#include <aidl/android/hardware/automotive/evs/BnEvsEnumeratorStatusCallback.h>
 #include <aidl/android/hardware/automotive/evs/BufferDesc.h>
 #include <aidl/android/hardware/automotive/evs/CameraDesc.h>
 #include <aidl/android/hardware/automotive/evs/CameraParam.h>
+#include <aidl/android/hardware/automotive/evs/DeviceStatus.h>
 #include <aidl/android/hardware/automotive/evs/DisplayDesc.h>
 #include <aidl/android/hardware/automotive/evs/DisplayState.h>
 #include <aidl/android/hardware/automotive/evs/EvsEventDesc.h>
@@ -30,6 +32,7 @@
 #include <aidl/android/hardware/automotive/evs/IEvsCamera.h>
 #include <aidl/android/hardware/automotive/evs/IEvsDisplay.h>
 #include <aidl/android/hardware/automotive/evs/IEvsEnumerator.h>
+#include <aidl/android/hardware/automotive/evs/IEvsEnumeratorStatusCallback.h>
 #include <aidl/android/hardware/automotive/evs/IEvsUltrasonicsArray.h>
 #include <aidl/android/hardware/automotive/evs/ParameterRange.h>
 #include <aidl/android/hardware/automotive/evs/Stream.h>
@@ -77,11 +80,11 @@
 } RawStreamConfig;
 constexpr size_t kStreamCfgSz = sizeof(RawStreamConfig) / sizeof(int32_t);
 
-}  // namespace
-
+using ::aidl::android::hardware::automotive::evs::BnEvsEnumeratorStatusCallback;
 using ::aidl::android::hardware::automotive::evs::BufferDesc;
 using ::aidl::android::hardware::automotive::evs::CameraDesc;
 using ::aidl::android::hardware::automotive::evs::CameraParam;
+using ::aidl::android::hardware::automotive::evs::DeviceStatus;
 using ::aidl::android::hardware::automotive::evs::DisplayDesc;
 using ::aidl::android::hardware::automotive::evs::DisplayState;
 using ::aidl::android::hardware::automotive::evs::EvsEventDesc;
@@ -90,6 +93,7 @@
 using ::aidl::android::hardware::automotive::evs::IEvsCamera;
 using ::aidl::android::hardware::automotive::evs::IEvsDisplay;
 using ::aidl::android::hardware::automotive::evs::IEvsEnumerator;
+using ::aidl::android::hardware::automotive::evs::IEvsEnumeratorStatusCallback;
 using ::aidl::android::hardware::automotive::evs::IEvsUltrasonicsArray;
 using ::aidl::android::hardware::automotive::evs::ParameterRange;
 using ::aidl::android::hardware::automotive::evs::Stream;
@@ -99,6 +103,8 @@
 using ::aidl::android::hardware::graphics::common::PixelFormat;
 using std::chrono_literals::operator""s;
 
+}  // namespace
+
 // The main test class for EVS
 class EvsAidlTest : public ::testing::TestWithParam<std::string> {
   public:
@@ -239,6 +245,13 @@
         return targetCfg;
     }
 
+    class DeviceStatusCallback : public BnEvsEnumeratorStatusCallback {
+        ndk::ScopedAStatus deviceStatusChanged(const std::vector<DeviceStatus>&) override {
+            // This empty implementation returns always ok().
+            return ndk::ScopedAStatus::ok();
+        }
+    };
+
     // Every test needs access to the service
     std::shared_ptr<IEvsEnumerator> mEnumerator;
     // Empty unless/util loadCameraList() is called
@@ -528,7 +541,7 @@
         // Ask for a very large number of buffers in flight to ensure it errors correctly
         auto badResult = pCam->setMaxFramesInFlight(std::numeric_limits<int32_t>::max());
         EXPECT_TRUE(!badResult.isOk() && badResult.getServiceSpecificError() ==
-                                                 static_cast<int>(EvsResult::INVALID_ARG));
+                                                 static_cast<int>(EvsResult::BUFFER_NOT_AVAILABLE));
 
         // Now ask for exactly two buffers in flight as we'll test behavior in that case
         ASSERT_TRUE(pCam->setMaxFramesInFlight(kBuffersToHold).isOk());
@@ -2064,6 +2077,20 @@
     }
 }
 
+TEST_P(EvsAidlTest, DeviceStatusCallbackRegistration) {
+    std::shared_ptr<IEvsEnumeratorStatusCallback> cb =
+            ndk::SharedRefBase::make<DeviceStatusCallback>();
+    ndk::ScopedAStatus status = mEnumerator->registerStatusCallback(cb);
+    if (mIsHwModule) {
+        ASSERT_TRUE(status.isOk());
+    } else {
+        // A callback registration may fail if a HIDL EVS HAL implementation is
+        // running.
+        ASSERT_TRUE(status.isOk() ||
+                    status.getServiceSpecificError() == static_cast<int>(EvsResult::NOT_SUPPORTED));
+    }
+}
+
 /*
  * UltrasonicsArrayOpenClean:
  * Opens each ultrasonics arrays reported by the enumerator and then explicitly closes it via a
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp b/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
index 7b3de58..b64c1a6 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
@@ -995,11 +995,15 @@
 template <class CallbackType, class RequestType>
 FakeVehicleHardware::PendingRequestHandler<CallbackType, RequestType>::PendingRequestHandler(
         FakeVehicleHardware* hardware)
-    : mHardware(hardware), mThread([this] {
-          while (mRequests.waitForItems()) {
-              handleRequestsOnce();
-          }
-      }) {}
+    : mHardware(hardware) {
+    // Don't initialize mThread in initialization list because mThread depends on mRequests and we
+    // want mRequests to be initialized first.
+    mThread = std::thread([this] {
+        while (mRequests.waitForItems()) {
+            handleRequestsOnce();
+        }
+    });
+}
 
 template <class CallbackType, class RequestType>
 void FakeVehicleHardware::PendingRequestHandler<CallbackType, RequestType>::addRequest(
diff --git a/bluetooth/audio/aidl/default/LeAudioSoftwareAudioProvider.cpp b/bluetooth/audio/aidl/default/LeAudioSoftwareAudioProvider.cpp
index 911c928..c16ff54 100644
--- a/bluetooth/audio/aidl/default/LeAudioSoftwareAudioProvider.cpp
+++ b/bluetooth/audio/aidl/default/LeAudioSoftwareAudioProvider.cpp
@@ -91,17 +91,21 @@
   else if (session_type_ == SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH)
     buffer_modifier = kBufferInCount;
 
+  // 24 bit audio stream is sent as unpacked
+  int bytes_per_sample =
+      (pcm_config.bitsPerSample == 24) ? 4 : (pcm_config.bitsPerSample / 8);
+
   uint32_t data_mq_size =
       (ceil(pcm_config.sampleRateHz) / 1000) *
-      channel_mode_to_channel_count(pcm_config.channelMode) *
-      (pcm_config.bitsPerSample / 8) * (pcm_config.dataIntervalUs / 1000) *
-      buffer_modifier;
+      channel_mode_to_channel_count(pcm_config.channelMode) * bytes_per_sample *
+      (pcm_config.dataIntervalUs / 1000) * buffer_modifier;
   if (data_mq_size <= 0) {
     LOG(ERROR) << __func__ << "Unexpected audio buffer size: " << data_mq_size
                << ", SampleRateHz: " << pcm_config.sampleRateHz
                << ", ChannelMode: " << toString(pcm_config.channelMode)
                << ", BitsPerSample: "
                << static_cast<int>(pcm_config.bitsPerSample)
+               << ", BytesPerSample: " << bytes_per_sample
                << ", DataIntervalUs: " << pcm_config.dataIntervalUs
                << ", SessionType: " << toString(session_type_);
     return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp b/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp
index f3ca279..1fb0e41 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp
@@ -37,7 +37,7 @@
 namespace audio {
 
 static const PcmCapabilities kDefaultSoftwarePcmCapabilities = {
-    .sampleRateHz = {16000, 24000, 44100, 48000, 88200, 96000},
+    .sampleRateHz = {16000, 24000, 32000, 44100, 48000, 88200, 96000},
     .channelMode = {ChannelMode::MONO, ChannelMode::STEREO},
     .bitsPerSample = {16, 24, 32},
     .dataIntervalUs = {},
diff --git a/current.txt b/current.txt
index ce03b55..afde7b1 100644
--- a/current.txt
+++ b/current.txt
@@ -5,6 +5,7 @@
 
 717c17cd380bb48710dff601d1a03351d4ebc28028353d5d60489248f506523c android.hardware.tests.lazy@1.0::ILazy
 67222a2ed4071b6c232e671ce0f4be4f85c1c6fb017ec2355396adaae1fe26be android.hardware.tests.lazy@1.1::ILazy
+c1c5fbd3a81c0d190c89348eed39539c77e97fe1d8d1b9874eba56393e70c6f0 android.hardware.tests.lazy_cb@1.0::ILazyCb
 
 # HALs released in Android O
 
@@ -919,5 +920,13 @@
 ec11690878547a55eb1d6a286f83e227d8328c2cf1d069316b55b4e4084fd9a2 android.hardware.audio@7.1::IStreamOut
 786b8619580d7cfae70f02136307e141481714fcc76c6b700e655568f1bf0733 android.hardware.audio@7.1::IStreamOutLatencyModeCallback
 bfbf383768881eb06f99db76ce79135e37b2b105a90d67bf7468f8df05180bf4 android.hardware.audio@7.1::types
+1de444305084b815a1cf45b41d8bd7fa8dc960da89c2d548f38feaa662d8f310 android.hardware.wifi@1.6::IWifi
+e8cf2570d2f3d8cf7a7251e85a87cbf633d0bff3c28e1c9bbf339dea04b254fa android.hardware.wifi@1.6::IWifiChip
+e05c047de0a7f2cc8f166a1c808b78e8565ff866fb69991fc3bbfa9141871d5b android.hardware.wifi@1.6::IWifiNanIface
+b7ce2d87841585551b082fca6d099622e63b7099e0d8013f687ea1a1dc35c4dc android.hardware.wifi@1.6::IWifiNanIfaceEventCallback
+8c51742b2540b005edb16d2003b87f8e8220e113b234ddbb133f95e86837e9aa android.hardware.wifi@1.6::IWifiRttController
+537f0bcfaf9d91b3136984f5e85d6ea559771726d6624a1d17c151b9c9f4b2f9 android.hardware.wifi@1.6::IWifiRttControllerEventCallback
+1bac6a7c8136dfb0414fe5639eec115aa2d12927e64a0642a43fb53225f099b2 android.hardware.wifi@1.6::IWifiStaIface
+0a800e010e8eb6eecdfdc96f04fd2ae2f417a79a74a7c0eec3a9f539199bccd4 android.hardware.wifi@1.6::types
 
 # There will be no more HIDL HALs. Use AIDL instead.
diff --git a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
index 8f440e4..2aac337 100644
--- a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
+++ b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
@@ -2212,6 +2212,11 @@
               mGralloc->set(bufferHandle, gralloc4::MetadataType_Dataspace, vec));
     ASSERT_EQ(Error::UNSUPPORTED,
               mGralloc->set(bufferHandle, gralloc4::MetadataType_BlendMode, vec));
+
+    // Keep optional metadata types below and populate the encoded metadata vec
+    // with some arbitrary different metadata because the common gralloc4::decode*()
+    // functions do not distinguish between an empty vec and bad value.
+    ASSERT_EQ(NO_ERROR, gralloc4::encodeDataspace(Dataspace::SRGB_LINEAR, &vec));
     ASSERT_EQ(Error::UNSUPPORTED,
               mGralloc->set(bufferHandle, gralloc4::MetadataType_Smpte2086, vec));
     ASSERT_EQ(Error::UNSUPPORTED,
diff --git a/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl b/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl
index cfbf171..8b3875b 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl
@@ -18,13 +18,20 @@
 
 /**
  * ProtectedData contains the encrypted BCC and the ephemeral MAC key used to
- * authenticate the keysToSign (see keysToSignMac output argument).
+ * authenticate the keysToSign (see keysToSignMac output argument of
+ * IRemotelyProvisionedComponent.generateCertificateRequest).
  * @hide
  */
 @VintfStability
 parcelable ProtectedData {
     /**
-     * ProtectedData is a COSE_Encrypt structure, specified by the following CDDL
+     * ProtectedData is a COSE_Encrypt structure, encrypted with an AES key that is agreed upon
+     * using Elliptic-curve Diffie-Hellman. The contents of the structure are specified by the
+     * following CDDL [RFC8610].
+     *
+     * Notes:
+     *   - None of the CBOR in ProtectedData uses CBOR tags. If an implementation includes
+     *     tags, parsers may reject the data.
      *
      *     ProtectedData = [               // COSE_Encrypt
      *         protected: bstr .cbor {
@@ -34,13 +41,18 @@
      *             5 : bstr .size 12       // IV
      *         },
      *         ciphertext: bstr,           // AES-GCM-256(K, .cbor ProtectedDataPayload)
+     *                                     // Where the encryption key 'K' is derived as follows:
+     *                                     // ikm = ECDH(EEK_pub, Ephemeral_priv)
+     *                                     // salt = null
+     *                                     // info = .cbor Context (see below)
+     *                                     // K = HKDF-SHA-256(ikm, salt, info)
      *         recipients : [
      *             [                       // COSE_Recipient
      *                 protected : bstr .cbor {
      *                     1 : -25         // Algorithm : ECDH-ES + HKDF-256
      *                 },
      *                 unprotected : {
-     *                     -1 : PubKeyX25519 / PubKeyEcdhP256  // Of the sender
+     *                     -1 : PubKeyX25519 / PubKeyEcdhP256  // Ephemeral_pub
      *                     4 : bstr,       // KID : EEK ID
      *                 },
      *                 ciphertext : nil
@@ -48,14 +60,14 @@
      *         ]
      *     ]
      *
-     *     K = HKDF-256(ECDH(EEK_pub, Ephemeral_priv), Context)
-     *
-     *     Context = [                     // COSE_KDF_Context
+     *     // The COSE_KDF_Context that is used to derive the ProtectedData encryption key with
+     *     // HKDF. See details on use in ProtectedData comments above.
+     *     Context = [
      *         AlgorithmID : 3             // AES-GCM 256
      *         PartyUInfo : [
      *             identity : bstr "client"
      *             nonce : bstr .size 0,
-     *             other : bstr            // Ephemeral pubkey
+     *             other : bstr            // Ephemeral_pub
      *         ],
      *         PartyVInfo : [
      *             identity : bstr "server",
@@ -68,41 +80,53 @@
      *         ]
      *     ]
      *
+     *     // The data that is encrypted and included in ProtectedData ciphertext (see above).
      *     ProtectedDataPayload [
      *         SignedMac,
      *         Bcc,
      *         ? AdditionalDKSignatures,
      *     ]
+     *
+     *     // AdditionalDKSignatures allows the platform to provide additional certifications
+     *     // for the DK_pub. For example, this could be provided by the hardware vendor, who
+     *     // certifies all of their devices. The SignerName is a free-form string describing
+     *     // who generated the signature.
      *     AdditionalDKSignatures = {
      *         + SignerName => DKCertChain
      *     }
      *
+     *     // SignerName is a string identifier that indicates both the signing authority as
+     *     // well as the format of the DKCertChain
      *     SignerName = tstr
      *
      *     DKCertChain = [
-     *         2* Certificate                      // Root -> Leaf.  Root is the vendor
-     *                                             // self-signed cert, leaf contains DK_pub
+     *         2* X509Certificate       // Root -> ... -> Leaf. "Root" is the vendor self-signed
+     *                                  // cert, "Leaf" contains DK_pub. There may also be
+     *                                  // intermediate certificates between Root and Leaf.
      *     ]
      *
-     *     Certificate = COSE_Sign1 of a public key
+     *     // A bstr containing a DER-encoded X.509 certificate (RSA, NIST P-curve, or edDSA)
+     *     X509Certificate = bstr
      *
-     *     SignedMac = [                                  // COSE_Sign1
-     *         bstr .cbor {                               // Protected params
-     *             1 : AlgorithmEdDSA / AlgorithmES256,   // Algorithm
+     *     // The SignedMac, which authenticates the MAC key that is used to authenticate the
+     *     // keysToSign.
+     *     SignedMac = [                                // COSE_Sign1
+     *         bstr .cbor {                             // Protected params
+     *             1 : AlgorithmEdDSA / AlgorithmES256, // Algorithm
      *         },
-     *         {},                   // Unprotected params
-     *         bstr .size 32,                  // MAC key
+     *         {},                                      // Unprotected params
+     *         bstr .size 32,                           // Payload: MAC key
      *         bstr // PureEd25519(KM_priv, bstr .cbor SignedMac_structure) /
      *              // ECDSA(KM_priv, bstr .cbor SignedMac_structure)
      *     ]
      *
-     *     SignedMac_structure = [
+     *     SignedMac_structure = [                      //  COSE Sig_structure
      *         "Signature1",
-     *         bstr .cbor {                               // Protected params
-     *             1 : AlgorithmEdDSA / AlgorithmES256,   // Algorithm
+     *         bstr .cbor {                             // Protected params
+     *             1 : AlgorithmEdDSA / AlgorithmES256, // Algorithm
      *         },
-     *         bstr .cbor SignedMacAad
-     *         bstr .size 32                              // MAC key
+     *         bstr .cbor SignedMacAad,
+     *         bstr .size 32                            // MAC key
      *     ]
      *
      *     SignedMacAad = [
@@ -114,31 +138,48 @@
      *                                   // the signature.
      *     ]
      *
+     *     VerifiedDeviceInfo = DeviceInfo  // See DeviceInfo.aidl
+     *
+     *     // The BCC is the boot certificate chain, containing measurements about the device
+     *     // boot chain. The BCC generally follows the Open Profile for DICE specification at
+     *     // https://pigweed.googlesource.com/open-dice/+/HEAD/docs/specification.md.
+     *     //
+     *     // The first entry in the Bcc is the DK_pub, encoded as a COSE_key. All entries after
+     *     // the first describe a link in the boot chain (e.g. bootloaders: BL1, BL2, ... BLN).
+     *     // Note that there is no BccEntry for DK_pub, only a "bare" COSE_key.
      *     Bcc = [
      *         PubKeyEd25519 / PubKeyECDSA256, // DK_pub
      *         + BccEntry,                     // Root -> leaf (KM_pub)
      *     ]
      *
-     *     BccPayload = {                     // CWT
-     *         1 : tstr,                      // Issuer
-     *         2 : tstr,                      // Subject
-     *         // See the Open Profile for DICE for details on these fields.
-     *         ? -4670545 : bstr,             // Code Hash
-     *         ? -4670546 : bstr,             // Code Descriptor
-     *         ? -4670547 : bstr,             // Configuration Hash
-     *         ? -4670548 : bstr .cbor {      // Configuration Descriptor
-     *             ? -70002 : tstr,           // Component name
-     *             ? -70003 : int,            // Firmware version
-     *             ? -70004 : null,           // Resettable
-     *         },
-     *         ? -4670549 : bstr,             // Authority Hash
-     *         ? -4670550 : bstr,             // Authority Descriptor
-     *         ? -4670551 : bstr,             // Mode
+     *     // This is the signed payload for each entry in the Bcc. Note that the "Configuration
+     *     // Input Values" described by the Open Profile are not used here. Instead, the Bcc
+     *     // defines its own configuration values for the Configuration Descriptor field. See
+     *     // the Open Profile for DICE for more details on the fields. All hashes are SHA256.
+     *     BccPayload = {                               // CWT [RFC8392]
+     *         1 : tstr,                                // Issuer
+     *         2 : tstr,                                // Subject
      *         -4670552 : bstr .cbor PubKeyEd25519 /
-     *                    bstr .cbor PubKeyECDSA256   // Subject Public Key
-     *         -4670553 : bstr                // Key Usage
+     *                    bstr .cbor PubKeyECDSA256,    // Subject Public Key
+     *         -4670553 : bstr                          // Key Usage
+     *
+     *         // NOTE: All of the following fields may be omitted for a "Degenerate BCC", as
+     *         //       described by IRemotelyProvisionedComponent.aidl.
+     *         -4670545 : bstr,                         // Code Hash
+     *         ? -4670546 : bstr,                       // Code Descriptor
+     *         ? -4670547 : bstr,                       // Configuration Hash
+     *         -4670548 : bstr .cbor {                  // Configuration Descriptor
+     *             ? -70002 : tstr,                         // Component name
+     *             ? -70003 : int,                          // Firmware version
+     *             ? -70004 : null,                         // Resettable
+     *         },
+     *         -4670549 : bstr,                         // Authority Hash
+     *         ? -4670550 : bstr,                       // Authority Descriptor
+     *         -4670551 : bstr,                         // Mode
      *     }
      *
+     *     // Each entry in the Bcc is a BccPayload signed by the key from the previous entry
+     *     // in the Bcc array.
      *     BccEntry = [                                  // COSE_Sign1 (untagged)
      *         protected : bstr .cbor {
      *             1 : AlgorithmEdDSA / AlgorithmES256,  // Algorithm
@@ -159,8 +200,8 @@
      *         payload: bstr .cbor BccPayload
      *     ]
      *
-     *     VerifiedDeviceInfo = DeviceInfo  // See DeviceInfo.aidl
-     *
+     *     // The following section defines some types that are reused throughout the above
+     *     // data structures.
      *     PubKeyX25519 = {                 // COSE_Key
      *          1 : 1,                      // Key type : Octet Key Pair
      *         -1 : 4,                      // Curve : X25519
@@ -168,25 +209,25 @@
      *     }
      *
      *     PubKeyEd25519 = {                // COSE_Key
-     *         1 : 1,                         // Key type : octet key pair
-     *         3 : AlgorithmEdDSA,            // Algorithm : EdDSA
-     *         -1 : 6,                        // Curve : Ed25519
-     *         -2 : bstr                      // X coordinate, little-endian
+     *         1 : 1,                       // Key type : octet key pair
+     *         3 : AlgorithmEdDSA,          // Algorithm : EdDSA
+     *         -1 : 6,                      // Curve : Ed25519
+     *         -2 : bstr                    // X coordinate, little-endian
      *     }
      *
-     *     PubKeyEcdhP256 = {              // COSE_Key
-     *          1 : 2,      // Key type : EC2
-     *          -1 : 1,     // Curve : P256
-     *          -2 : bstr   // Sender X coordinate
-     *          -3 : bstr   // Sender Y coordinate
+     *     PubKeyEcdhP256 = {               // COSE_Key
+     *          1 : 2,                      // Key type : EC2
+     *          -1 : 1,                     // Curve : P256
+     *          -2 : bstr                   // Sender X coordinate
+     *          -3 : bstr                   // Sender Y coordinate
      *     }
      *
-     *     PubKeyECDSA256 = {                 // COSE_Key
-     *         1 : 2,                         // Key type : EC2
-     *         3 : AlgorithmES256,            // Algorithm : ECDSA w/ SHA-256
-     *         -1 : 1,                        // Curve: P256
-     *         -2 : bstr,                     // X coordinate
-     *         -3 : bstr                      // Y coordinate
+     *     PubKeyECDSA256 = {               // COSE_Key
+     *         1 : 2,                       // Key type : EC2
+     *         3 : AlgorithmES256,          // Algorithm : ECDSA w/ SHA-256
+     *         -1 : 1,                      // Curve: P256
+     *         -2 : bstr,                   // X coordinate
+     *         -3 : bstr                    // Y coordinate
      *     }
      *
      *     AlgorithmES256 = -7
diff --git a/security/keymint/aidl/vts/functional/AttestKeyTest.cpp b/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
index 5cdea93..240de35 100644
--- a/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
+++ b/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
@@ -743,6 +743,11 @@
 }
 
 TEST_P(AttestKeyTest, EcdsaAttestationID) {
+    if (is_gsi_image()) {
+        // GSI sets up a standard set of device identifiers that may not match
+        // the device identifiers held by the device.
+        GTEST_SKIP() << "Test not applicable under GSI";
+    }
     // Create attestation key.
     AttestationKey attest_key;
     vector<KeyCharacteristics> attest_key_characteristics;
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
index 943c692..be21994 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
@@ -17,6 +17,7 @@
 #include "KeyMintAidlTestBase.h"
 
 #include <chrono>
+#include <fstream>
 #include <unordered_set>
 #include <vector>
 
@@ -1460,6 +1461,11 @@
     OPENSSL_free(cert_issuer);
 }
 
+bool is_gsi_image() {
+    std::ifstream ifs("/system/system_ext/etc/init/init.gsi.rc");
+    return ifs.good();
+}
+
 vector<uint8_t> build_serial_blob(const uint64_t serial_int) {
     BIGNUM_Ptr serial(BN_new());
     EXPECT_TRUE(BN_set_u64(serial.get(), serial_int));
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
index 7279c95..2634ab7 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
@@ -354,6 +354,9 @@
     }
 }
 
+// Indicate whether the test is running on a GSI image.
+bool is_gsi_image();
+
 vector<uint8_t> build_serial_blob(const uint64_t serial_int);
 void verify_subject(const X509* cert, const string& subject, bool self_signed);
 void verify_serial(X509* cert, const uint64_t expected_serial);
diff --git a/security/keymint/aidl/vts/functional/KeyMintTest.cpp b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
index cbe4512..3c2bece 100644
--- a/security/keymint/aidl/vts/functional/KeyMintTest.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
@@ -1949,6 +1949,11 @@
  * attestation extension.
  */
 TEST_P(NewKeyGenerationTest, EcdsaAttestationIdTags) {
+    if (is_gsi_image()) {
+        // GSI sets up a standard set of device identifiers that may not match
+        // the device identifiers held by the device.
+        GTEST_SKIP() << "Test not applicable under GSI";
+    }
     auto challenge = "hello";
     auto app_id = "foo";
     auto subject = "cert subj 2";
@@ -7520,7 +7525,6 @@
             uint8_t privKeyData[32];
             uint8_t pubKeyData[32];
             X25519_keypair(pubKeyData, privKeyData);
-            *localPublicKey = vector<uint8_t>(pubKeyData, pubKeyData + 32);
             *localPrivKey = EVP_PKEY_Ptr(EVP_PKEY_new_raw_private_key(
                     EVP_PKEY_X25519, nullptr, privKeyData, sizeof(privKeyData)));
         } else {
@@ -7532,16 +7536,15 @@
             ASSERT_EQ(EC_KEY_generate_key(ecKey.get()), 1);
             *localPrivKey = EVP_PKEY_Ptr(EVP_PKEY_new());
             ASSERT_EQ(EVP_PKEY_set1_EC_KEY(localPrivKey->get(), ecKey.get()), 1);
-
-            // Get encoded form of the public part of the locally generated key...
-            unsigned char* p = nullptr;
-            int localPublicKeySize = i2d_PUBKEY(localPrivKey->get(), &p);
-            ASSERT_GT(localPublicKeySize, 0);
-            *localPublicKey =
-                    vector<uint8_t>(reinterpret_cast<const uint8_t*>(p),
-                                    reinterpret_cast<const uint8_t*>(p + localPublicKeySize));
-            OPENSSL_free(p);
         }
+
+        // Get encoded form of the public part of the locally generated key...
+        unsigned char* p = nullptr;
+        int localPublicKeySize = i2d_PUBKEY(localPrivKey->get(), &p);
+        ASSERT_GT(localPublicKeySize, 0);
+        *localPublicKey = vector<uint8_t>(reinterpret_cast<const uint8_t*>(p),
+                                          reinterpret_cast<const uint8_t*>(p + localPublicKeySize));
+        OPENSSL_free(p);
     }
 
     void GenerateKeyMintEcKey(EcCurve curve, EVP_PKEY_Ptr* kmPubKey) {
@@ -7636,6 +7639,9 @@
     //
     for (auto curve : ValidCurves()) {
         for (auto localCurve : ValidCurves()) {
+            SCOPED_TRACE(testing::Message()
+                         << "local-curve-" << localCurve << "-keymint-curve-" << curve);
+
             // Generate EC key locally (with access to private key material)
             EVP_PKEY_Ptr localPrivKey;
             vector<uint8_t> localPublicKey;