summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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;