diff options
author | Eric Laurent <elaurent@google.com> | 2014-10-02 19:41:47 -0700 |
---|---|---|
committer | Eric Laurent <elaurent@google.com> | 2014-10-02 19:41:47 -0700 |
commit | 1b92868010b5c1409692a86f6b27e4a265b64c1a (patch) | |
tree | aa514a65d23d1bebbceef49cc6b7f2662c7bad76 /services/audioflinger | |
parent | d8b03abf1d003e2940a19f0071ea2892689dd10e (diff) | |
download | frameworks_av-1b92868010b5c1409692a86f6b27e4a265b64c1a.zip frameworks_av-1b92868010b5c1409692a86f6b27e4a265b64c1a.tar.gz frameworks_av-1b92868010b5c1409692a86f6b27e4a265b64c1a.tar.bz2 |
audioflinger: fix pre processing transfer between record threads.
Fix two problems remaining with pre processing effects transfer from
one record thread to the next in case of tear down due to device connection:
1 - the enabled state of the effects was not communicated to the new HAL
input stream.
2 - the effects saved in orphan chains list were not transfered to the
new thread when a AudioRecord was created.
Bug: 17757378.
Change-Id: I0923c98470db3b51154dc89846157780a4c21e86
Diffstat (limited to 'services/audioflinger')
-rw-r--r-- | services/audioflinger/AudioFlinger.cpp | 48 | ||||
-rw-r--r-- | services/audioflinger/Effects.cpp | 36 | ||||
-rw-r--r-- | services/audioflinger/Effects.h | 3 | ||||
-rw-r--r-- | services/audioflinger/Threads.cpp | 4 |
4 files changed, 76 insertions, 15 deletions
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp index e200857..e48af20 100644 --- a/services/audioflinger/AudioFlinger.cpp +++ b/services/audioflinger/AudioFlinger.cpp @@ -1436,6 +1436,16 @@ sp<IAudioRecord> AudioFlinger::openRecord( IPCThreadState::self()->getCallingUid(), flags, tid, &lStatus); LOG_ALWAYS_FATAL_IF((lStatus == NO_ERROR) && (recordTrack == 0)); + + if (lStatus == NO_ERROR) { + // Check if one effect chain was awaiting for an AudioRecord to be created on this + // session and move it to this thread. + sp<EffectChain> chain = getOrphanEffectChain_l((audio_session_t)lSessionId); + if (chain != 0) { + Mutex::Autolock _l(thread->mLock); + thread->addEffectChain_l(chain); + } + } } if (lStatus != NO_ERROR) { @@ -2034,14 +2044,41 @@ status_t AudioFlinger::closeInput_nonvirtual(audio_io_handle_t input) } ALOGV("closeInput() %d", input); + + // If we still have effect chains, it means that a client still holds a handle + // on at least one effect. We must either move the chain to an existing thread with the + // same session ID or put it aside in case a new record thread is opened for a + // new capture on the same session + sp<EffectChain> chain; { - // If we still have effect chains, it means that a client still holds a handle - // on at least one effect. We must keep the chain alive in case a new record - // thread is opened for a new capture on the same session Mutex::Autolock _sl(thread->mLock); Vector< sp<EffectChain> > effectChains = thread->getEffectChains_l(); - for (size_t i = 0; i < effectChains.size(); i++) { - putOrphanEffectChain_l(effectChains[i]); + // Note: maximum one chain per record thread + if (effectChains.size() != 0) { + chain = effectChains[0]; + } + } + if (chain != 0) { + // first check if a record thread is already opened with a client on the same session. + // This should only happen in case of overlap between one thread tear down and the + // creation of its replacement + size_t i; + for (i = 0; i < mRecordThreads.size(); i++) { + sp<RecordThread> t = mRecordThreads.valueAt(i); + if (t == thread) { + continue; + } + if (t->hasAudioSession(chain->sessionId()) != 0) { + Mutex::Autolock _l(t->mLock); + ALOGV("closeInput() found thread %d for effect session %d", + t->id(), chain->sessionId()); + t->addEffectChain_l(chain); + break; + } + } + // put the chain aside if we could not find a record thread with the same session id. + if (i == mRecordThreads.size()) { + putOrphanEffectChain_l(chain); } } audioConfigChanged(AudioSystem::INPUT_CLOSED, input, NULL); @@ -2478,6 +2515,7 @@ sp<IEffect> AudioFlinger::createEffect( // session and used it instead of creating a new one. sp<EffectChain> chain = getOrphanEffectChain_l((audio_session_t)sessionId); if (chain != 0) { + Mutex::Autolock _l(thread->mLock); thread->addEffectChain_l(chain); } } diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp index 4678880..bcaf8ae 100644 --- a/services/audioflinger/Effects.cpp +++ b/services/audioflinger/Effects.cpp @@ -440,6 +440,20 @@ status_t AudioFlinger::EffectModule::init() return status; } +void AudioFlinger::EffectModule::addEffectToHal_l() +{ + if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC || + (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC) { + sp<ThreadBase> thread = mThread.promote(); + if (thread != 0) { + audio_stream_t *stream = thread->stream(); + if (stream != NULL) { + stream->add_audio_effect(stream, mEffectInterface); + } + } + } +} + status_t AudioFlinger::EffectModule::start() { Mutex::Autolock _l(mLock); @@ -466,16 +480,7 @@ status_t AudioFlinger::EffectModule::start_l() status = cmdStatus; } if (status == 0) { - if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC || - (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC) { - sp<ThreadBase> thread = mThread.promote(); - if (thread != 0) { - audio_stream_t *stream = thread->stream(); - if (stream != NULL) { - stream->add_audio_effect(stream, mEffectInterface); - } - } - } + addEffectToHal_l(); sp<EffectChain> chain = mChain.promote(); if (chain != 0) { chain->forceVolume(); @@ -1696,6 +1701,17 @@ bool AudioFlinger::EffectChain::setVolume_l(uint32_t *left, uint32_t *right) return hasControl; } +void AudioFlinger::EffectChain::syncHalEffectsState() +{ + Mutex::Autolock _l(mLock); + for (size_t i = 0; i < mEffects.size(); i++) { + if (mEffects[i]->state() == EffectModule::ACTIVE || + mEffects[i]->state() == EffectModule::STOPPING) { + mEffects[i]->addEffectToHal_l(); + } + } +} + void AudioFlinger::EffectChain::dump(int fd, const Vector<String16>& args) { const size_t SIZE = 256; diff --git a/services/audioflinger/Effects.h b/services/audioflinger/Effects.h index b87a1fd..6f93f81 100644 --- a/services/audioflinger/Effects.h +++ b/services/audioflinger/Effects.h @@ -119,6 +119,7 @@ public: { return (mDescriptor.flags & EFFECT_FLAG_OFFLOAD_SUPPORTED) != 0; } status_t setOffloaded(bool offloaded, audio_io_handle_t io); bool isOffloaded() const; + void addEffectToHal_l(); void dump(int fd, const Vector<String16>& args); @@ -325,6 +326,8 @@ public: // we are the only observers. bool isVolumeForced() { return (android_atomic_acquire_cas(true, false, &mForceVolume) == 0); } + void syncHalEffectsState(); + void dump(int fd, const Vector<String16>& args); protected: diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp index 12e09ab..bdf74d5 100644 --- a/services/audioflinger/Threads.cpp +++ b/services/audioflinger/Threads.cpp @@ -6192,6 +6192,10 @@ status_t AudioFlinger::RecordThread::addEffectChain_l(const sp<EffectChain>& cha checkSuspendOnAddEffectChain_l(chain); + // make sure enabled pre processing effects state is communicated to the HAL as we + // just moved them to a new input stream. + chain->syncHalEffectsState(); + mEffectChains.add(chain); return NO_ERROR; |