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

Commit 32179d65 authored by android-build-team Robot's avatar android-build-team Robot
Browse files

Snap for 7468789 from fcd9129a to sc-d1-release

Change-Id: I0f9bdb8b73187a9cf1ebf1bc3c23e75a3ceec65b
parents bfbc794e fcd9129a
Loading
Loading
Loading
Loading
+22 −4
Original line number Diff line number Diff line
@@ -222,10 +222,23 @@ protected:

    sp<IMemory> sharedBuffer() const { return mSharedBuffer; }

    // presentationComplete checked by frames. (Mixed Tracks).
    // framesWritten is cumulative, never reset, and is shared all tracks
    // audioHalFrames is derived from output latency
    // FIXME parameters not needed, could get them from the thread
    bool presentationComplete(int64_t framesWritten, size_t audioHalFrames);

    // presentationComplete checked by time. (Direct Tracks).
    bool presentationComplete(uint32_t latencyMs);

    void resetPresentationComplete() {
        mPresentationCompleteFrames = 0;
        mPresentationCompleteTimeNs = 0;
    }

    // notifyPresentationComplete is called when presentationComplete() detects
    // that the track is finished stopping.
    void notifyPresentationComplete();

    void signalClientFlag(int32_t flag);

public:
@@ -256,9 +269,6 @@ protected:
    int32_t             *mAuxBuffer;
    int                 mAuxEffectId;
    bool                mHasVolumeController;
    size_t              mPresentationCompleteFrames; // number of frames written to the
                                    // audio HAL when this track will be fully rendered
                                    // zero means not monitoring

    // access these three variables only when holding thread lock.
    LinearMap<int64_t> mFrameMap;           // track frame to server frame mapping
@@ -294,6 +304,14 @@ private:
        for (auto& tp : mTeePatches) { f(tp.patchTrack); }
    };

    size_t              mPresentationCompleteFrames = 0; // (Used for Mixed tracks)
                                    // The number of frames written to the
                                    // audio HAL when this track is considered fully rendered.
                                    // Zero means not monitoring.
    int64_t             mPresentationCompleteTimeNs = 0; // (Used for Direct tracks)
                                    // The time when this track is considered fully rendered.
                                    // Zero means not monitoring.

    // The following fields are only for fast tracks, and should be in a subclass
    int                 mFastIndex; // index within FastMixerState::mFastTracks[];
                                    // either mFastIndex == -1 if not isFastTrack()
