From 59fe010bcc072597852454a2ec53d7b0a2002a3b Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Fri, 27 Sep 2013 18:48:26 -0700 Subject: fix volume and effect enable delay on offloaded tracks Volume: add a method to wake up the mediaserver playback thread when a volume command is received on an offloaded track. Effects: call effect chain process on offloaded playback threads asynchronously from writes to allow effect state updates while waiting for async write callback. Bug: 10796540. Change-Id: Id2747ae88783575d1d7ffd6fc86fbd054ab2c739 --- services/audioflinger/AudioFlinger.h | 1 + services/audioflinger/Effects.cpp | 22 +++++++++++++++++----- services/audioflinger/PlaybackTracks.h | 1 + services/audioflinger/Threads.cpp | 11 ++++++++++- services/audioflinger/Tracks.cpp | 16 ++++++++++++++++ 5 files changed, 45 insertions(+), 6 deletions(-) (limited to 'services/audioflinger') diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h index b41d480..2aeb263 100644 --- a/services/audioflinger/AudioFlinger.h +++ b/services/audioflinger/AudioFlinger.h @@ -412,6 +412,7 @@ private: int target); virtual status_t setParameters(const String8& keyValuePairs); virtual status_t getTimestamp(AudioTimestamp& timestamp); + virtual void signal(); // signal playback thread for a change in control block virtual status_t onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags); diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp index 6e0354d..a8a5169 100644 --- a/services/audioflinger/Effects.cpp +++ b/services/audioflinger/Effects.cpp @@ -972,13 +972,20 @@ status_t AudioFlinger::EffectHandle::enable() } mEnabled = false; } else { - if (thread != 0 && !mEffect->isOffloadable()) { - if ((thread->type() == ThreadBase::OFFLOAD)) { + if (thread != 0) { + if (thread->type() == ThreadBase::OFFLOAD) { PlaybackThread *t = (PlaybackThread *)thread.get(); - t->invalidateTracks(AUDIO_STREAM_MUSIC); + Mutex::Autolock _l(t->mLock); + t->broadcast_l(); } - if (mEffect->sessionId() == AUDIO_SESSION_OUTPUT_MIX) { - thread->mAudioFlinger->onNonOffloadableGlobalEffectEnable(); + if (!mEffect->isOffloadable()) { + if (thread->type() == ThreadBase::OFFLOAD) { + PlaybackThread *t = (PlaybackThread *)thread.get(); + t->invalidateTracks(AUDIO_STREAM_MUSIC); + } + if (mEffect->sessionId() == AUDIO_SESSION_OUTPUT_MIX) { + thread->mAudioFlinger->onNonOffloadableGlobalEffectEnable(); + } } } } @@ -1009,6 +1016,11 @@ status_t AudioFlinger::EffectHandle::disable() sp thread = mEffect->thread().promote(); if (thread != 0) { thread->checkSuspendOnEffectEnabled(mEffect, false, mEffect->sessionId()); + if (thread->type() == ThreadBase::OFFLOAD) { + PlaybackThread *t = (PlaybackThread *)thread.get(); + Mutex::Autolock _l(t->mLock); + t->broadcast_l(); + } } return status; diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h index f7ad6b1..a2e2511 100644 --- a/services/audioflinger/PlaybackTracks.h +++ b/services/audioflinger/PlaybackTracks.h @@ -60,6 +60,7 @@ public: int16_t *mainBuffer() const { return mMainBuffer; } int auxEffectId() const { return mAuxEffectId; } virtual status_t getTimestamp(AudioTimestamp& timestamp); + void signal(); // implement FastMixerState::VolumeProvider interface virtual uint32_t getVolumeLR(); diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp index 2d9d485..187adf3 100644 --- a/services/audioflinger/Threads.cpp +++ b/services/audioflinger/Threads.cpp @@ -2238,12 +2238,21 @@ bool AudioFlinger::PlaybackThread::threadLoop() } // only process effects if we're going to write - if (sleepTime == 0) { + if (sleepTime == 0 && mType != OFFLOAD) { for (size_t i = 0; i < effectChains.size(); i ++) { effectChains[i]->process_l(); } } } + // Process effect chains for offloaded thread even if no audio + // was read from audio track: process only updates effect state + // and thus does have to be synchronized with audio writes but may have + // to be called while waiting for async write callback + if (mType == OFFLOAD) { + for (size_t i = 0; i < effectChains.size(); i ++) { + effectChains[i]->process_l(); + } + } // enable changes in effect chain unlockEffectChains(effectChains); diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp index d8d325d..9c6e724 100644 --- a/services/audioflinger/Tracks.cpp +++ b/services/audioflinger/Tracks.cpp @@ -288,6 +288,12 @@ status_t AudioFlinger::TrackHandle::getTimestamp(AudioTimestamp& timestamp) return mTrack->getTimestamp(timestamp); } + +void AudioFlinger::TrackHandle::signal() +{ + return mTrack->signal(); +} + status_t AudioFlinger::TrackHandle::onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { @@ -926,6 +932,16 @@ void AudioFlinger::PlaybackThread::Track::invalidate() mIsInvalid = true; } +void AudioFlinger::PlaybackThread::Track::signal() +{ + sp thread = mThread.promote(); + if (thread != 0) { + PlaybackThread *t = (PlaybackThread *)thread.get(); + Mutex::Autolock _l(t->mLock); + t->broadcast_l(); + } +} + // ---------------------------------------------------------------------------- sp -- cgit v1.1