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

Commit c0691380 authored by Andy Hung's avatar Andy Hung
Browse files

AudioFlinger: Replace track name with id

Simplifies Mixer handling, makes debug messages consistent.

Test: Audio sanity test, check logcat
Bug: 115435564
Change-Id: I216e2746170605dfb7994ac660c5534869e887fe
parent 867f39f2
Loading
Loading
Loading
Loading
+0 −13
Original line number Original line Diff line number Diff line
@@ -51,18 +51,6 @@ public:


            void        flush();
            void        flush();
            void        destroy();
            void        destroy();
            int         name() const { return mName; }
            void        setName(int name) {
                LOG_ALWAYS_FATAL_IF(mName >= 0 && name >= 0,
                        "%s both old name %d and new name %d are valid", __func__, mName, name);
                mName = name;
#ifdef TEE_SINK
                mTee.setId(std::string("_") + std::to_string(mThreadIoHandle)
                        + "_" + std::to_string(mId)
                        + "_" + std::to_string(mName)
                        + "_T");
#endif
            }


    virtual uint32_t    sampleRate() const;
    virtual uint32_t    sampleRate() const;


@@ -183,7 +171,6 @@ protected:


    bool                mResetDone;
    bool                mResetDone;
    const audio_stream_type_t mStreamType;
    const audio_stream_type_t mStreamType;
    int                 mName;
    effect_buffer_t     *mMainBuffer;
    effect_buffer_t     *mMainBuffer;


    int32_t             *mAuxBuffer;
    int32_t             *mAuxBuffer;
+60 −88
Original line number Original line Diff line number Diff line
@@ -2220,49 +2220,18 @@ Exit:
    return track;
    return track;
}
}


template<typename T>
ssize_t AudioFlinger::PlaybackThread::Tracks<T>::add(const sp<T> &track)
{
    const ssize_t index = mTracks.add(track);
    if (index >= 0) {
        // set name for track when adding.
        int name;
        if (mUnusedTrackNames.empty()) {
            name = mTracks.size() - 1; // new name {0 ... size-1}.
        } else {
            // reuse smallest name for deleted track.
            auto it = mUnusedTrackNames.begin();
            name = *it;
            (void)mUnusedTrackNames.erase(it);
        }
        track->setName(name);
    } else {
        LOG_ALWAYS_FATAL("cannot add track");
    }
    return index;
}

