Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 12381092 authored by Kevin Rocard's avatar Kevin Rocard
Browse files

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

The original patch was breaking the fast track volume, so it was
reverted.
In order to fix the original patch, revert the revert and in the
following patch apply the fix.
This makes review easier as only the difference to the original patch
will be present.

Bug: 38184704
Bug: 69623109
Bug: 77892019
Test: Patch already tested for original patch and is tested for following
      patch that fixes this patch.
This reverts commit 80ee2722.
Change-Id: I06914911c2435df167fff05ce5ca40dd1ed90f39
parent 80ee2722
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -19,8 +19,11 @@
#define ANDROID_AUDIO_FLINGER_H

#include "Configuration.h"
#include <atomic>
#include <mutex>
#include <deque>
#include <map>
#include <vector>
#include <stdint.h>
#include <sys/types.h>
#include <limits.h>
+40 −1
Original line number Diff line number Diff line
@@ -93,6 +93,23 @@ public:
                                const sp<media::VolumeShaper::Operation>& operation);
    sp<media::VolumeShaper::State> getVolumeShaperState(int id);
    sp<media::VolumeHandler>   getVolumeHandler() { return mVolumeHandler; }
    /** Set the computed normalized final volume of the track.
     * !masterMute * masterVolume * streamVolume * averageLRVolume */
    void                setFinalVolume(float volume);
    float               getFinalVolume() const { return mFinalVolume; }

    /** @return true if the track has changed (metadata or volume) since
     *          the last time this function was called,
     *          true if this function was never called since the track creation,
     *          false otherwise.
     *  Thread safe.
     */
    bool            readAndClearHasChanged() { return !mChangeNotified.test_and_set(); }

    using SourceMetadatas = std::vector<playback_track_metadata_t>;
    using MetadataInserter = std::back_insert_iterator<SourceMetadatas>;
    /** Copy the track metadata in the provided iterator. Thread safe. */
    virtual void    copyMetadataTo(MetadataInserter& backInserter) const;

protected:
    // for numerous
@@ -133,6 +150,8 @@ protected:
    bool presentationComplete(int64_t framesWritten, size_t audioHalFrames);
    void signalClientFlag(int32_t flag);

    /** Set that a metadata has changed and needs to be notified to backend. Thread safe. */
    void setMetadataHasChanged() { mChangeNotified.clear(); }
public:
    void triggerEvents(AudioSystem::sync_event_t type);
    virtual void invalidate();
@@ -182,10 +201,13 @@ private:
    volatile float      mCachedVolume;  // combined master volume and stream type volume;
                                        // 'volatile' means accessed without lock or
                                        // barrier, but is read/written atomically
    float               mFinalVolume; // combine master volume, stream type volume and track volume
    sp<AudioTrackServerProxy>  mAudioTrackServerProxy;
    bool                mResumeToStopping; // track was paused in stopping state.
    bool                mFlushHwPending; // track requests for thread flush
    audio_output_flags_t mFlags;
    // If the last track change was notified to the client with readAndClearHasChanged
    std::atomic_flag     mChangeNotified = ATOMIC_FLAG_INIT;
};  // end of Track


@@ -216,8 +238,11 @@ public:
            bool        isActive() const { return mActive; }
    const wp<ThreadBase>& thread() const { return mThread; }

private:
            void        copyMetadataTo(MetadataInserter& backInserter) const override;
    /** Set the metadatas of the upstream tracks. Thread safe. */
            void        setMetadatas(const SourceMetadatas& metadatas);

private:
    status_t            obtainBuffer(AudioBufferProvider::Buffer* buffer,
                                     uint32_t waitTimeMs);
    void                clearBufferQueue();
@@ -232,6 +257,20 @@ private:
    bool                        mActive;
    DuplicatingThread* const    mSourceThread; // for waitTimeMs() in write()
    sp<AudioTrackClientProxy>   mClientProxy;
    /** Attributes of the source tracks.
     *
     * This member must be accessed with mTrackMetadatasMutex taken.
     * There is one writer (duplicating thread) and one reader (downstream mixer).
     *
     * That means that the duplicating thread can block the downstream mixer
     * thread and vice versa for the time of the copy.
     * If this becomes an issue, the metadata could be stored in an atomic raw pointer,
     * and a exchange with nullptr and delete can be used.
     * Alternatively a read-copy-update might be implemented.
     */
    SourceMetadatas mTrackMetadatas;
    /** Protects mTrackMetadatas against concurrent access. */
    mutable std::mutex mTrackMetadatasMutex;
};  // end of OutputTrack

