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/vts/ModuleConfig.cpp b/audio/aidl/vts/ModuleConfig.cpp
index 7b002ad..b07edb7 100644
--- a/audio/aidl/vts/ModuleConfig.cpp
+++ b/audio/aidl/vts/ModuleConfig.cpp
@@ -56,7 +56,7 @@
         offloadInfo.base.sampleRate = portConfig.sampleRate.value().value;
         offloadInfo.base.channelMask = portConfig.channelMask.value();
         offloadInfo.base.format = portConfig.format.value();
-        offloadInfo.bitRatePerSecond = 256;                                // Arbitrary value.
+        offloadInfo.bitRatePerSecond = 256000;                             // Arbitrary value.
         offloadInfo.durationUs = std::chrono::microseconds(1min).count();  // Arbitrary value.
         offloadInfo.usage = AudioUsage::MEDIA;
         offloadInfo.encapsulationMode = AudioEncapsulationMode::NONE;
diff --git a/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp b/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
index b6015ff..cd7ab0e 100644
--- a/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
@@ -53,6 +53,7 @@
 #include "TestUtils.h"
 
 using namespace android;
+using aidl::android::hardware::audio::common::AudioOffloadMetadata;
 using aidl::android::hardware::audio::common::PlaybackTrackMetadata;
 using aidl::android::hardware::audio::common::RecordTrackMetadata;
 using aidl::android::hardware::audio::common::SinkMetadata;
@@ -401,8 +402,9 @@
 // Can be used as a base for any test here, does not depend on the fixture GTest parameters.
 class AudioCoreModuleBase {
   public:
-    // The default buffer size is used mostly for negative tests.
+    // Default buffer sizes are used mostly for negative tests.
     static constexpr int kDefaultBufferSizeFrames = 256;
+    static constexpr int kDefaultLargeBufferSizeFrames = 48000;
 
     void SetUpImpl(const std::string& moduleName) {
         ASSERT_NO_FATAL_FAILURE(ConnectToService(moduleName));
@@ -2696,7 +2698,7 @@
     aidl::android::hardware::audio::core::IModule::OpenOutputStreamArguments args;
     args.portConfigId = portConfig.getId();
     args.sourceMetadata = GenerateSourceMetadata(portConfig.get());
-    args.bufferSizeFrames = kDefaultBufferSizeFrames;
+    args.bufferSizeFrames = kDefaultLargeBufferSizeFrames;
     aidl::android::hardware::audio::core::IModule::OpenOutputStreamReturn ret;
     EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->openOutputStream(args, &ret))
             << "when no offload info is provided for a compressed offload mix port";
@@ -2876,7 +2878,7 @@
         const auto portConfig = moduleConfig->getSingleConfigForMixPort(false, port);
         ASSERT_TRUE(portConfig.has_value()) << "No profiles specified for output mix port";
         WithStream<IStreamOut> stream(portConfig.value());
-        ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
+        ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultLargeBufferSizeFrames));
         bool isSupported = false;
         EXPECT_NO_FATAL_FAILURE(TestAccessors<AudioPlaybackRate>(
                 stream.get(), &IStreamOut::getPlaybackRateParameters,
@@ -2901,7 +2903,7 @@
         const auto portConfig = moduleConfig->getSingleConfigForMixPort(false, port);
         ASSERT_TRUE(portConfig.has_value()) << "No profiles specified for output mix port";
         WithStream<IStreamOut> stream(portConfig.value());
-        ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
+        ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultLargeBufferSizeFrames));
         ndk::ScopedAStatus status;
         EXPECT_STATUS(kStatuses, status = stream.get()->selectPresentation(0, 0));
         if (status.getExceptionCode() != EX_UNSUPPORTED_OPERATION) atLeastOneSupports = true;
@@ -2911,6 +2913,33 @@
     }
 }
 
+TEST_P(AudioStreamOut, UpdateOffloadMetadata) {
+    const auto offloadMixPorts =
+            moduleConfig->getOffloadMixPorts(true /*attachedOnly*/, false /*singlePort*/);
+    if (offloadMixPorts.empty()) {
+        GTEST_SKIP()
+                << "No mix port for compressed offload that could be routed to attached devices";
+    }
+    for (const auto& port : offloadMixPorts) {
+        const auto portConfig = moduleConfig->getSingleConfigForMixPort(false, port);
+        ASSERT_TRUE(portConfig.has_value()) << "No profiles specified for output mix port";
+        WithStream<IStreamOut> stream(portConfig.value());
+        ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultLargeBufferSizeFrames));
+        AudioOffloadMetadata validMetadata{
+                .sampleRate = portConfig.value().sampleRate.value().value,
+                .channelMask = portConfig.value().channelMask.value(),
+                .averageBitRatePerSecond = 256000,
+                .delayFrames = 0,
+                .paddingFrames = 0};
+        EXPECT_IS_OK(stream.get()->updateOffloadMetadata(validMetadata));
+        AudioOffloadMetadata invalidMetadata{.sampleRate = -1,
+                                             .averageBitRatePerSecond = -1,
+                                             .delayFrames = -1,
+                                             .paddingFrames = -1};
+        EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, stream.get()->updateOffloadMetadata(invalidMetadata));
+    }
+}
+
 class StreamLogicDefaultDriver : public StreamLogicDriver {
   public:
     StreamLogicDefaultDriver(std::shared_ptr<StateSequence> commands, size_t frameSizeBytes)