template<typename T>
template<typename T>
ssize_t AudioFlinger::PlaybackThread::Tracks<T>::remove(const sp<T> &track)
ssize_t AudioFlinger::PlaybackThread::Tracks<T>::remove(const sp<T> &track)
{
{
    const int name = track->name();
    const int trackId = track->id();
    const ssize_t index = mTracks.remove(track);
    const ssize_t index = mTracks.remove(track);
    if (index >= 0) {
    if (index >= 0) {
        // invalidate name when removing from mTracks.
        if (mSaveDeletedTrackIds) {
        LOG_ALWAYS_FATAL_IF(name < 0, "invalid name %d for track on mTracks", name);

        if (mSaveDeletedTrackNames) {
            // We can't directly access mAudioMixer since the caller may be outside of threadLoop.
            // We can't directly access mAudioMixer since the caller may be outside of threadLoop.
            // Instead, we add to mDeletedTrackNames which is solely used for mAudioMixer update,
            // Instead, we add to mDeletedTrackIds which is solely used for mAudioMixer update,
            // to be handled when MixerThread::prepareTracks_l() next changes mAudioMixer.
            // to be handled when MixerThread::prepareTracks_l() next changes mAudioMixer.
            mDeletedTrackNames.emplace(name);
            mDeletedTrackIds.emplace(trackId);
        }
        }

        mUnusedTrackNames.emplace(name);
        track->setName(T::TRACK_NAME_PENDING);
    } else {
        LOG_ALWAYS_FATAL_IF(name >= 0,
                "valid name %d for track not in mTracks (returned %zd)", name, index);
    }
    }
    return index;
    return index;
}
}
@@ -4351,14 +4320,14 @@ void AudioFlinger::MixerThread::threadLoop_sleepTime()
AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTracks_l(
AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTracks_l(
        Vector< sp<Track> > *tracksToRemove)
        Vector< sp<Track> > *tracksToRemove)
{
{
    // clean up deleted track names in AudioMixer before allocating new tracks
    // clean up deleted track ids in AudioMixer before allocating new tracks
    (void)mTracks.processDeletedTrackNames([this](int name) {
    (void)mTracks.processDeletedTrackIds([this](int trackId) {
        // for each name, destroy it in the AudioMixer
        // for each trackId, destroy it in the AudioMixer
        if (mAudioMixer->exists(name)) {
        if (mAudioMixer->exists(trackId)) {
            mAudioMixer->destroy(name);
            mAudioMixer->destroy(trackId);
        }
        }
    });
    });
    mTracks.clearDeletedTrackNames();
    mTracks.clearDeletedTrackIds();


    mixer_state mixerStatus = MIXER_IDLE;
    mixer_state mixerStatus = MIXER_IDLE;
    // find out which tracks need to be processed
    // find out which tracks need to be processed
@@ -4617,19 +4586,21 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac


        // The first time a track is added we wait
        // The first time a track is added we wait
        // for all its buffers to be filled before processing it
        // for all its buffers to be filled before processing it
        int name = track->name();
        const int trackId = track->id();


        // if an active track doesn't exist in the AudioMixer, create it.
        // if an active track doesn't exist in the AudioMixer, create it.
        if (!mAudioMixer->exists(name)) {
        // use the trackId as the AudioMixer name.
        if (!mAudioMixer->exists(trackId)) {
            status_t status = mAudioMixer->create(
            status_t status = mAudioMixer->create(
                    name,
                    trackId,
                    track->mChannelMask,
                    track->mChannelMask,
                    track->mFormat,
                    track->mFormat,
                    track->mSessionId);
                    track->mSessionId);
            if (status != OK) {
            if (status != OK) {
                ALOGW("%s: cannot create track name"
                ALOGW("%s(): AudioMixer cannot create track(%d)"
                        " %d, mask %#x, format %#x, sessionId %d in AudioMixer",
                        " mask %#x, format %#x, sessionId %d",
                        __func__, name, track->mChannelMask, track->mFormat, track->mSessionId);
                        __func__, trackId,
                        track->mChannelMask, track->mFormat, track->mSessionId);
                tracksToRemove->add(track);
                tracksToRemove->add(track);
                track->invalidate(); // consider it dead.
                track->invalidate(); // consider it dead.
                continue;
                continue;
@@ -4650,7 +4621,7 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac
        // TODO: ONLY USED FOR LEGACY RESAMPLERS, remove when they are removed.
        // TODO: ONLY USED FOR LEGACY RESAMPLERS, remove when they are removed.
        // add frames already consumed but not yet released by the resampler
        // add frames already consumed but not yet released by the resampler
        // because mAudioTrackServerProxy->framesReady() will include these frames
        // because mAudioTrackServerProxy->framesReady() will include these frames
        desiredFrames += mAudioMixer->getUnreleasedFrames(track->name());
        desiredFrames += mAudioMixer->getUnreleasedFrames(trackId);


        uint32_t minFrames = 1;
        uint32_t minFrames = 1;
        if ((track->sharedBuffer() == 0) && !track->isStopped() && !track->isPausing() &&
        if ((track->sharedBuffer() == 0) && !track->isStopped() && !track->isPausing() &&
@@ -4662,13 +4633,13 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac
        if (ATRACE_ENABLED()) {
        if (ATRACE_ENABLED()) {
            // I wish we had formatted trace names
            // I wish we had formatted trace names
            std::string traceName("nRdy");
            std::string traceName("nRdy");
            traceName += std::to_string(track->name());
            traceName += std::to_string(trackId);
            ATRACE_INT(traceName.c_str(), framesReady);
            ATRACE_INT(traceName.c_str(), framesReady);
        }
        }
        if ((framesReady >= minFrames) && track->isReady() &&
        if ((framesReady >= minFrames) && track->isReady() &&
                !track->isPaused() && !track->isTerminated())
                !track->isPaused() && !track->isTerminated())
        {
        {
            ALOGVV("track %d s=%08x [OK] on thread %p", name, cblk->mServer, this);
            ALOGVV("track(%d) s=%08x [OK] on thread %p", trackId, cblk->mServer, this);


            mixedTracks++;
            mixedTracks++;


@@ -4685,9 +4656,9 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac
                if (chain != 0) {
                if (chain != 0) {
                    tracksWithEffect++;
                    tracksWithEffect++;
                } else {
                } else {
                    ALOGW("prepareTracks_l(): track %d attached to effect but no chain found on "
                    ALOGW("prepareTracks_l(): track(%d) attached to effect but no chain found on "
                            "session %d",
                            "session %d",
                            name, track->sessionId());
                            trackId, track->sessionId());
                }
                }
            }
            }


@@ -4700,7 +4671,7 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac
                    track->mState = TrackBase::ACTIVE;
                    track->mState = TrackBase::ACTIVE;
                    param = AudioMixer::RAMP_VOLUME;
                    param = AudioMixer::RAMP_VOLUME;
                }
                }
                mAudioMixer->setParameter(name, AudioMixer::RESAMPLE, AudioMixer::RESET, NULL);
                mAudioMixer->setParameter(trackId, AudioMixer::RESAMPLE, AudioMixer::RESET, NULL);
                mLeftVolFloat = -1.0;
                mLeftVolFloat = -1.0;
            // FIXME should not make a decision based on mServer
            // FIXME should not make a decision based on mServer
            } else if (cblk->mServer != 0) {
            } else if (cblk->mServer != 0) {
@@ -4796,22 +4767,22 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac
               }
               }
            }
            }
            // XXX: these things DON'T need to be done each time
            // XXX: these things DON'T need to be done each time
            mAudioMixer->setBufferProvider(name, track);
            mAudioMixer->setBufferProvider(trackId, track);
            mAudioMixer->enable(name);
            mAudioMixer->enable(trackId);


            mAudioMixer->setParameter(name, param, AudioMixer::VOLUME0, &vlf);
            mAudioMixer->setParameter(trackId, param, AudioMixer::VOLUME0, &vlf);
            mAudioMixer->setParameter(name, param, AudioMixer::VOLUME1, &vrf);
            mAudioMixer->setParameter(trackId, param, AudioMixer::VOLUME1, &vrf);
            mAudioMixer->setParameter(name, param, AudioMixer::AUXLEVEL, &vaf);
            mAudioMixer->setParameter(trackId, param, AudioMixer::AUXLEVEL, &vaf);
            mAudioMixer->setParameter(
            mAudioMixer->setParameter(
                name,
                trackId,
                AudioMixer::TRACK,
                AudioMixer::TRACK,
                AudioMixer::FORMAT, (void *)track->format());
                AudioMixer::FORMAT, (void *)track->format());
            mAudioMixer->setParameter(
            mAudioMixer->setParameter(
                name,
                trackId,
                AudioMixer::TRACK,
                AudioMixer::TRACK,
                AudioMixer::CHANNEL_MASK, (void *)(uintptr_t)track->channelMask());
                AudioMixer::CHANNEL_MASK, (void *)(uintptr_t)track->channelMask());
            mAudioMixer->setParameter(
            mAudioMixer->setParameter(
                name,
                trackId,
                AudioMixer::TRACK,
                AudioMixer::TRACK,
                AudioMixer::MIXER_CHANNEL_MASK, (void *)(uintptr_t)mChannelMask);
                AudioMixer::MIXER_CHANNEL_MASK, (void *)(uintptr_t)mChannelMask);
            // limit track sample rate to 2 x output sample rate, which changes at re-configuration
            // limit track sample rate to 2 x output sample rate, which changes at re-configuration
@@ -4823,14 +4794,14 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac
                reqSampleRate = maxSampleRate;
                reqSampleRate = maxSampleRate;
            }
            }
            mAudioMixer->setParameter(
            mAudioMixer->setParameter(
                name,
                trackId,
                AudioMixer::RESAMPLE,
                AudioMixer::RESAMPLE,
                AudioMixer::SAMPLE_RATE,
                AudioMixer::SAMPLE_RATE,
                (void *)(uintptr_t)reqSampleRate);
                (void *)(uintptr_t)reqSampleRate);


            AudioPlaybackRate playbackRate = track->mAudioTrackServerProxy->getPlaybackRate();
            AudioPlaybackRate playbackRate = track->mAudioTrackServerProxy->getPlaybackRate();
            mAudioMixer->setParameter(
            mAudioMixer->setParameter(
                name,
                trackId,
                AudioMixer::TIMESTRETCH,
                AudioMixer::TIMESTRETCH,
                AudioMixer::PLAYBACK_RATE,
                AudioMixer::PLAYBACK_RATE,
                &playbackRate);
                &playbackRate);
