audio: Add AudioOffloadMetadata and a method to update it

AudioOffloadMetadata contains the same information
as 'AUDIO_OFFLOAD_CODEC_*' framework parameters.
It is updated via a new method IStreamOut.updateOffloadMetadata
which only works for compressed offload streams.

Bug: 270731693
Test: atest VtsHalAudioCoreTargetTest
Change-Id: I6c8a8853f216438284082f79e3f57e511a2a1f06
Merged-In: I6c8a8853f216438284082f79e3f57e511a2a1f06
diff --git a/audio/aidl/default/Stream.cpp b/audio/aidl/default/Stream.cpp
index 49ad2f2..193c793 100644
--- a/audio/aidl/default/Stream.cpp
+++ b/audio/aidl/default/Stream.cpp
@@ -24,6 +24,7 @@
 #include "core-impl/Module.h"
 #include "core-impl/Stream.h"
 
+using aidl::android::hardware::audio::common::AudioOffloadMetadata;
 using aidl::android::hardware::audio::common::SinkMetadata;
 using aidl::android::hardware::audio::common::SourceMetadata;
 using aidl::android::media::audio::common::AudioDevice;
@@ -785,6 +786,40 @@
     LOG(DEBUG) << __func__;
 }
 
+ndk::ScopedAStatus StreamOut::updateOffloadMetadata(
+        const AudioOffloadMetadata& in_offloadMetadata) {
+    LOG(DEBUG) << __func__;
+    if (isClosed()) {
+        LOG(ERROR) << __func__ << ": stream was closed";
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+    }
+    if (!mOffloadInfo.has_value()) {
+        LOG(ERROR) << __func__ << ": not a compressed offload stream";
+        return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+    }
+    if (in_offloadMetadata.sampleRate < 0) {
+        LOG(ERROR) << __func__ << ": invalid sample rate value: " << in_offloadMetadata.sampleRate;
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+    if (in_offloadMetadata.averageBitRatePerSecond < 0) {
+        LOG(ERROR) << __func__
+                   << ": invalid average BPS value: " << in_offloadMetadata.averageBitRatePerSecond;
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+    if (in_offloadMetadata.delayFrames < 0) {
+        LOG(ERROR) << __func__
+                   << ": invalid delay frames value: " << in_offloadMetadata.delayFrames;
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+    if (in_offloadMetadata.paddingFrames < 0) {
+        LOG(ERROR) << __func__
+                   << ": invalid padding frames value: " << in_offloadMetadata.paddingFrames;
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+    mOffloadMetadata = in_offloadMetadata;
+    return ndk::ScopedAStatus::ok();
+}
+
 ndk::ScopedAStatus StreamOut::getHwVolume(std::vector<float>* _aidl_return) {
     LOG(DEBUG) << __func__;
     (void)_aidl_return;
diff --git a/audio/aidl/default/include/core-impl/Stream.h b/audio/aidl/default/include/core-impl/Stream.h
index 0d4365a3..e9b1fbb 100644
--- a/audio/aidl/default/include/core-impl/Stream.h
+++ b/audio/aidl/default/include/core-impl/Stream.h
@@ -463,6 +463,9 @@
         return StreamCommonImpl<::aidl::android::hardware::audio::common::SourceMetadata>::
                 updateMetadata(in_sourceMetadata);
     }
+    ndk::ScopedAStatus updateOffloadMetadata(
+            const ::aidl::android::hardware::audio::common::AudioOffloadMetadata&
+                    in_offloadMetadata) override;
     ndk::ScopedAStatus getHwVolume(std::vector<float>* _aidl_return) override;
     ndk::ScopedAStatus setHwVolume(const std::vector<float>& in_channelVolumes) override;
     ndk::ScopedAStatus getAudioDescriptionMixLevel(float* _aidl_return) override;
@@ -500,6 +503,7 @@
                       offloadInfo);
 
     std::optional<::aidl::android::media::audio::common::AudioOffloadInfo> mOffloadInfo;
+    std::optional<::aidl::android::hardware::audio::common::AudioOffloadMetadata> mOffloadMetadata;
 
   public:
     using CreateInstance = std::function<ndk::ScopedAStatus(