From af76b10d0bce63c7e5896ddbe6fe897ed0110186 Mon Sep 17 00:00:00 2001 From: Weiyin Jiang Date: Mon, 7 Mar 2016 22:12:56 +0800 Subject: audio: allow standby for direct track Delay standby for offload track use case is not suitable for direct track in PCM format, because player torn down doesn't necessarily happen. To avoid AP looping infinitely, allow standby right after direct track in PCM format is paused. CRs-Fixed: 986784 Change-Id: Id0026ac9891a12acc4affa446b2bc841559fcc28 --- services/audioflinger/Threads.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'services/audioflinger/Threads.cpp') diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp index c3ee6c2..6f223af 100644 --- a/services/audioflinger/Threads.cpp +++ b/services/audioflinger/Threads.cpp @@ -4863,6 +4863,10 @@ bool AudioFlinger::DirectOutputThread::shouldStandby_l() bool trackPaused = false; bool trackStopped = false; + if ((mType == DIRECT) && audio_is_linear_pcm(mFormat) && !usesHwAvSync()) { + return !mStandby; + } + // do not put the HAL in standby when paused. AwesomePlayer clear the offloaded AudioTrack // after a timeout and we will enter standby then. if (mTracks.size() > 0) { -- cgit v1.1 From e5c901e16fdb7ed1d37bd7aa1232973588692a91 Mon Sep 17 00:00:00 2001 From: Weiyin Jiang Date: Fri, 26 Feb 2016 18:07:49 +0800 Subject: audio: use offload standby delay for direct pcm Default standby delay for legacy direct is too aggressive for track offloaded use case. Using offload standby delay instead, which allows sufficient time for track transition before standby the output. CRs-Fixed: 982822 Change-Id: Ifd0e39c5b3fe4a4af9f444dbbad21ef1e1a5edfa --- services/audioflinger/Threads.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'services/audioflinger/Threads.cpp') diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp index 6f223af..e1e4980 100644 --- a/services/audioflinger/Threads.cpp +++ b/services/audioflinger/Threads.cpp @@ -4987,6 +4987,8 @@ void AudioFlinger::DirectOutputThread::cacheParameters_l() mStandbyDelayNs = 0; } else if ((mType == OFFLOAD) && !audio_is_linear_pcm(mFormat)) { mStandbyDelayNs = kOffloadStandbyDelayNs; + } else if (mType == DIRECT && mIsDirectPcm) { + mStandbyDelayNs = kOffloadStandbyDelayNs; } else { mStandbyDelayNs = microseconds(mActiveSleepTimeUs*2); } -- cgit v1.1 From e72652f039b9067f9e747d70184507d41ef1f6d7 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Wed, 2 Dec 2015 11:40:09 -0800 Subject: Don't place large objects on the stack Bug: 25020816 Change-Id: Ife4da9fc3000e645f654f2eb28b37ad3a89d61f9 --- services/audioflinger/Threads.cpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'services/audioflinger/Threads.cpp') diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp index e1e4980..ecdbf43 100644 --- a/services/audioflinger/Threads.cpp +++ b/services/audioflinger/Threads.cpp @@ -4470,8 +4470,12 @@ void AudioFlinger::MixerThread::dumpInternals(int fd, const Vector& ar dprintf(fd, " AudioMixer tracks: 0x%08x\n", mAudioMixer->trackNames()); // Make a non-atomic copy of fast mixer dump state so it won't change underneath us - const FastMixerDumpState copy(mFastMixerDumpState); - copy.dump(fd); + // while we are dumping it. It may be inconsistent, but it won't mutate! + // This is a large object so we place it on the heap. + // FIXME 25972958: Need an intelligent copy constructor that does not touch unused pages. + const FastMixerDumpState *copy = new FastMixerDumpState(mFastMixerDumpState); + copy->dump(fd); + delete copy; #ifdef STATE_QUEUE_DUMP // Similar for state queue @@ -6460,9 +6464,13 @@ void AudioFlinger::RecordThread::dumpInternals(int fd, const Vector& a dprintf(fd, " Fast capture thread: %s\n", hasFastCapture() ? "yes" : "no"); dprintf(fd, " Fast track available: %s\n", mFastTrackAvail ? "yes" : "no"); - // Make a non-atomic copy of fast capture dump state so it won't change underneath us - const FastCaptureDumpState copy(mFastCaptureDumpState); - copy.dump(fd); + // Make a non-atomic copy of fast capture dump state so it won't change underneath us + // while we are dumping it. It may be inconsistent, but it won't mutate! + // This is a large object so we place it on the heap. + // FIXME 25972958: Need an intelligent copy constructor that does not touch unused pages. + const FastCaptureDumpState *copy = new FastCaptureDumpState(mFastCaptureDumpState); + copy->dump(fd); + delete copy; } void AudioFlinger::RecordThread::dumpTracks(int fd, const Vector& args __unused) -- cgit v1.1 From 6fde774471629832951e9b9b2e0d758e10f6431d Mon Sep 17 00:00:00 2001 From: Haynes Mathew George Date: Tue, 3 May 2016 16:34:26 -0700 Subject: audioflinger: set flush pending on invalidating offload track On invalidating an offload track, the IAudioTrack instance is destroyed and the offload output is released. If it so happens that APM::getOutputForAttr for the new IAudioTrack is called before OffloadThread::prepareTracks_l checks and removes an invalid track, the same output can get reused. The side effect of this is data present in HAL and below from before the invalidate will be rendered before data from the new seek position is rendered. This is unexpected. To fix this, set hint to issue flush when an offload track is invalidated. Bug: 28566885 CRs-Fixed: 1002438 Change-Id: Ib6c38a3abb600598b87591bac90d03b7150d5216 --- services/audioflinger/Threads.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'services/audioflinger/Threads.cpp') diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp index ecdbf43..ee5dc24 100644 --- a/services/audioflinger/Threads.cpp +++ b/services/audioflinger/Threads.cpp @@ -2574,11 +2574,10 @@ void AudioFlinger::PlaybackThread::cacheParameters_l() } } -void AudioFlinger::PlaybackThread::invalidateTracks(audio_stream_type_t streamType) +void AudioFlinger::PlaybackThread::invalidateTracks_l(audio_stream_type_t streamType) { ALOGV("MixerThread::invalidateTracks() mixer %p, streamType %d, mTracks.size %d", this, streamType, mTracks.size()); - Mutex::Autolock _l(mLock); size_t size = mTracks.size(); for (size_t i = 0; i < size; i++) { @@ -2589,6 +2588,12 @@ void AudioFlinger::PlaybackThread::invalidateTracks(audio_stream_type_t streamTy } } +void AudioFlinger::PlaybackThread::invalidateTracks(audio_stream_type_t streamType) +{ + Mutex::Autolock _l(mLock); + invalidateTracks_l(streamType); +} + status_t AudioFlinger::PlaybackThread::addEffectChain_l(const sp& chain) { int session = chain->sessionId(); @@ -5371,6 +5376,13 @@ void AudioFlinger::OffloadThread::flushHw_l() } } +void AudioFlinger::OffloadThread::invalidateTracks(audio_stream_type_t streamType) +{ + Mutex::Autolock _l(mLock); + mFlushPending = true; + PlaybackThread::invalidateTracks_l(streamType); +} + // ---------------------------------------------------------------------------- AudioFlinger::DuplicatingThread::DuplicatingThread(const sp& audioFlinger, -- cgit v1.1 From e4575aeb5d66f71b6ef6c611570ea96df81c1246 Mon Sep 17 00:00:00 2001 From: Haynes Mathew George Date: Thu, 5 May 2016 19:02:06 -0700 Subject: audioflinger: Always process volume commands from a latest track Process them irrespective of whether the track is invalid. Ignoring to do so may lead to glitches/loud bursts in audio when a new track reuses the same output. CRs-Fixed: 1002448 Change-Id: I9afbdd221db3a7311eb0ec8bb75852cf5409084e --- services/audioflinger/Threads.cpp | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) (limited to 'services/audioflinger/Threads.cpp') diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp index ee5dc24..e5e8bdb 100644 --- a/services/audioflinger/Threads.cpp +++ b/services/audioflinger/Threads.cpp @@ -5169,15 +5169,9 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::OffloadThread::prepareTr if (track->isInvalid()) { ALOGW("An invalidated track shouldn't be in active list"); tracksToRemove->add(track); - continue; - } - - if (track->mState == TrackBase::IDLE) { + } else if (track->mState == TrackBase::IDLE) { ALOGW("An idle track shouldn't be in active list"); - continue; - } - - if (track->isPausing()) { + } else if (track->isPausing()) { track->setPaused(); if (last) { if (mHwSupportsPause && !mHwPaused) { @@ -5200,7 +5194,7 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::OffloadThread::prepareTr if (last) { mFlushPending = true; } - } else if (track->isResumePending()){ + } else if (track->isResumePending()) { track->resumeAck(); if (last) { if (mPausedBytesRemaining) { -- cgit v1.1