@@ -4851,27 +4822,27 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac
                    && (track->mainBuffer() == mSinkBuffer
                    && (track->mainBuffer() == mSinkBuffer
                            || track->mainBuffer() == mMixerBuffer)) {
                            || track->mainBuffer() == mMixerBuffer)) {
                mAudioMixer->setParameter(
                mAudioMixer->setParameter(
                        name,
                        trackId,
                        AudioMixer::TRACK,
                        AudioMixer::TRACK,
                        AudioMixer::MIXER_FORMAT, (void *)mMixerBufferFormat);
                        AudioMixer::MIXER_FORMAT, (void *)mMixerBufferFormat);
                mAudioMixer->setParameter(
                mAudioMixer->setParameter(
                        name,
                        trackId,
                        AudioMixer::TRACK,
                        AudioMixer::TRACK,
                        AudioMixer::MAIN_BUFFER, (void *)mMixerBuffer);
                        AudioMixer::MAIN_BUFFER, (void *)mMixerBuffer);
                // TODO: override track->mainBuffer()?
                // TODO: override track->mainBuffer()?
                mMixerBufferValid = true;
                mMixerBufferValid = true;
            } else {
            } else {
                mAudioMixer->setParameter(
                mAudioMixer->setParameter(
                        name,
                        trackId,
                        AudioMixer::TRACK,
                        AudioMixer::TRACK,
                        AudioMixer::MIXER_FORMAT, (void *)EFFECT_BUFFER_FORMAT);
                        AudioMixer::MIXER_FORMAT, (void *)EFFECT_BUFFER_FORMAT);
                mAudioMixer->setParameter(
                mAudioMixer->setParameter(
                        name,
                        trackId,
                        AudioMixer::TRACK,
                        AudioMixer::TRACK,
                        AudioMixer::MAIN_BUFFER, (void *)track->mainBuffer());
                        AudioMixer::MAIN_BUFFER, (void *)track->mainBuffer());
            }
            }
            mAudioMixer->setParameter(
            mAudioMixer->setParameter(
                name,
                trackId,
                AudioMixer::TRACK,
                AudioMixer::TRACK,
                AudioMixer::AUX_BUFFER, (void *)track->auxBuffer());
                AudioMixer::AUX_BUFFER, (void *)track->auxBuffer());


