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

Commit 069c2719 authored by Kevin Rocard's avatar Kevin Rocard
Browse files

Audio V4: Propagate track attributes to HAL



This patch does not propagate the volume.

Bug: 38184704
Bug: 69623109
Test: log metadata in HAL
Change-Id: I313563cafd9f2b29a13839c3c075beb65a170632
Signed-off-by: default avatarKevin Rocard <krocard@google.com>
parent 1f564acc
Loading
Loading
Loading
Loading
+99 −0
Original line number Diff line number Diff line
@@ -57,6 +57,7 @@
#include <powermanager/PowerManager.h>

#include <media/audiohal/EffectsFactoryHalInterface.h>
#include <media/audiohal/StreamHalInterface.h>

#include "AudioFlinger.h"
#include "FastMixer.h"
@@ -1554,6 +1555,7 @@ ssize_t AudioFlinger::ThreadBase::ActiveTracks<T>::add(const sp<T> &track) {
    mActiveTracksGeneration++;
    mLatestActiveTrack = track;
    ++mBatteryCounter[track->uid()].second;
    mHasChanged = true;
    return mActiveTracks.add(track);
}

@@ -1568,6 +1570,7 @@ ssize_t AudioFlinger::ThreadBase::ActiveTracks<T>::remove(const sp<T> &track) {
    mActiveTracksGeneration++;
    --mBatteryCounter[track->uid()].second;
    // mLatestActiveTrack is not cleared even if is the same as track.
    mHasChanged = true;
    return index;
}

@@ -1578,6 +1581,7 @@ void AudioFlinger::ThreadBase::ActiveTracks<T>::clear() {
        logTrack("clear", track);
    }
    mLastActiveTracksGeneration = mActiveTracksGeneration;
    if (!mActiveTracks.empty()) { mHasChanged = true; }
    mActiveTracks.clear();
    mLatestActiveTrack.clear();
    mBatteryCounter.clear();
@@ -1614,6 +1618,13 @@ void AudioFlinger::ThreadBase::ActiveTracks<T>::updatePowerState(
    }
}

template <typename T>
bool AudioFlinger::ThreadBase::ActiveTracks<T>::readAndClearHasChanged() {
    const bool hasChanged = mHasChanged;
    mHasChanged = false;
    return hasChanged;
}

template <typename T>
void AudioFlinger::ThreadBase::ActiveTracks<T>::logTrack(
        const char *funcName, const sp<T> &track) const {
@@ -2610,6 +2621,24 @@ void AudioFlinger::PlaybackThread::readOutputParameters_l()
    }
}

void AudioFlinger::PlaybackThread::updateMetadata_l()
{
    // TODO: add volume support
    if (mOutput == nullptr || mOutput->stream == nullptr ||
            !mActiveTracks.readAndClearHasChanged()) {
        return;
    }
    StreamOutHalInterface::SourceMetadata metadata;
    for (const sp<Track> &track : mActiveTracks) {
        // No track is invalid as this is called after prepareTrack_l in the same critical section
        metadata.tracks.push_back({
                .usage = track->attributes().usage,
                .content_type = track->attributes().content_type,
                .gain = 1,
        });
    }
    mOutput->stream->updateSourceMetadata(metadata);
}

