Audio V4: Send volume and duplicated track attr in update metadata

Only the volume of MMAP thread was previously sent and
the attributes of duplicated tracks were skipped.

Bug: 38184704
Bug: 69623109
Test: check that the HAL receives correct track metadata volume
Test: check that the HAL receives correct duplicated track metadata
Signed-off-by: Kevin Rocard <krocard@google.com>

Change-Id: I1e3b14edd8c9a5a65d2b9f4cf8660997c81c701c
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 160aa45..43a8b50 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -2623,27 +2623,33 @@
 
 void AudioFlinger::PlaybackThread::updateMetadata_l()
 {
-    // TODO: add volume support
-    if (mOutput == nullptr || mOutput->stream == nullptr ||
-            !mActiveTracks.readAndClearHasChanged()) {
-        return;
+    if (mOutput == nullptr || mOutput->stream == nullptr ) {
+        return; // That should not happen
+    }
+    bool hasChanged = mActiveTracks.readAndClearHasChanged();
+    for (const sp<Track> &track : mActiveTracks) {
+        // Do not short-circuit as all hasChanged states must be reset
+        // as all the metadata are going to be sent
+        hasChanged |= track->readAndClearHasChanged();
+    }
+    if (!hasChanged) {
+        return; // nothing to do
     }
     StreamOutHalInterface::SourceMetadata metadata;
+    auto backInserter = std::back_inserter(metadata.tracks);
     for (const sp<Track> &track : mActiveTracks) {
         // No track is invalid as this is called after prepareTrack_l in the same critical section
-        if (track->isOutputTrack()) {
-            // TODO: OutputTrack (used for duplication) are currently not supported
-            continue;
-        }
-        metadata.tracks.push_back({
-                .usage = track->attributes().usage,
-                .content_type = track->attributes().content_type,
-                .gain = 1,
-        });
+        track->copyMetadataTo(backInserter);
     }
-    mOutput->stream->updateSourceMetadata(metadata);
+    sendMetadataToBackend_l(metadata);
 }
 
+void AudioFlinger::PlaybackThread::sendMetadataToBackend_l(
+        const StreamOutHalInterface::SourceMetadata& metadata)
+{
+    mOutput->stream->updateSourceMetadata(metadata);
+};
+
 status_t AudioFlinger::PlaybackThread::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames)
 {
     if (halFrames == NULL || dspFrames == NULL) {
@@ -4381,13 +4387,19 @@
                     didModify = true;
                     // no acknowledgement required for newly active tracks
                 }
+                sp<AudioTrackServerProxy> proxy = track->mAudioTrackServerProxy;
                 // cache the combined master volume and stream type volume for fast mixer; this
                 // lacks any synchronization or barrier so VolumeProvider may read a stale value
                 const float vh = track->getVolumeHandler()->getVolume(
-                        track->mAudioTrackServerProxy->framesReleased()).first;
-                track->mCachedVolume = masterVolume
+                        proxy->framesReleased()).first;
+                float volume = masterVolume
                         * mStreamTypes[track->streamType()].volume
                         * vh;
+                track->mCachedVolume = masterVolume;
+                gain_minifloat_packed_t vlr = proxy->getVolumeLR();
+                float vlf = volume * float_from_gain(gain_minifloat_unpack_left(vlr));
+                float vrf = volume * float_from_gain(gain_minifloat_unpack_right(vlr));
+                track->setFinalVolume((vlf + vrf) / 2.f);
                 ++fastTracks;
             } else {
                 // was it previously active?
@@ -4564,6 +4576,8 @@
                 vaf = v * sendLevel * (1. / MAX_GAIN_INT);
             }
 
+            track->setFinalVolume((vrf + vlf) / 2.f);
+
             // Delegate volume control to effect in track effect chain if needed
             if (chain != 0 && chain->setVolume_l(&vl, &vr)) {
                 // Do not ramp volume if volume is controlled by effect
@@ -5096,6 +5110,7 @@
     }
 
     if (lastTrack) {
+        track->setFinalVolume((left + right) / 2.f);
         if (left != mLeftVolFloat || right != mRightVolFloat) {
             mLeftVolFloat = left;
             mRightVolFloat = right;
@@ -6153,14 +6168,12 @@
     return true;
 }
 
-void AudioFlinger::DuplicatingThread::updateMetadata_l()
+void AudioFlinger::DuplicatingThread::sendMetadataToBackend_l(
+        const StreamOutHalInterface::SourceMetadata& metadata)
 {
-    // TODO: The duplicated track metadata needs to be pushed to downstream
-    // but this information can be read at any time by the downstream threads.
-    // Taking the lock of any downstream threads is no possible due to cross deadlock risks
-    // (eg: during effect move).
-    // A lock-free structure needs to be used to shared the metadata, probably an atomic
-    // pointer to a metadata vector in each output tracks.
+    for (auto& outputTrack : outputTracks) { // not mOutputTracks
+        outputTrack->setMetadatas(metadata.tracks);
+    }
 }
 
 uint32_t AudioFlinger::DuplicatingThread::activeSleepTimeUs() const