@@ -4888,8 +4859,8 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac
        } else {
        } else {
            size_t underrunFrames = 0;
            size_t underrunFrames = 0;
            if (framesReady < desiredFrames && !track->isStopped() && !track->isPaused()) {
            if (framesReady < desiredFrames && !track->isStopped() && !track->isPaused()) {
                ALOGV("track(%p) underrun,  framesReady(%zu) < framesDesired(%zd)",
                ALOGV("track(%d) underrun,  framesReady(%zu) < framesDesired(%zd)",
                        track, framesReady, desiredFrames);
                        trackId, framesReady, desiredFrames);
                underrunFrames = desiredFrames;
                underrunFrames = desiredFrames;
            }
            }
            deferredOperations.tallyUnderrunFrames(track, underrunFrames);
            deferredOperations.tallyUnderrunFrames(track, underrunFrames);
@@ -4901,7 +4872,7 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac
                chain->clearInputBuffer();
                chain->clearInputBuffer();
            }
            }


            ALOGVV("track %d s=%08x [NOT READY] on thread %p", name, cblk->mServer, this);
            ALOGVV("track(%d) s=%08x [NOT READY] on thread %p", trackId, cblk->mServer, this);
            if ((track->sharedBuffer() != 0) || track->isTerminated() ||
            if ((track->sharedBuffer() != 0) || track->isTerminated() ||
                    track->isStopped() || track->isPaused()) {
                    track->isStopped() || track->isPaused()) {
                // We have consumed all the buffers of this track.
                // We have consumed all the buffers of this track.
@@ -4920,7 +4891,8 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac
                // No buffers for this track. Give it a few chances to
                // No buffers for this track. Give it a few chances to
                // fill a buffer, then remove it from active list.
                // fill a buffer, then remove it from active list.
                if (--(track->mRetryCount) <= 0) {
                if (--(track->mRetryCount) <= 0) {
                    ALOGI("BUFFER TIMEOUT: remove(%d) from active list on thread %p", name, this);
                    ALOGI("BUFFER TIMEOUT: remove(%d) from active list on thread %p",
                            trackId, this);
                    tracksToRemove->add(track);
                    tracksToRemove->add(track);
                    // indicate to client process that the track was disabled because of underrun;
                    // indicate to client process that the track was disabled because of underrun;
                    // it will then automatically call start() when data is available
                    // it will then automatically call start() when data is available
@@ -4933,7 +4905,7 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac
                    mixerStatus = MIXER_TRACKS_ENABLED;
                    mixerStatus = MIXER_TRACKS_ENABLED;
                }
                }
            }
            }
            mAudioMixer->disable(name);
            mAudioMixer->disable(trackId);
        }
        }


        }   // local variable scope to avoid goto warning
        }   // local variable scope to avoid goto warning
@@ -4994,9 +4966,9 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac
    // of prepareTracks_l(); this releases any outstanding buffer back to the track.
    // of prepareTracks_l(); this releases any outstanding buffer back to the track.
    // See also the implementation of destroyTrack_l().
    // See also the implementation of destroyTrack_l().
    for (const auto &track : *tracksToRemove) {
    for (const auto &track : *tracksToRemove) {
        const int name = track->name();
        const int trackId = track->id();
        if (mAudioMixer->exists(name)) { // Normal tracks here, fast tracks in FastMixer.
        if (mAudioMixer->exists(trackId)) { // Normal tracks here, fast tracks in FastMixer.
            mAudioMixer->setBufferProvider(name, nullptr /* bufferProvider */);
            mAudioMixer->setBufferProvider(trackId, nullptr /* bufferProvider */);
        }
        }
    }
    }