status_t AudioFlinger::PlaybackThread::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames)
{
@@ -3307,6 +3336,8 @@ bool AudioFlinger::PlaybackThread::threadLoop()

            mActiveTracks.updatePowerState(this);

            updateMetadata_l();

            // prevent any changes in effect chain list and in each effect chain
            // during mixing and effect process as the audio buffers could be deleted
            // or modified if an effect is created or deleted
@@ -6118,6 +6149,17 @@ bool AudioFlinger::DuplicatingThread::outputsReady(
    return true;
}

void AudioFlinger::DuplicatingThread::updateMetadata_l()
{
    // TODO: The duplicated track metadata are stored in other threads
    // (accessible through mActiveTracks::OutputTrack::thread()::mActiveTracks::Track::attributes())
    // but this information can be mutated at any time by the owning threads.
    // Taking the lock of any other owning threads is no possible due to timing constrains.
    // Similarly, the other threads can not push the metadatas in this thread as cross deadlock
    // would be possible.
    // A lock-free structure needs to be used to shared the metadata (maybe an atomic shared_ptr ?).
}

uint32_t AudioFlinger::DuplicatingThread::activeSleepTimeUs() const
{
    return (mWaitTimeMs * 1000) / 2;
@@ -6445,6 +6487,8 @@ reacquire_wakelock:

            mActiveTracks.updatePowerState(this);

            updateMetadata_l();

            if (allStopped) {
                standbyIfNotAlreadyInStandby();
            }
@@ -7135,6 +7179,23 @@ status_t AudioFlinger::RecordThread::getActiveMicrophones(
    return status;
}

void AudioFlinger::RecordThread::updateMetadata_l()
{
    if (mInput == nullptr || mInput->stream == nullptr ||
            !mActiveTracks.readAndClearHasChanged()) {
        return;
    }
    StreamInHalInterface::SinkMetadata metadata;
    for (const sp<RecordTrack> &track : mActiveTracks) {
        // No track is invalid as this is called after prepareTrack_l in the same critical section
        metadata.tracks.push_back({
                .source = track->attributes().source,
                .gain = 1, // capture tracks do not have volumes
        });
    }
    mInput->stream->updateSinkMetadata(metadata);
}

// destroyTrack_l() must be called with ThreadBase::mLock held
void AudioFlinger::RecordThread::destroyTrack_l(const sp<RecordTrack>& track)
{
@@ -8099,6 +8160,8 @@ bool AudioFlinger::MmapThread::threadLoop()

        mActiveTracks.updatePowerState(this);

        updateMetadata_l();

        lockEffectChains_l(effectChains);
        for (size_t i = 0; i < effectChains.size(); i ++) {
            effectChains[i]->process_l();
@@ -8646,6 +8709,24 @@ void AudioFlinger::MmapPlaybackThread::processVolume_l()
    }
}

void AudioFlinger::MmapPlaybackThread::updateMetadata_l()
{
    if (mOutput == nullptr || mOutput->stream == nullptr ||
            !mActiveTracks.readAndClearHasChanged()) {
        return;
    }
    StreamOutHalInterface::SourceMetadata metadata;
    for (const sp<MmapTrack> &track : mActiveTracks) {
        // No track is invalid as this is called after prepareTrack_l in the same critical section
        metadata.tracks.push_back({
                .usage = track->attributes().usage,
                .content_type = track->attributes().content_type,
                .gain = mHalVolFloat, // TODO: propagate from aaudio pre-mix volume
        });
    }
    mOutput->stream->updateSourceMetadata(metadata);
}

void AudioFlinger::MmapPlaybackThread::checkSilentMode_l()
{
    if (!mMasterMute) {
@@ -8690,4 +8771,22 @@ AudioFlinger::AudioStreamIn* AudioFlinger::MmapCaptureThread::clearInput()
    mInput = NULL;
    return input;
}

void AudioFlinger::MmapCaptureThread::updateMetadata_l()
{
    if (mInput == nullptr || mInput->stream == nullptr ||
            !mActiveTracks.readAndClearHasChanged()) {
        return;
    }
    StreamInHalInterface::SinkMetadata metadata;
    for (const sp<MmapTrack> &track : mActiveTracks) {
        // No track is invalid as this is called after prepareTrack_l in the same critical section
        metadata.tracks.push_back({
                .source = track->attributes().source,
                .gain = 1, // capture tracks do not have volumes
        });
    }
    mInput->stream->updateSinkMetadata(metadata);
}

} // namespace android
+18 −0
Original line number Diff line number Diff line
@@ -425,6 +425,9 @@ protected:
                // check if some effects must be suspended when an effect chain is added
                void checkSuspendOnAddEffectChain_l(const sp<EffectChain>& chain);

                // sends the metadata of the active tracks to the HAL
    virtual     void        updateMetadata_l() = 0;

                String16 getWakeLockTag();

    virtual     void        preExit() { }
@@ -563,6 +566,10 @@ 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. */
                    bool            readAndClearHasChanged();

                private:
                    void            logTrack(const char *funcName, const sp<T> &track) const;

@@ -581,6 +588,8 @@ 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
                    bool                mHasChanged = false;
                };

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

    void        readOutputParameters_l();
    void        updateMetadata_l() override;

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

                void        updateMetadata_l() override;
protected:
    virtual     uint32_t    activeSleepTimeUs() const;

@@ -1463,6 +1475,8 @@ public:

            status_t    getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones);

            void        updateMetadata_l() override;

private:
            // Enter standby if not already in standby, and set mStandby flag
            void    standbyIfNotAlreadyInStandby();
@@ -1660,6 +1674,8 @@ public:

    virtual     bool        isOutput() const override { return true; }

                void        updateMetadata_l() override;

protected:

                audio_stream_type_t         mStreamType;
@@ -1686,6 +1702,8 @@ public:

    virtual     bool           isOutput() const override { return false; }

                void           updateMetadata_l() override;

protected:

                AudioStreamIn*  mInput;
+1 −0
Original line number Diff line number Diff line
@@ -98,6 +98,7 @@ public:
    virtual void        invalidate() { mIsInvalid = true; }
            bool        isInvalid() const { return mIsInvalid; }

    audio_attributes_t  attributes() const { return mAttr; }

protected:
    DISALLOW_COPY_AND_ASSIGN(TrackBase);