// playback track, used by PatchPanel
+36 −23
Original line number Diff line number Diff line
@@ -2623,26 +2623,32 @@ void AudioFlinger::PlaybackThread::readOutputParameters_l()

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;
        track->copyMetadataTo(backInserter);
    }
        metadata.tracks.push_back({
                .usage = track->attributes().usage,
                .content_type = track->attributes().content_type,
                .gain = 1,
        });
    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)
{
@@ -4381,13 +4387,19 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac
                    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 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac
                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 @@ void AudioFlinger::DirectOutputThread::processVolume_l(Track *track, bool lastTr
    }

    if (lastTrack) {
        track->setFinalVolume((left + right) / 2.f);
        if (left != mLeftVolFloat || right != mRightVolFloat) {
            mLeftVolFloat = left;
            mRightVolFloat = right;
@@ -6153,14 +6168,12 @@ bool AudioFlinger::DuplicatingThread::outputsReady(
    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
+7 −5
Original line number Diff line number Diff line
@@ -566,8 +566,8 @@ protected:
                    // periodically called in the threadLoop() to update power state uids.
                    void            updatePowerState(sp<ThreadBase> thread, bool force = false);

                    /** @return true if the active tracks have changed since the last time
                     *          this function was called or the vector was created. */
                    /** @return true if one or move active tracks was added or removed since the
                     *          last time this function was called or the vector was created. */
                    bool            readAndClearHasChanged();

                private:
@@ -588,7 +588,7 @@ protected:
                    int                 mLastActiveTracksGeneration;
                    wp<T>               mLatestActiveTrack; // latest track added to ActiveTracks
                    SimpleLog * const   mLocalLog;
                    // If the active tracks have changed since last call to readAndClearHasChanged
                    // If the vector has changed since last call to readAndClearHasChanged
                    bool                mHasChanged = false;
                };

@@ -927,7 +927,8 @@ private:
    void        removeTrack_l(const sp<Track>& track);

    void        readOutputParameters_l();
    void        updateMetadata_l() override;
    void        updateMetadata_l() final;
    virtual void sendMetadataToBackend_l(const StreamOutHalInterface::SourceMetadata& metadata);

    virtual void dumpInternals(int fd, const Vector<String16>& args);
    void        dumpTracks(int fd, const Vector<String16>& args);
@@ -1287,7 +1288,8 @@ public:
                void        removeOutputTrack(MixerThread* thread);
                uint32_t    waitTimeMs() const { return mWaitTimeMs; }

                void        updateMetadata_l() override;
                void        sendMetadataToBackend_l(
                        const StreamOutHalInterface::SourceMetadata& metadata) override;
protected:
    virtual     uint32_t    activeSleepTimeUs() const;

+35 −0
Original line number Diff line number Diff line
@@ -407,6 +407,9 @@ AudioFlinger::PlaybackThread::Track::Track(
    // mSinkTimestamp
    mFastIndex(-1),
    mCachedVolume(1.0),
    /* The track might not play immediately after being active, similarly as if its volume was 0.
     * When the track starts playing, its volume will be computed. */
    mFinalVolume(0.f),
    mResumeToStopping(false),
    mFlushHwPending(false),
    mFlags(flags)
@@ -997,6 +1000,23 @@ sp<VolumeShaper::State> AudioFlinger::PlaybackThread::Track::getVolumeShaperStat
    return mVolumeHandler->getVolumeShaperState(id);
}

void AudioFlinger::PlaybackThread::Track::setFinalVolume(float volume)
{
    if (mFinalVolume != volume) { // Compare to an epsilon if too many meaningless updates
        mFinalVolume = volume;
        setMetadataHasChanged();
    }
}

void AudioFlinger::PlaybackThread::Track::copyMetadataTo(MetadataInserter& backInserter) const
{
    *backInserter++ = {
            .usage = mAttr.usage,
            .content_type = mAttr.content_type,
            .gain = mFinalVolume,
    };
}

status_t AudioFlinger::PlaybackThread::Track::getTimestamp(AudioTimestamp& timestamp)
{
    if (!isOffloaded() && !isDirect()) {
@@ -1427,6 +1447,21 @@ bool AudioFlinger::PlaybackThread::OutputTrack::write(void* data, uint32_t frame
    return outputBufferFull;
}

void AudioFlinger::PlaybackThread::OutputTrack::copyMetadataTo(MetadataInserter& backInserter) const
{
    std::lock_guard<std::mutex> lock(mTrackMetadatasMutex);
    backInserter = std::copy(mTrackMetadatas.begin(), mTrackMetadatas.end(), backInserter);
}

void AudioFlinger::PlaybackThread::OutputTrack::setMetadatas(const SourceMetadatas& metadatas) {
    {
        std::lock_guard<std::mutex> lock(mTrackMetadatasMutex);
        mTrackMetadatas = metadatas;
    }
    // No need to adjust metadata track volumes as OutputTrack volumes are always 0dBFS.
    setMetadataHasChanged();
}

status_t AudioFlinger::PlaybackThread::OutputTrack::obtainBuffer(
        AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs)
{