@@ -5165,17 +5137,17 @@ bool AudioFlinger::MixerThread::checkForNewParameter_l(const String8& keyValuePa
            delete mAudioMixer;
            delete mAudioMixer;
            mAudioMixer = new AudioMixer(mNormalFrameCount, mSampleRate);
            mAudioMixer = new AudioMixer(mNormalFrameCount, mSampleRate);
            for (const auto &track : mTracks) {
            for (const auto &track : mTracks) {
                const int name = track->name();
                const int trackId = track->id();
                status_t status = mAudioMixer->create(
                status_t status = mAudioMixer->create(
                        name,
                        trackId,
                        track->mChannelMask,
                        track->mChannelMask,
                        track->mFormat,
                        track->mFormat,
                        track->mSessionId);
                        track->mSessionId);
                ALOGW_IF(status != NO_ERROR,
                ALOGW_IF(status != NO_ERROR,
                        "%s: cannot create track name"
                        "%s(): AudioMixer cannot create track(%d)"
                        " %d, mask %#x, format %#x, sessionId %d in AudioMixer",
                        " mask %#x, format %#x, sessionId %d",
                        __func__,
                        __func__,
                        name, track->mChannelMask, track->mFormat, track->mSessionId);
                        trackId, track->mChannelMask, track->mFormat, track->mSessionId);
            }
            }
            sendIoConfigEvent_l(AUDIO_OUTPUT_CONFIG_CHANGED);
            sendIoConfigEvent_l(AUDIO_OUTPUT_CONFIG_CHANGED);
        }
        }