+3 −18
Original line number Diff line number Diff line
@@ -2631,7 +2631,7 @@ status_t AudioFlinger::PlaybackThread::addTrack_l(const sp<Track>& track)
        }

        track->mResetDone = false;
        track->mPresentationCompleteFrames = 0;
        track->resetPresentationComplete();
        mActiveTracks.add(track);
        if (chain != 0) {
            ALOGV("addTrack_l() starting track on chain %p for session %d", chain.get(),
@@ -6038,16 +6038,8 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::DirectOutputThread::prep
                    track->isStopping_2() || track->isPaused()) {
                // We have consumed all the buffers of this track.
                // Remove it from the list of active tracks.
                size_t audioHALFrames;
                if (audio_has_proportional_frames(mFormat)) {
                    audioHALFrames = (latency_l() * mSampleRate) / 1000;
                } else {
                    audioHALFrames = 0;
                }

                int64_t framesWritten = mBytesWritten / mFrameSize;
                if (mStandby || !last ||
                        track->presentationComplete(framesWritten, audioHALFrames) ||
                        track->presentationComplete(latency_l()) ||
                        track->isPaused() || mHwPaused) {
                    if (track->isStopping_2()) {
                        track->mState = TrackBase::STOPPED;
@@ -6621,14 +6613,7 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::OffloadThread::prepareTr
                // Drain has completed or we are in standby, signal presentation complete
                if (!(mDrainSequence & 1) || !last || mStandby) {
                    track->mState = TrackBase::STOPPED;
                    uint32_t latency = 0;
                    status_t result = mOutput->stream->getLatency(&latency);
                    ALOGE_IF(result != OK,
                            "Error when retrieving output stream latency: %d", result);
                    size_t audioHALFrames = (latency * mSampleRate) / 1000;
                    int64_t framesWritten =
                            mBytesWritten / mOutput->getFrameSize();
                    track->presentationComplete(framesWritten, audioHALFrames);
                    track->presentationComplete(latency_l());
                    track->reset();
                    tracksToRemove->add(track);
                    // OFFLOADED stop resets frame counts.
+47 −7
Original line number Diff line number Diff line
@@ -650,7 +650,6 @@ AudioFlinger::PlaybackThread::Track::Track(
    mMainBuffer(thread->sinkBuffer()),
    mAuxBuffer(NULL),
    mAuxEffectId(0), mHasVolumeController(false),
    mPresentationCompleteFrames(0),
    mFrameMap(16 /* sink-frame-to-track-frame map memory */),
    mVolumeHandler(new media::VolumeHandler(sampleRate)),
    mOpPlayAudioMonitor(OpPlayAudioMonitor::createIfNeeded(attributionSource, attr, id(),
@@ -1462,6 +1461,7 @@ void AudioFlinger::PlaybackThread::Track::setAuxBuffer(int EffectId, int32_t *bu
    mAuxBuffer = buffer;
}

// presentationComplete verified by frames, used by Mixed tracks.
bool AudioFlinger::PlaybackThread::Track::presentationComplete(
        int64_t framesWritten, size_t audioHalFrames)
{
@@ -1480,30 +1480,70 @@ bool AudioFlinger::PlaybackThread::Track::presentationComplete(
            (long long)mPresentationCompleteFrames, (long long)framesWritten);
    if (mPresentationCompleteFrames == 0) {
        mPresentationCompleteFrames = framesWritten + audioHalFrames;
        ALOGV("%s(%d): presentationComplete() reset:"
        ALOGV("%s(%d): set:"
                " mPresentationCompleteFrames %lld audioHalFrames %zu",
                __func__, mId,
                (long long)mPresentationCompleteFrames, audioHalFrames);
    }

    bool complete;
    if (isOffloaded()) {
        complete = true;
    } else if (isDirect() || isFastTrack()) { // these do not go through linear map
    if (isFastTrack()) { // does not go through linear map
        complete = framesWritten >= (int64_t) mPresentationCompleteFrames;
        ALOGV("%s(%d): %s framesWritten:%lld  mPresentationCompleteFrames:%lld",
                __func__, mId, (complete ? "complete" : "waiting"),
                (long long) framesWritten, (long long) mPresentationCompleteFrames);
    } else {  // Normal tracks, OutputTracks, and PatchTracks
        complete = framesWritten >= (int64_t) mPresentationCompleteFrames
                && mAudioTrackServerProxy->isDrained();
    }

    if (complete) {
        triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
        mAudioTrackServerProxy->setStreamEndDone();
        notifyPresentationComplete();
        return true;
    }
    return false;
}

// presentationComplete checked by time, used by DirectTracks.
bool AudioFlinger::PlaybackThread::Track::presentationComplete(uint32_t latencyMs)
{
    // For Offloaded or Direct tracks.

    // For a direct track, we incorporated time based testing for presentationComplete.

    // For an offloaded track the HAL+h/w delay is variable so a HAL drain() is used
    // to detect when all frames have been played. In this case latencyMs isn't
    // useful because it doesn't always reflect whether there is data in the h/w
    // buffers, particularly if a track has been paused and resumed during draining

    constexpr float MIN_SPEED = 0.125f; // min speed scaling allowed for timely response.
    if (mPresentationCompleteTimeNs == 0) {
        mPresentationCompleteTimeNs = systemTime() + latencyMs * 1e6 / fmax(mSpeed, MIN_SPEED);
        ALOGV("%s(%d): set: latencyMs %u  mPresentationCompleteTimeNs:%lld",
                __func__, mId, latencyMs, (long long) mPresentationCompleteTimeNs);
    }

    bool complete;
    if (isOffloaded()) {
        complete = true;
    } else { // Direct
        complete = systemTime() >= mPresentationCompleteTimeNs;
        ALOGV("%s(%d): %s", __func__, mId, (complete ? "complete" : "waiting"));
    }
    if (complete) {
        notifyPresentationComplete();
        return true;
    }
    return false;
}

void AudioFlinger::PlaybackThread::Track::notifyPresentationComplete()
{
    // This only triggers once. TODO: should we enforce this?
    triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
    mAudioTrackServerProxy->setStreamEndDone();
}

void AudioFlinger::PlaybackThread::Track::triggerEvents(AudioSystem::sync_event_t type)
{
    for (size_t i = 0; i < mSyncEvents.size();) {