audioflinger: add check for effect vs thread compatibility am: 4c415062ad
am: ad67b138fc
Change-Id: I38015a85b7df2d620daa2c9e5d7435de510a8fbe
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index a757aac..35a120a 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -660,7 +660,7 @@
sp<PlaybackThread> t = mPlaybackThreads.valueAt(i);
if (mPlaybackThreads.keyAt(i) != output) {
uint32_t sessions = t->hasAudioSession(lSessionId);
- if (sessions & PlaybackThread::EFFECT_SESSION) {
+ if (sessions & ThreadBase::EFFECT_SESSION) {
effectThread = t.get();
break;
}
@@ -1766,7 +1766,7 @@
for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
sp<PlaybackThread> thread = mPlaybackThreads.valueAt(i);
uint32_t sessions = thread->hasAudioSession(sessionId);
- if (sessions & PlaybackThread::TRACK_SESSION) {
+ if (sessions & ThreadBase::TRACK_SESSION) {
AudioParameter param = AudioParameter();
param.addInt(String8(AUDIO_PARAMETER_STREAM_HW_AV_SYNC), value);
thread->setParameters(param.toString());
@@ -2824,14 +2824,11 @@
return INVALID_OPERATION;
}
- // Check whether the destination thread has a channel count of FCC_2, which is
- // currently required for (most) effects. Prevent moving the effect chain here rather
- // than disabling the addEffect_l() call in dstThread below.
- if ((dstThread->type() == ThreadBase::MIXER || dstThread->isDuplicating()) &&
- dstThread->mChannelCount != FCC_2) {
+ // Check whether the destination thread and all effects in the chain are compatible
+ if (!chain->isCompatibleWithThread_l(dstThread)) {
ALOGW("moveEffectChain_l() effect chain failed because"
- " destination thread %p channel count(%u) != %u",
- dstThread, dstThread->mChannelCount, FCC_2);
+ " destination thread %p is not compatible with effects in the chain",
+ dstThread);
return INVALID_OPERATION;
}
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 00304b2..a9aafd8 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -1960,4 +1960,27 @@
}
}
+bool AudioFlinger::EffectChain::hasSoftwareEffect() const
+{
+ Mutex::Autolock _l(mLock);
+ for (size_t i = 0; i < mEffects.size(); i++) {
+ if (mEffects[i]->isImplementationSoftware()) {
+ return true;
+ }
+ }
+ return false;
+}
+
+// isCompatibleWithThread_l() must be called with thread->mLock held
+bool AudioFlinger::EffectChain::isCompatibleWithThread_l(const sp<ThreadBase>& thread) const
+{
+ Mutex::Autolock _l(mLock);
+ for (size_t i = 0; i < mEffects.size(); i++) {
+ if (thread->checkEffectCompatibility_l(&(mEffects[i]->desc()), mSessionId) != NO_ERROR) {
+ return false;
+ }
+ }
+ return true;
+}
+
} // namespace android
diff --git a/services/audioflinger/Effects.h b/services/audioflinger/Effects.h
index bc9bc94..3b62652 100644
--- a/services/audioflinger/Effects.h
+++ b/services/audioflinger/Effects.h
@@ -117,6 +117,8 @@
void unlock() { mLock.unlock(); }
bool isOffloadable() const
{ return (mDescriptor.flags & EFFECT_FLAG_OFFLOAD_SUPPORTED) != 0; }
+ bool isImplementationSoftware() const
+ { return (mDescriptor.flags & EFFECT_FLAG_HW_ACC_MASK) == 0; }
status_t setOffloaded(bool offloaded, audio_io_handle_t io);
bool isOffloaded() const;
void addEffectToHal_l();
@@ -330,6 +332,11 @@
void syncHalEffectsState();
+ bool hasSoftwareEffect() const;
+
+ // isCompatibleWithThread_l() must be called with thread->mLock held
+ bool isCompatibleWithThread_l(const sp<ThreadBase>& thread) const;
+
void dump(int fd, const Vector<String16>& args);
protected:
@@ -361,30 +368,30 @@
void setThread(const sp<ThreadBase>& thread);
- wp<ThreadBase> mThread; // parent mixer thread
- Mutex mLock; // mutex protecting effect list
- Vector< sp<EffectModule> > mEffects; // list of effect modules
- audio_session_t mSessionId; // audio session ID
- int16_t *mInBuffer; // chain input buffer
- int16_t *mOutBuffer; // chain output buffer
+ wp<ThreadBase> mThread; // parent mixer thread
+ mutable Mutex mLock; // mutex protecting effect list
+ Vector< sp<EffectModule> > mEffects; // list of effect modules
+ audio_session_t mSessionId; // audio session ID
+ int16_t *mInBuffer; // chain input buffer
+ int16_t *mOutBuffer; // chain output buffer
// 'volatile' here means these are accessed with atomic operations instead of mutex
volatile int32_t mActiveTrackCnt; // number of active tracks connected
volatile int32_t mTrackCnt; // number of tracks connected
- int32_t mTailBufferCount; // current effect tail buffer count
- int32_t mMaxTailBuffers; // maximum effect tail buffers
- bool mOwnInBuffer; // true if the chain owns its input buffer
- int mVolumeCtrlIdx; // index of insert effect having control over volume
- uint32_t mLeftVolume; // previous volume on left channel
- uint32_t mRightVolume; // previous volume on right channel
- uint32_t mNewLeftVolume; // new volume on left channel
- uint32_t mNewRightVolume; // new volume on right channel
- uint32_t mStrategy; // strategy for this effect chain
- // mSuspendedEffects lists all effects currently suspended in the chain.
- // Use effect type UUID timelow field as key. There is no real risk of identical
- // timeLow fields among effect type UUIDs.
- // Updated by updateSuspendedSessions_l() only.
- KeyedVector< int, sp<SuspendedEffectDesc> > mSuspendedEffects;
+ int32_t mTailBufferCount; // current effect tail buffer count
+ int32_t mMaxTailBuffers; // maximum effect tail buffers
+ bool mOwnInBuffer; // true if the chain owns its input buffer
+ int mVolumeCtrlIdx; // index of insert effect having control over volume
+ uint32_t mLeftVolume; // previous volume on left channel
+ uint32_t mRightVolume; // previous volume on right channel
+ uint32_t mNewLeftVolume; // new volume on left channel
+ uint32_t mNewRightVolume; // new volume on right channel
+ uint32_t mStrategy; // strategy for this effect chain
+ // mSuspendedEffects lists all effects currently suspended in the chain.
+ // Use effect type UUID timelow field as key. There is no real risk of identical
+ // timeLow fields among effect type UUIDs.
+ // Updated by updateSuspendedSessions_l() only.
+ KeyedVector< int, sp<SuspendedEffectDesc> > mSuspendedEffects;
volatile int32_t mForceVolume; // force next volume command because a new effect was enabled
};
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index fb1d2b0..d721270 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -1256,6 +1256,135 @@
}
}
+// checkEffectCompatibility_l() must be called with ThreadBase::mLock held
+status_t AudioFlinger::RecordThread::checkEffectCompatibility_l(
+ const effect_descriptor_t *desc, audio_session_t sessionId)
+{
+ // No global effect sessions on record threads
+ if (sessionId == AUDIO_SESSION_OUTPUT_MIX || sessionId == AUDIO_SESSION_OUTPUT_STAGE) {
+ ALOGW("checkEffectCompatibility_l(): global effect %s on record thread %s",
+ desc->name, mThreadName);
+ return BAD_VALUE;
+ }
+ // only pre processing effects on record thread
+ if ((desc->flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_PRE_PROC) {
+ ALOGW("checkEffectCompatibility_l(): non pre processing effect %s on record thread %s",
+ desc->name, mThreadName);
+ return BAD_VALUE;
+ }
+ audio_input_flags_t flags = mInput->flags;
+ if (hasFastCapture() || (flags & AUDIO_INPUT_FLAG_FAST)) {
+ if (flags & AUDIO_INPUT_FLAG_RAW) {
+ ALOGW("checkEffectCompatibility_l(): effect %s on record thread %s in raw mode",
+ desc->name, mThreadName);
+ return BAD_VALUE;
+ }
+ if ((desc->flags & EFFECT_FLAG_HW_ACC_TUNNEL) == 0) {
+ ALOGW("checkEffectCompatibility_l(): non HW effect %s on record thread %s in fast mode",
+ desc->name, mThreadName);
+ return BAD_VALUE;
+ }
+ }
+ return NO_ERROR;
+}
+
+// checkEffectCompatibility_l() must be called with ThreadBase::mLock held
+status_t AudioFlinger::PlaybackThread::checkEffectCompatibility_l(
+ const effect_descriptor_t *desc, audio_session_t sessionId)
+{
+ // no preprocessing on playback threads
+ if ((desc->flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC) {
+ ALOGW("checkEffectCompatibility_l(): pre processing effect %s created on playback"
+ " thread %s", desc->name, mThreadName);
+ return BAD_VALUE;
+ }
+
+ switch (mType) {
+ case MIXER: {
+ // Reject any effect on mixer multichannel sinks.
+ // TODO: fix both format and multichannel issues with effects.
+ if (mChannelCount != FCC_2) {
+ ALOGW("checkEffectCompatibility_l(): effect %s for multichannel(%d) on MIXER"
+ " thread %s", desc->name, mChannelCount, mThreadName);
+ return BAD_VALUE;
+ }
+ audio_output_flags_t flags = mOutput->flags;
+ if (hasFastMixer() || (flags & AUDIO_OUTPUT_FLAG_FAST)) {
+ if (sessionId == AUDIO_SESSION_OUTPUT_MIX) {
+ // global effects are applied only to non fast tracks if they are SW
+ if ((desc->flags & EFFECT_FLAG_HW_ACC_TUNNEL) == 0) {
+ break;
+ }
+ } else if (sessionId == AUDIO_SESSION_OUTPUT_STAGE) {
+ // only post processing on output stage session
+ if ((desc->flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_POST_PROC) {
+ ALOGW("checkEffectCompatibility_l(): non post processing effect %s not allowed"
+ " on output stage session", desc->name);
+ return BAD_VALUE;
+ }
+ } else {
+ // no restriction on effects applied on non fast tracks
+ if ((hasAudioSession_l(sessionId) & ThreadBase::FAST_SESSION) == 0) {
+ break;
+ }
+ }
+ if (flags & AUDIO_OUTPUT_FLAG_RAW) {
+ ALOGW("checkEffectCompatibility_l(): effect %s on playback thread in raw mode",
+ desc->name);
+ return BAD_VALUE;
+ }
+ if ((desc->flags & EFFECT_FLAG_HW_ACC_TUNNEL) == 0) {
+ ALOGW("checkEffectCompatibility_l(): non HW effect %s on playback thread"
+ " in fast mode", desc->name);
+ return BAD_VALUE;
+ }
+ }
+ } break;
+ case OFFLOAD:
+ // only offloadable effects on offload thread
+ if ((desc->flags & EFFECT_FLAG_OFFLOAD_MASK) != EFFECT_FLAG_OFFLOAD_SUPPORTED) {
+ ALOGW("checkEffectCompatibility_l(): non offloadable effect %s created on"
+ " OFFLOAD thread %s", desc->name, mThreadName);
+ return BAD_VALUE;
+ }
+ break;
+ case DIRECT:
+ // Reject any effect on Direct output threads for now, since the format of
+ // mSinkBuffer is not guaranteed to be compatible with effect processing (PCM 16 stereo).
+ ALOGW("checkEffectCompatibility_l(): effect %s on DIRECT output thread %s",
+ desc->name, mThreadName);
+ return BAD_VALUE;
+ case DUPLICATING:
+ // Reject any effect on mixer multichannel sinks.
+ // TODO: fix both format and multichannel issues with effects.
+ if (mChannelCount != FCC_2) {
+ ALOGW("checkEffectCompatibility_l(): effect %s for multichannel(%d)"
+ " on DUPLICATING thread %s", desc->name, mChannelCount, mThreadName);
+ return BAD_VALUE;
+ }
+ if ((sessionId == AUDIO_SESSION_OUTPUT_STAGE) || (sessionId == AUDIO_SESSION_OUTPUT_MIX)) {
+ ALOGW("checkEffectCompatibility_l(): global effect %s on DUPLICATING"
+ " thread %s", desc->name, mThreadName);
+ return BAD_VALUE;
+ }
+ if ((desc->flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC) {
+ ALOGW("checkEffectCompatibility_l(): post processing effect %s on"
+ " DUPLICATING thread %s", desc->name, mThreadName);
+ return BAD_VALUE;
+ }
+ if ((desc->flags & EFFECT_FLAG_HW_ACC_TUNNEL) != 0) {
+ ALOGW("checkEffectCompatibility_l(): HW tunneled effect %s on"
+ " DUPLICATING thread %s", desc->name, mThreadName);
+ return BAD_VALUE;
+ }
+ break;
+ default:
+ LOG_ALWAYS_FATAL("checkEffectCompatibility_l(): wrong thread type %d", mType);
+ }
+
+ return NO_ERROR;
+}
+
// ThreadBase::createEffect_l() must be called with AudioFlinger::mLock held
sp<AudioFlinger::EffectHandle> AudioFlinger::ThreadBase::createEffect_l(
const sp<AudioFlinger::Client>& client,
@@ -1280,54 +1409,16 @@
goto Exit;
}
- // Reject any effect on Direct output threads for now, since the format of
- // mSinkBuffer is not guaranteed to be compatible with effect processing (PCM 16 stereo).
- if (mType == DIRECT) {
- ALOGW("createEffect_l() Cannot add effect %s on Direct output type thread %s",
- desc->name, mThreadName);
- lStatus = BAD_VALUE;
- goto Exit;
- }
-
- // Reject any effect on mixer or duplicating multichannel sinks.
- // TODO: fix both format and multichannel issues with effects.
- if ((mType == MIXER || mType == DUPLICATING) && mChannelCount != FCC_2) {
- ALOGW("createEffect_l() Cannot add effect %s for multichannel(%d) %s threads",
- desc->name, mChannelCount, mType == MIXER ? "MIXER" : "DUPLICATING");
- lStatus = BAD_VALUE;
- goto Exit;
- }
-
- // Allow global effects only on offloaded and mixer threads
- if (sessionId == AUDIO_SESSION_OUTPUT_MIX) {
- switch (mType) {
- case MIXER:
- case OFFLOAD:
- break;
- case DIRECT:
- case DUPLICATING:
- case RECORD:
- default:
- ALOGW("createEffect_l() Cannot add global effect %s on thread %s",
- desc->name, mThreadName);
- lStatus = BAD_VALUE;
- goto Exit;
- }
- }
-
- // Only Pre processor effects are allowed on input threads and only on input threads
- if ((mType == RECORD) != ((desc->flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC)) {
- ALOGW("createEffect_l() effect %s (flags %08x) created on wrong thread type %d",
- desc->name, desc->flags, mType);
- lStatus = BAD_VALUE;
- goto Exit;
- }
-
ALOGV("createEffect_l() thread %p effect %s on session %d", this, desc->name, sessionId);
{ // scope for mLock
Mutex::Autolock _l(mLock);
+ lStatus = checkEffectCompatibility_l(desc, sessionId);
+ if (lStatus != NO_ERROR) {
+ goto Exit;
+ }
+
// check for existing effect chain with the requested audio session
chain = getEffectChain_l(sessionId);
if (chain == 0) {
@@ -1804,8 +1895,44 @@
}
frameCount = max(frameCount, mFrameCount * sFastTrackMultiplier); // incl framecount 0
}
- ALOGV("AUDIO_OUTPUT_FLAG_FAST accepted: frameCount=%zu mFrameCount=%zu",
- frameCount, mFrameCount);
+
+ // check compatibility with audio effects.
+ { // scope for mLock
+ Mutex::Autolock _l(mLock);
+ // do not accept RAW flag if post processing are present. Note that post processing on
+ // a fast mixer are necessarily hardware
+ sp<EffectChain> chain = getEffectChain_l(AUDIO_SESSION_OUTPUT_STAGE);
+ if (chain != 0) {
+ ALOGV_IF((flags & AUDIO_OUTPUT_FLAG_RAW) != 0,
+ "AUDIO_OUTPUT_FLAG_RAW denied: post processing effect present");
+ *flags = (audio_output_flags_t)(*flags & ~AUDIO_OUTPUT_FLAG_RAW);
+ }
+ // Do not accept FAST flag if software global effects are present
+ chain = getEffectChain_l(AUDIO_SESSION_OUTPUT_MIX);
+ if (chain != 0) {
+ ALOGV_IF((flags & AUDIO_OUTPUT_FLAG_RAW) != 0,
+ "AUDIO_OUTPUT_FLAG_RAW denied: global effect present");
+ *flags = (audio_output_flags_t)(*flags & ~AUDIO_OUTPUT_FLAG_RAW);
+ if (chain->hasSoftwareEffect()) {
+ ALOGV("AUDIO_OUTPUT_FLAG_FAST denied: software global effect present");
+ *flags = (audio_output_flags_t)(*flags & ~AUDIO_OUTPUT_FLAG_FAST);
+ }
+ }
+ // Do not accept FAST flag if the session has software effects
+ chain = getEffectChain_l(sessionId);
+ if (chain != 0) {
+ ALOGV_IF((flags & AUDIO_OUTPUT_FLAG_RAW) != 0,
+ "AUDIO_OUTPUT_FLAG_RAW denied: effect present on session");
+ *flags = (audio_output_flags_t)(*flags & ~AUDIO_OUTPUT_FLAG_RAW);
+ if (chain->hasSoftwareEffect()) {
+ ALOGV("AUDIO_OUTPUT_FLAG_FAST denied: software effect present on session");
+ *flags = (audio_output_flags_t)(*flags & ~AUDIO_OUTPUT_FLAG_FAST);
+ }
+ }
+ }
+ ALOGV_IF((flags & AUDIO_OUTPUT_FLAG_FAST) != 0,
+ "AUDIO_OUTPUT_FLAG_FAST accepted: frameCount=%zu mFrameCount=%zu",
+ frameCount, mFrameCount);
} else {
ALOGV("AUDIO_OUTPUT_FLAG_FAST denied: sharedBuffer=%p frameCount=%zu "
"mFrameCount=%zu format=%#x mFormat=%#x isLinear=%d channelMask=%#x "
@@ -1814,7 +1941,7 @@
sharedBuffer.get(), frameCount, mFrameCount, format, mFormat,
audio_is_linear_pcm(format),
channelMask, sampleRate, mSampleRate, hasFastMixer(), tid, mFastTrackAvailMask);
- *flags = (audio_output_flags_t)(*flags &~AUDIO_OUTPUT_FLAG_FAST);
+ *flags = (audio_output_flags_t)(*flags & ~AUDIO_OUTPUT_FLAG_FAST);
}
}
// For normal PCM streaming tracks, update minimum frame count.
@@ -2400,9 +2527,9 @@
}
}
-uint32_t AudioFlinger::PlaybackThread::hasAudioSession(audio_session_t sessionId) const
+// hasAudioSession_l() must be called with ThreadBase::mLock held
+uint32_t AudioFlinger::PlaybackThread::hasAudioSession_l(audio_session_t sessionId) const
{
- Mutex::Autolock _l(mLock);
uint32_t result = 0;
if (getEffectChain_l(sessionId) != 0) {
result = EFFECT_SESSION;
@@ -2412,6 +2539,9 @@
sp<Track> track = mTracks[i];
if (sessionId == track->sessionId() && !track->isInvalid()) {
result |= TRACK_SESSION;
+ if (track->isFastTrack()) {
+ result |= FAST_SESSION;
+ }
break;
}
}
@@ -6333,8 +6463,22 @@
// there are sufficient fast track slots available
mFastTrackAvail
) {
- ALOGV("AUDIO_INPUT_FLAG_FAST accepted: frameCount=%zu mFrameCount=%zu",
- frameCount, mFrameCount);
+ // check compatibility with audio effects.
+ Mutex::Autolock _l(mLock);
+ // Do not accept FAST flag if the session has software effects
+ sp<EffectChain> chain = getEffectChain_l(sessionId);
+ if (chain != 0) {
+ ALOGV_IF((flags & AUDIO_INPUT_FLAG_RAW) != 0,
+ "AUDIO_INPUT_FLAG_RAW denied: effect present on session");
+ *flags = (audio_input_flags_t)(*flags & ~AUDIO_INPUT_FLAG_RAW);
+ if (chain->hasSoftwareEffect()) {
+ ALOGV("AUDIO_INPUT_FLAG_FAST denied: software effect present on session");
+ *flags = (audio_input_flags_t)(*flags & ~AUDIO_INPUT_FLAG_FAST);
+ }
+ }
+ ALOGV_IF((flags & AUDIO_INPUT_FLAG_FAST) != 0,
+ "AUDIO_INPUT_FLAG_FAST accepted: frameCount=%zu mFrameCount=%zu",
+ frameCount, mFrameCount);
} else {
ALOGV("AUDIO_INPUT_FLAG_FAST denied: frameCount=%zu mFrameCount=%zu mPipeFramesP2=%zu "
"format=%#x isLinear=%d channelMask=%#x sampleRate=%u mSampleRate=%u "
@@ -7224,9 +7368,9 @@
return mInput->stream->get_input_frames_lost(mInput->stream);
}
-uint32_t AudioFlinger::RecordThread::hasAudioSession(audio_session_t sessionId) const
+// hasAudioSession_l() must be called with ThreadBase::mLock held
+uint32_t AudioFlinger::RecordThread::hasAudioSession_l(audio_session_t sessionId) const
{
- Mutex::Autolock _l(mLock);
uint32_t result = 0;
if (getEffectChain_l(sessionId) != 0) {
result = EFFECT_SESSION;
@@ -7235,6 +7379,9 @@
for (size_t i = 0; i < mTracks.size(); ++i) {
if (sessionId == mTracks[i]->sessionId()) {
result |= TRACK_SESSION;
+ if (mTracks[i]->isFastTrack()) {
+ result |= FAST_SESSION;
+ }
break;
}
}
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 0b4fbb9..1bfbca9 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -301,8 +301,10 @@
enum effect_state {
EFFECT_SESSION = 0x1, // the audio session corresponds to at least one
// effect
- TRACK_SESSION = 0x2 // the audio session corresponds to at least one
+ TRACK_SESSION = 0x2, // the audio session corresponds to at least one
// track
+ FAST_SESSION = 0x4 // the audio session corresponds to at least one
+ // fast track
};
// get effect chain corresponding to session Id.
@@ -335,9 +337,16 @@
void removeEffect_l(const sp< EffectModule>& effect);
// detach all tracks connected to an auxiliary effect
virtual void detachAuxEffect_l(int effectId __unused) {}
- // returns either EFFECT_SESSION if effects on this audio session exist in one
- // chain, or TRACK_SESSION if tracks on this audio session exist, or both
- virtual uint32_t hasAudioSession(audio_session_t sessionId) const = 0;
+ // returns a combination of:
+ // - EFFECT_SESSION if effects on this audio session exist in one chain
+ // - TRACK_SESSION if tracks on this audio session exist
+ // - FAST_SESSION if fast tracks on this audio session exist
+ virtual uint32_t hasAudioSession_l(audio_session_t sessionId) const = 0;
+ uint32_t hasAudioSession(audio_session_t sessionId) const {
+ Mutex::Autolock _l(mLock);
+ return hasAudioSession_l(sessionId);
+ }
+
// the value returned by default implementation is not important as the
// strategy is only meaningful for PlaybackThread which implements this method
virtual uint32_t getStrategyForSession_l(audio_session_t sessionId __unused)
@@ -374,6 +383,10 @@
void systemReady();
+ // checkEffectCompatibility_l() must be called with ThreadBase::mLock held
+ virtual status_t checkEffectCompatibility_l(const effect_descriptor_t *desc,
+ audio_session_t sessionId) = 0;
+
mutable Mutex mLock;
protected:
@@ -506,6 +519,9 @@
// RefBase
virtual void onFirstRef();
+ virtual status_t checkEffectCompatibility_l(const effect_descriptor_t *desc,
+ audio_session_t sessionId);
+
protected:
// Code snippets that were lifted up out of threadLoop()
virtual void threadLoop_mix() = 0;
@@ -605,7 +621,7 @@
virtual status_t addEffectChain_l(const sp<EffectChain>& chain);
virtual size_t removeEffectChain_l(const sp<EffectChain>& chain);
- virtual uint32_t hasAudioSession(audio_session_t sessionId) const;
+ virtual uint32_t hasAudioSession_l(audio_session_t sessionId) const;
virtual uint32_t getStrategyForSession_l(audio_session_t sessionId);
@@ -1292,7 +1308,7 @@
virtual status_t addEffectChain_l(const sp<EffectChain>& chain);
virtual size_t removeEffectChain_l(const sp<EffectChain>& chain);
- virtual uint32_t hasAudioSession(audio_session_t sessionId) const;
+ virtual uint32_t hasAudioSession_l(audio_session_t sessionId) const;
// Return the set of unique session IDs across all tracks.
// The keys are the session IDs, and the associated values are meaningless.
@@ -1308,6 +1324,9 @@
bool hasFastCapture() const { return mFastCapture != 0; }
virtual void getAudioPortConfig(struct audio_port_config *config);
+ virtual status_t checkEffectCompatibility_l(const effect_descriptor_t *desc,
+ audio_session_t sessionId);
+
private:
// Enter standby if not already in standby, and set mStandby flag
void standbyIfNotAlreadyInStandby();