Fix race condition in Effects
Main problem was in AudioFlinger::EffectChain::EffectChain(), where
the thread* argument could possibly have been destroyed before the
creation of the weak pointer
(AudioFlinger::EffectChain::EffectCallback::mThread) around it.
While here, cleaned up a bunch of other pointer-related operations
in order to avoid trafficking in raw pointers to RefBase subclasses.
Bug: 147770363
Change-Id: I508ca94dd38a04e13f1a1c413f548001b961c721
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 0fac36d..d4e0ae2 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -343,7 +343,10 @@
virtual ~SyncEvent() {}
- void trigger() { Mutex::Autolock _l(mLock); if (mCallback) mCallback(this); }
+ void trigger() {
+ Mutex::Autolock _l(mLock);
+ if (mCallback) mCallback(wp<SyncEvent>(this));
+ }
bool isCancelled() const { Mutex::Autolock _l(mLock); return (mCallback == NULL); }
void cancel() { Mutex::Autolock _l(mLock); mCallback = NULL; }
AudioSystem::sync_event_t type() const { return mType; }
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 70c56e3..2f3724f 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -737,7 +737,7 @@
}
if (!mSupportsFloat) { // convert input to int16_t as effect doesn't support float.
if (!auxType) {
- if (mInConversionBuffer.get() == nullptr) {
+ if (mInConversionBuffer == nullptr) {
ALOGW("%s: mInConversionBuffer is null, bypassing", __func__);
goto data_bypass;
}
@@ -748,7 +748,7 @@
inBuffer = mInConversionBuffer;
}
if (mConfig.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
- if (mOutConversionBuffer.get() == nullptr) {
+ if (mOutConversionBuffer == nullptr) {
ALOGW("%s: mOutConversionBuffer is null, bypassing", __func__);
goto data_bypass;
}
@@ -921,9 +921,8 @@
mConfig.outputCfg.buffer.frameCount = mConfig.inputCfg.buffer.frameCount;
ALOGV("configure() %p chain %p buffer %p framecount %zu",
- this, mCallback->chain().promote() != nullptr ? mCallback->chain().promote().get() :
- nullptr,
- mConfig.inputCfg.buffer.raw, mConfig.inputCfg.buffer.frameCount);
+ this, mCallback->chain().promote().get(),
+ mConfig.inputCfg.buffer.raw, mConfig.inputCfg.buffer.frameCount);
status_t cmdStatus;
size = sizeof(int);
@@ -1290,7 +1289,7 @@
const uint32_t inChannelCount =
audio_channel_count_from_out_mask(mConfig.inputCfg.channels);
const bool formatMismatch = !mSupportsFloat || mInChannelCountRequested != inChannelCount;
- if (!auxType && formatMismatch && mInBuffer.get() != nullptr) {
+ if (!auxType && formatMismatch && mInBuffer != nullptr) {
// we need to translate - create hidl shared buffer and intercept
const size_t inFrameCount = mConfig.inputCfg.buffer.frameCount;
// Use FCC_2 in case mInChannelCountRequested is mono and the effect is stereo.
@@ -1300,13 +1299,13 @@
ALOGV("%s: setInBuffer updating for inChannels:%d inFrameCount:%zu total size:%zu",
__func__, inChannels, inFrameCount, size);
- if (size > 0 && (mInConversionBuffer.get() == nullptr
+ if (size > 0 && (mInConversionBuffer == nullptr
|| size > mInConversionBuffer->getSize())) {
mInConversionBuffer.clear();
ALOGV("%s: allocating mInConversionBuffer %zu", __func__, size);
(void)mCallback->allocateHalBuffer(size, &mInConversionBuffer);
}
- if (mInConversionBuffer.get() != nullptr) {
+ if (mInConversionBuffer != nullptr) {
mInConversionBuffer->setFrameCount(inFrameCount);
mEffectInterface->setInBuffer(mInConversionBuffer);
} else if (size > 0) {
@@ -1335,7 +1334,7 @@
const uint32_t outChannelCount =
audio_channel_count_from_out_mask(mConfig.outputCfg.channels);
const bool formatMismatch = !mSupportsFloat || mOutChannelCountRequested != outChannelCount;
- if (formatMismatch && mOutBuffer.get() != nullptr) {
+ if (formatMismatch && mOutBuffer != nullptr) {
const size_t outFrameCount = mConfig.outputCfg.buffer.frameCount;
// Use FCC_2 in case mOutChannelCountRequested is mono and the effect is stereo.
const uint32_t outChannels = std::max((uint32_t)FCC_2, mOutChannelCountRequested);
@@ -1344,13 +1343,13 @@
ALOGV("%s: setOutBuffer updating for outChannels:%d outFrameCount:%zu total size:%zu",
__func__, outChannels, outFrameCount, size);
- if (size > 0 && (mOutConversionBuffer.get() == nullptr
+ if (size > 0 && (mOutConversionBuffer == nullptr
|| size > mOutConversionBuffer->getSize())) {
mOutConversionBuffer.clear();
ALOGV("%s: allocating mOutConversionBuffer %zu", __func__, size);
(void)mCallback->allocateHalBuffer(size, &mOutConversionBuffer);
}
- if (mOutConversionBuffer.get() != nullptr) {
+ if (mOutConversionBuffer != nullptr) {
mOutConversionBuffer->setFrameCount(outFrameCount);
mEffectInterface->setOutBuffer(mOutConversionBuffer);
} else if (size > 0) {
@@ -1521,7 +1520,7 @@
static std::string dumpInOutBuffer(bool isInput, const sp<EffectBufferHalInterface> &buffer) {
std::stringstream ss;
- if (buffer.get() == nullptr) {
+ if (buffer == nullptr) {
return "nullptr"; // make different than below
} else if (buffer->externalData() != nullptr) {
ss << (isInput ? buffer->externalData() : buffer->audioBuffer()->raw)
@@ -1937,19 +1936,20 @@
#undef LOG_TAG
#define LOG_TAG "AudioFlinger::EffectChain"
-AudioFlinger::EffectChain::EffectChain(ThreadBase *thread,
- audio_session_t sessionId)
+AudioFlinger::EffectChain::EffectChain(const wp<ThreadBase>& thread,
+ audio_session_t sessionId)
: mSessionId(sessionId), mActiveTrackCnt(0), mTrackCnt(0), mTailBufferCount(0),
mVolumeCtrlIdx(-1), mLeftVolume(UINT_MAX), mRightVolume(UINT_MAX),
mNewLeftVolume(UINT_MAX), mNewRightVolume(UINT_MAX),
- mEffectCallback(new EffectCallback(this, thread, thread->mAudioFlinger.get()))
+ mEffectCallback(new EffectCallback(wp<EffectChain>(this), thread))
{
mStrategy = AudioSystem::getStrategyForStream(AUDIO_STREAM_MUSIC);
- if (thread == nullptr) {
+ sp<ThreadBase> p = thread.promote();
+ if (p == nullptr) {
return;
}
- mMaxTailBuffers = ((kProcessTailDurationMs * thread->sampleRate()) / 1000) /
- thread->frameCount();
+ mMaxTailBuffers = ((kProcessTailDurationMs * p->sampleRate()) / 1000) /
+ p->frameCount();
}
AudioFlinger::EffectChain::~EffectChain()
@@ -2638,7 +2638,7 @@
void AudioFlinger::EffectChain::setThread(const sp<ThreadBase>& thread)
{
Mutex::Autolock _l(mLock);
- mEffectCallback->setThread(thread.get());
+ mEffectCallback->setThread(thread);
}
void AudioFlinger::EffectChain::checkOutputFlagCompatibility(audio_output_flags_t *flags) const
diff --git a/services/audioflinger/Effects.h b/services/audioflinger/Effects.h
index 40bb226..1dfa1ae 100644
--- a/services/audioflinger/Effects.h
+++ b/services/audioflinger/Effects.h
@@ -402,7 +402,6 @@
class EffectChain : public RefBase {
public:
EffectChain(const wp<ThreadBase>& wThread, audio_session_t sessionId);
- EffectChain(ThreadBase *thread, audio_session_t sessionId);
virtual ~EffectChain();
// special key used for an entry in mSuspendedEffects keyed vector
@@ -513,8 +512,11 @@
class EffectCallback : public EffectCallbackInterface {
public:
- EffectCallback(EffectChain *chain, ThreadBase *thread, AudioFlinger *audioFlinger)
- : mChain(chain), mThread(thread), mAudioFlinger(audioFlinger) {}
+ EffectCallback(const wp<EffectChain>& chain,
+ const wp<ThreadBase>& thread)
+ : mChain(chain) {
+ setThread(thread);
+ }
status_t createEffectHal(const effect_uuid_t *pEffectUuid,
int32_t sessionId, int32_t deviceId, sp<EffectHalInterface> *effect) override;
@@ -550,7 +552,12 @@
wp<EffectChain> chain() const override { return mChain; }
wp<ThreadBase> thread() { return mThread; }
- void setThread(ThreadBase *thread) { mThread = thread; };
+
+ void setThread(const wp<ThreadBase>& thread) {
+ mThread = thread;
+ sp<ThreadBase> p = thread.promote();
+ mAudioFlinger = p ? p->mAudioFlinger : nullptr;
+ }
private:
wp<EffectChain> mChain;
@@ -623,7 +630,8 @@
effect_descriptor_t *desc, int id)
: EffectBase(callback, desc, id, AUDIO_SESSION_DEVICE, false),
mDevice(device), mManagerCallback(callback),
- mMyCallback(new ProxyCallback(this, callback)) {}
+ mMyCallback(new ProxyCallback(wp<DeviceEffectProxy>(this),
+ callback)) {}
status_t setEnabled(bool enabled, bool fromHandle) override;
sp<DeviceEffectProxy> asDeviceEffectProxy() override { return this; }
@@ -649,7 +657,7 @@
class ProxyCallback : public EffectCallbackInterface {
public:
- ProxyCallback(DeviceEffectProxy *proxy,
+ ProxyCallback(const wp<DeviceEffectProxy>& proxy,
const sp<DeviceEffectManagerCallback>& callback)
: mProxy(proxy), mManagerCallback(callback) {}