@@ -5429,7 +5401,7 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::DirectOutputThread::prep
        if ((track->framesReady() >= minFrames) && track->isReady() && !track->isPaused() &&
        if ((track->framesReady() >= minFrames) && track->isReady() && !track->isPaused() &&
                !track->isStopping_2() && !track->isStopped())
                !track->isStopping_2() && !track->isStopped())
        {
        {
            ALOGVV("track %d s=%08x [OK]", track->name(), cblk->mServer);
            ALOGVV("track(%d) s=%08x [OK]", track->id(), cblk->mServer);


            if (track->mFillingUpStatus == Track::FS_FILLED) {
            if (track->mFillingUpStatus == Track::FS_FILLED) {
                track->mFillingUpStatus = Track::FS_ACTIVE;
                track->mFillingUpStatus = Track::FS_ACTIVE;
@@ -5505,7 +5477,7 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::DirectOutputThread::prep
                // fill a buffer, then remove it from active list.
                // fill a buffer, then remove it from active list.
                // Only consider last track started for mixer state control
                // Only consider last track started for mixer state control
                if (--(track->mRetryCount) <= 0) {
                if (--(track->mRetryCount) <= 0) {
                    ALOGV("BUFFER TIMEOUT: remove(%d) from active list", track->name());
                    ALOGV("BUFFER TIMEOUT: remove track(%d) from active list", track->id());
                    tracksToRemove->add(track);
                    tracksToRemove->add(track);
                    // indicate to client process that the track was disabled because of underrun;
                    // indicate to client process that the track was disabled because of underrun;
                    // it will then automatically call start() when data is available
                    // it will then automatically call start() when data is available
@@ -5988,7 +5960,7 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::OffloadThread::prepareTr
            }
            }
        }  else if (track->framesReady() && track->isReady() &&
        }  else if (track->framesReady() && track->isReady() &&
                !track->isPaused() && !track->isTerminated() && !track->isStopping_2()) {
                !track->isPaused() && !track->isTerminated() && !track->isStopping_2()) {
            ALOGVV("OffloadThread: track %d s=%08x [OK]", track->name(), cblk->mServer);
            ALOGVV("OffloadThread: track(%d) s=%08x [OK]", track->id(), cblk->mServer);
            if (track->mFillingUpStatus == Track::FS_FILLED) {
            if (track->mFillingUpStatus == Track::FS_FILLED) {
                track->mFillingUpStatus = Track::FS_ACTIVE;
                track->mFillingUpStatus = Track::FS_ACTIVE;
                if (last) {
                if (last) {
@@ -6032,7 +6004,7 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::OffloadThread::prepareTr
                mixerStatus = MIXER_TRACKS_READY;
                mixerStatus = MIXER_TRACKS_READY;
            }
            }
        } else {
        } else {
            ALOGVV("OffloadThread: track %d s=%08x [NOT READY]", track->name(), cblk->mServer);
            ALOGVV("OffloadThread: track(%d) s=%08x [NOT READY]", track->id(), cblk->mServer);
            if (track->isStopping_1()) {
            if (track->isStopping_1()) {
                if (--(track->mRetryCount) <= 0) {
                if (--(track->mRetryCount) <= 0) {
                    // Hardware buffer can hold a large amount of audio so we must
                    // Hardware buffer can hold a large amount of audio so we must
@@ -6108,8 +6080,8 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::OffloadThread::prepareTr
                    if (running) { // still running, give us more time.
                    if (running) { // still running, give us more time.
                        track->mRetryCount = kMaxTrackRetriesOffload;
                        track->mRetryCount = kMaxTrackRetriesOffload;
                    } else {
                    } else {
                        ALOGV("OffloadThread: BUFFER TIMEOUT: remove(%d) from active list",
                        ALOGV("OffloadThread: BUFFER TIMEOUT: remove track(%d) from active list",
                                track->name());
                                track->id());
                        tracksToRemove->add(track);
                        tracksToRemove->add(track);
                        // tell client process that the track was disabled because of underrun;
                        // tell client process that the track was disabled because of underrun;
                        // it will then automatically call start() when data is available
                        // it will then automatically call start() when data is available
@@ -6292,7 +6264,7 @@ void AudioFlinger::DuplicatingThread::dumpInternals(int fd, const Vector<String1
        ss << ":";
        ss << ":";
        for (const auto &track : mOutputTracks) {
        for (const auto &track : mOutputTracks) {
            const sp<ThreadBase> thread = track->thread().promote();
            const sp<ThreadBase> thread = track->thread().promote();
            ss << " (" << track->name() << " : ";
            ss << " (" << track->id() << " : ";
            if (thread.get() != nullptr) {
            if (thread.get() != nullptr) {
                ss << thread.get() << ", " << thread->id();
                ss << thread.get() << ", " << thread->id();
            } else {
            } else {
+16 −22
Original line number Original line Diff line number Diff line
@@ -962,16 +962,19 @@ private:
    virtual void dumpInternals(int fd, const Vector<String16>& args);
    virtual void dumpInternals(int fd, const Vector<String16>& args);
    void        dumpTracks(int fd, const Vector<String16>& args);
    void        dumpTracks(int fd, const Vector<String16>& args);


    // The Tracks class manages names for all tracks
    // The Tracks class manages tracks added and removed from the Thread.
    // added and removed from the Thread.
    template <typename T>
    template <typename T>
    class Tracks {
    class Tracks {
    public:
    public:
        Tracks(bool saveDeletedTrackNames) :
        Tracks(bool saveDeletedTrackIds) :
            mSaveDeletedTrackNames(saveDeletedTrackNames) { }
            mSaveDeletedTrackIds(saveDeletedTrackIds) { }


        // SortedVector methods
        // SortedVector methods
        ssize_t         add(const sp<T> &track);
        ssize_t         add(const sp<T> &track) {
            const ssize_t index = mTracks.add(track);
            LOG_ALWAYS_FATAL_IF(index < 0, "cannot add track");
            return index;
        }
        ssize_t         remove(const sp<T> &track);
        ssize_t         remove(const sp<T> &track);
        size_t          size() const {
        size_t          size() const {
            return mTracks.size();
            return mTracks.size();
@@ -992,28 +995,19 @@ private:
            return mTracks.end();
            return mTracks.end();
        }
        }


        size_t          processDeletedTrackNames(std::function<void(int)> f) {
        size_t          processDeletedTrackIds(std::function<void(int)> f) {
            const size_t size = mDeletedTrackNames.size();
            for (const int trackId : mDeletedTrackIds) {
            if (size > 0) {
                f(trackId);
                for (const int name : mDeletedTrackNames) {
                    f(name);
                }
            }
            }
            return size;
            return mDeletedTrackIds.size();
        }
        }


        void            clearDeletedTrackNames() { mDeletedTrackNames.clear(); }
        void            clearDeletedTrackIds() { mDeletedTrackIds.clear(); }


    private:
    private:
        // Track names pending deletion for MIXER type threads
        // Tracks pending deletion for MIXER type threads
        const bool mSaveDeletedTrackNames; // true to enable tracking
        const bool mSaveDeletedTrackIds; // true to enable tracking
        std::set<int> mDeletedTrackNames;
        std::set<int> mDeletedTrackIds;

        // Fast lookup of previously deleted track names for reuse.
        // This is an arbitrary decision (actually any non-negative
        // integer that isn't in mTracks[*]->names() could be used) - we attempt
        // to use the smallest possible available name.
        std::set<int> mUnusedTrackNames;


        SortedVector<sp<T>> mTracks; // wrapped SortedVector.
        SortedVector<sp<T>> mTracks; // wrapped SortedVector.
    };
    };
+1 −5
Original line number Original line Diff line number Diff line
@@ -54,11 +54,6 @@ public:
        TYPE_PATCH,
        TYPE_PATCH,
    };
    };


    enum {
        TRACK_NAME_PENDING = -1,
        TRACK_NAME_FAILURE = -2,
    };

                        TrackBase(ThreadBase *thread,
                        TrackBase(ThreadBase *thread,
                                const sp<Client>& client,
                                const sp<Client>& client,
                                const audio_attributes_t& mAttr,
                                const audio_attributes_t& mAttr,
@@ -199,6 +194,7 @@ public:
                        }
                        }


           audio_format_t format() const { return mFormat; }
           audio_format_t format() const { return mFormat; }
           int id() const { return mId; }


protected:
protected:
    DISALLOW_COPY_AND_ASSIGN(TrackBase);
    DISALLOW_COPY_AND_ASSIGN(TrackBase);
+20 −23
Original line number Original line Diff line number Diff line
@@ -377,7 +377,6 @@ AudioFlinger::PlaybackThread::Track::Track(
    // mRetryCount initialized later when needed
    // mRetryCount initialized later when needed
    mSharedBuffer(sharedBuffer),
    mSharedBuffer(sharedBuffer),
    mStreamType(streamType),
    mStreamType(streamType),
    mName(TRACK_NAME_FAILURE),  // set to TRACK_NAME_PENDING on constructor success.
    mMainBuffer(thread->sinkBuffer()),
    mMainBuffer(thread->sinkBuffer()),
    mAuxBuffer(NULL),
    mAuxBuffer(NULL),
    mAuxEffectId(0), mHasVolumeController(false),
    mAuxEffectId(0), mHasVolumeController(false),
@@ -433,14 +432,12 @@ AudioFlinger::PlaybackThread::Track::Track(
        mFastIndex = i;
        mFastIndex = i;
        thread->mFastTrackAvailMask &= ~(1 << i);
        thread->mFastTrackAvailMask &= ~(1 << i);
    }
    }
    mName = TRACK_NAME_PENDING;


    mServerLatencySupported = thread->type() == ThreadBase::MIXER
    mServerLatencySupported = thread->type() == ThreadBase::MIXER
            || thread->type() == ThreadBase::DUPLICATING;
            || thread->type() == ThreadBase::DUPLICATING;
#ifdef TEE_SINK
#ifdef TEE_SINK
    mTee.setId(std::string("_") + std::to_string(mThreadIoHandle)
    mTee.setId(std::string("_") + std::to_string(mThreadIoHandle)
            + "_" + std::to_string(mId) +
            + "_" + std::to_string(mId));
            + "_PEND_T");
#endif
#endif
}
}


@@ -460,7 +457,7 @@ AudioFlinger::PlaybackThread::Track::~Track()
status_t AudioFlinger::PlaybackThread::Track::initCheck() const
status_t AudioFlinger::PlaybackThread::Track::initCheck() const
{
{
    status_t status = TrackBase::initCheck();
    status_t status = TrackBase::initCheck();
    if (status == NO_ERROR && mName == TRACK_NAME_FAILURE) {
    if (status == NO_ERROR && mCblk == nullptr) {
        status = NO_MEMORY;
        status = NO_MEMORY;
    }
    }
    return status;
    return status;
@@ -493,7 +490,7 @@ void AudioFlinger::PlaybackThread::Track::destroy()


void AudioFlinger::PlaybackThread::Track::appendDumpHeader(String8& result)
void AudioFlinger::PlaybackThread::Track::appendDumpHeader(String8& result)
{
{
    result.appendFormat("T Name Active Client Session S  Flags "
    result.appendFormat("Type     Id Active Client Session S  Flags "
                        "  Format Chn mask  SRate "
                        "  Format Chn mask  SRate "
                        "ST Usg CT "
                        "ST Usg CT "
                        " G db  L dB  R dB  VS dB "
                        " G db  L dB  R dB  VS dB "
@@ -522,13 +519,9 @@ void AudioFlinger::PlaybackThread::Track::appendDump(String8& result, bool activ
    }
    }


    if (isFastTrack()) {
    if (isFastTrack()) {
        result.appendFormat("F%c %3d", trackType, mFastIndex);
        result.appendFormat("F%d %c %6d", mFastIndex, trackType, mId);
    } else if (mName == TRACK_NAME_PENDING) {
        result.appendFormat("%c pend", trackType);
    } else if (mName == TRACK_NAME_FAILURE) {
        result.appendFormat("%c fail", trackType);
    } else {
    } else {
        result.appendFormat("%c %4d", trackType, mName);
        result.appendFormat("   %c %6d", trackType, mId);
    }
    }


    char nowInUnderrun;
    char nowInUnderrun;
@@ -721,8 +714,8 @@ status_t AudioFlinger::PlaybackThread::Track::start(AudioSystem::sync_event_t ev
                                                    audio_session_t triggerSession __unused)
                                                    audio_session_t triggerSession __unused)
{
{
    status_t status = NO_ERROR;
    status_t status = NO_ERROR;
    ALOGV("start(%d), calling pid %d session %d",
    ALOGV("%s(%d): calling pid %d session %d",
            mName, IPCThreadState::self()->getCallingPid(), mSessionId);
            __func__, mId, IPCThreadState::self()->getCallingPid(), mSessionId);


    sp<ThreadBase> thread = mThread.promote();
    sp<ThreadBase> thread = mThread.promote();
    if (thread != 0) {
    if (thread != 0) {
@@ -748,14 +741,17 @@ status_t AudioFlinger::PlaybackThread::Track::start(AudioSystem::sync_event_t ev
            if (mResumeToStopping) {
            if (mResumeToStopping) {
                // happened we need to resume to STOPPING_1
                // happened we need to resume to STOPPING_1
                mState = TrackBase::STOPPING_1;
                mState = TrackBase::STOPPING_1;
                ALOGV("PAUSED => STOPPING_1 (%d) on thread %p", mName, this);
                ALOGV("%s(%d): PAUSED => STOPPING_1 on thread %d",
                        __func__, mId, (int)mThreadIoHandle);
            } else {
            } else {
                mState = TrackBase::RESUMING;
                mState = TrackBase::RESUMING;
                ALOGV("PAUSED => RESUMING (%d) on thread %p", mName, this);
                ALOGV("%s(%d): PAUSED => RESUMING on thread %d",
                        __func__,  mId, (int)mThreadIoHandle);
            }
            }
        } else {
        } else {
            mState = TrackBase::ACTIVE;
            mState = TrackBase::ACTIVE;
            ALOGV("? => ACTIVE (%d) on thread %p", mName, this);
            ALOGV("%s(%d): ? => ACTIVE on thread %d",
                    __func__, mId, (int)mThreadIoHandle);
        }
        }


        // states to reset position info for non-offloaded/direct tracks
        // states to reset position info for non-offloaded/direct tracks
@@ -806,7 +802,7 @@ status_t AudioFlinger::PlaybackThread::Track::start(AudioSystem::sync_event_t ev


void AudioFlinger::PlaybackThread::Track::stop()
void AudioFlinger::PlaybackThread::Track::stop()
{
{
    ALOGV("stop(%d), calling pid %d", mName, IPCThreadState::self()->getCallingPid());
    ALOGV("%s(%d): calling pid %d", __func__, mId, IPCThreadState::self()->getCallingPid());
    sp<ThreadBase> thread = mThread.promote();
    sp<ThreadBase> thread = mThread.promote();
    if (thread != 0) {
    if (thread != 0) {
        Mutex::Autolock _l(thread->mLock);
        Mutex::Autolock _l(thread->mLock);
@@ -830,15 +826,15 @@ void AudioFlinger::PlaybackThread::Track::stop()
                }
                }
            }
            }
            playbackThread->broadcast_l();
            playbackThread->broadcast_l();
            ALOGV("not stopping/stopped => stopping/stopped (%d) on thread %p", mName,
            ALOGV("%s(%d): not stopping/stopped => stopping/stopped on thread %d",
                    playbackThread);
                    __func__, mId, (int)mThreadIoHandle);
        }
        }
    }
    }
}
}


void AudioFlinger::PlaybackThread::Track::pause()
void AudioFlinger::PlaybackThread::Track::pause()
{
{
    ALOGV("pause(%d), calling pid %d", mName, IPCThreadState::self()->getCallingPid());
    ALOGV("%s(%d): calling pid %d", __func__, mId, IPCThreadState::self()->getCallingPid());
    sp<ThreadBase> thread = mThread.promote();
    sp<ThreadBase> thread = mThread.promote();
    if (thread != 0) {
    if (thread != 0) {
        Mutex::Autolock _l(thread->mLock);
        Mutex::Autolock _l(thread->mLock);
@@ -857,7 +853,8 @@ void AudioFlinger::PlaybackThread::Track::pause()
        case ACTIVE:
        case ACTIVE:
        case RESUMING:
        case RESUMING:
            mState = PAUSING;
            mState = PAUSING;
            ALOGV("ACTIVE/RESUMING => PAUSING (%d) on thread %p", mName, thread.get());
            ALOGV("%s(%d): ACTIVE/RESUMING => PAUSING on thread %d",
                    __func__, mId, (int)mThreadIoHandle);
            playbackThread->broadcast_l();
            playbackThread->broadcast_l();
            break;
            break;


@@ -869,7 +866,7 @@ void AudioFlinger::PlaybackThread::Track::pause()


void AudioFlinger::PlaybackThread::Track::flush()
void AudioFlinger::PlaybackThread::Track::flush()
{
{
    ALOGV("flush(%d)", mName);
    ALOGV("%s(%d)", __func__, mId);
    sp<ThreadBase> thread = mThread.promote();
    sp<ThreadBase> thread = mThread.promote();
    if (thread != 0) {
    if (thread != 0) {
        Mutex::Autolock _l(thread->mLock);
        Mutex::Autolock _l(thread->mLock);