summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Laurent <elaurent@google.com>2014-10-02 19:41:47 -0700
committerEric Laurent <elaurent@google.com>2014-10-02 19:41:47 -0700
commit1b92868010b5c1409692a86f6b27e4a265b64c1a (patch)
treeaa514a65d23d1bebbceef49cc6b7f2662c7bad76
parentd8b03abf1d003e2940a19f0071ea2892689dd10e (diff)
downloadframeworks_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
-rw-r--r--services/audioflinger/AudioFlinger.cpp48
-rw-r--r--services/audioflinger/Effects.cpp36
-rw-r--r--services/audioflinger/Effects.h3
-rw-r--r--services/audioflinger/Threads.cpp4
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;