Loading services/audioflinger/Effects.cpp +39 −4 Original line number Diff line number Diff line Loading @@ -263,7 +263,9 @@ bool AudioFlinger::EffectModule::updateState() { } break; case STOPPING: if (stop_l() == NO_ERROR) { // volume control for offload and direct threads must take effect immediately. if (stop_l() == NO_ERROR && !(isVolumeControl() && isOffloadedOrDirect())) { mDisableWaitCnt = mMaxDisableWaitCnt; } else { mDisableWaitCnt = 1; // will cause immediate transition to IDLE Loading Loading @@ -778,6 +780,16 @@ status_t AudioFlinger::EffectModule::stop_l() } status_t cmdStatus = NO_ERROR; uint32_t size = sizeof(status_t); if (isVolumeControl() && isOffloadedOrDirect()) { sp<EffectChain>chain = mChain.promote(); // We have the EffectChain and EffectModule lock, permit a reentrant call to setVolume: // resetVolume_l --> setVolume_l --> EffectModule::setVolume mSetVolumeReentrantTid = gettid(); chain->resetVolume_l(); mSetVolumeReentrantTid = INVALID_PID; } status_t status = mEffectInterface->command(EFFECT_CMD_DISABLE, 0, NULL, Loading Loading @@ -993,6 +1005,16 @@ bool AudioFlinger::EffectModule::isProcessEnabled() const } } bool AudioFlinger::EffectModule::isOffloadedOrDirect() const { return (mThreadType == ThreadBase::OFFLOAD || mThreadType == ThreadBase::DIRECT); } bool AudioFlinger::EffectModule::isVolumeControlEnabled() const { return (isVolumeControl() && (isOffloadedOrDirect() ? isEnabled() : isProcessEnabled())); } void AudioFlinger::EffectModule::setInBuffer(const sp<EffectBufferHalInterface>& buffer) { ALOGVV("setInBuffer %p",(&buffer)); Loading Loading @@ -1091,7 +1113,7 @@ void AudioFlinger::EffectModule::setOutBuffer(const sp<EffectBufferHalInterface> status_t AudioFlinger::EffectModule::setVolume(uint32_t *left, uint32_t *right, bool controller) { Mutex::Autolock _l(mLock); AutoLockReentrant _l(mLock, mSetVolumeReentrantTid); if (mStatus != NO_ERROR) { return mStatus; } Loading Loading @@ -1122,6 +1144,18 @@ status_t AudioFlinger::EffectModule::setVolume(uint32_t *left, uint32_t *right, return status; } void AudioFlinger::EffectChain::setVolumeForOutput_l(uint32_t left, uint32_t right) { sp<ThreadBase> thread = mThread.promote(); if (thread != 0 && (thread->type() == ThreadBase::OFFLOAD || thread->type() == ThreadBase::DIRECT)) { PlaybackThread *t = (PlaybackThread *)thread.get(); float vol_l = (float)left / (1 << 24); float vol_r = (float)right / (1 << 24); t->setVolumeForOutput_l(vol_l, vol_r); } } status_t AudioFlinger::EffectModule::setDevice(audio_devices_t device) { if (device == AUDIO_DEVICE_NONE) { Loading Loading @@ -2200,8 +2234,7 @@ bool AudioFlinger::EffectChain::setVolume_l(uint32_t *left, uint32_t *right, boo // first update volume controller for (size_t i = size; i > 0; i--) { if (mEffects[i - 1]->isProcessEnabled() && (mEffects[i - 1]->desc().flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_CTRL) { if (mEffects[i - 1]->isVolumeControlEnabled()) { ctrlIdx = i - 1; hasControl = true; break; Loading Loading @@ -2247,6 +2280,8 @@ bool AudioFlinger::EffectChain::setVolume_l(uint32_t *left, uint32_t *right, boo *left = newLeft; *right = newRight; setVolumeForOutput_l(*left, *right); return hasControl; } Loading services/audioflinger/Effects.h +28 −1 Original line number Diff line number Diff line Loading @@ -85,6 +85,8 @@ public: status_t setEnabled_l(bool enabled); bool isEnabled() const; bool isProcessEnabled() const; bool isOffloadedOrDirect() const; bool isVolumeControlEnabled() const; void setInBuffer(const sp<EffectBufferHalInterface>& buffer); int16_t *inBuffer() const { Loading @@ -95,7 +97,8 @@ public: return mOutBuffer != 0 ? reinterpret_cast<int16_t*>(mOutBuffer->ptr()) : NULL; } void setChain(const wp<EffectChain>& chain) { mChain = chain; } void setThread(const wp<ThreadBase>& thread) { mThread = thread; } void setThread(const wp<ThreadBase>& thread) { mThread = thread; mThreadType = thread.promote()->type(); } const wp<ThreadBase>& thread() { return mThread; } status_t addHandle(EffectHandle *handle); Loading Loading @@ -128,6 +131,9 @@ public: { return (mDescriptor.flags & EFFECT_FLAG_HW_ACC_MASK) == 0; } bool isProcessImplemented() const { return (mDescriptor.flags & EFFECT_FLAG_NO_PROCESS) == 0; } bool isVolumeControl() const { return (mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_CTRL; } status_t setOffloaded(bool offloaded, audio_io_handle_t io); bool isOffloaded() const; void addEffectToHal_l(); Loading @@ -150,6 +156,7 @@ private: mutable Mutex mLock; // mutex for process, commands and handles list protection wp<ThreadBase> mThread; // parent thread ThreadBase::type_t mThreadType; // parent thread type wp<EffectChain> mChain; // parent effect chain const int mId; // this instance unique ID const audio_session_t mSessionId; // audio session ID Loading @@ -176,6 +183,24 @@ mutable Mutex mLock; // mutex for process, commands and handl uint32_t mInChannelCountRequested; uint32_t mOutChannelCountRequested; #endif class AutoLockReentrant { public: AutoLockReentrant(Mutex& mutex, pid_t allowedTid) : mMutex(gettid() == allowedTid ? nullptr : &mutex) { if (mMutex != nullptr) mMutex->lock(); } ~AutoLockReentrant() { if (mMutex != nullptr) mMutex->unlock(); } private: Mutex * const mMutex; }; static constexpr pid_t INVALID_PID = (pid_t)-1; // this tid is allowed to call setVolume() without acquiring the mutex. pid_t mSetVolumeReentrantTid = INVALID_PID; }; // The EffectHandle class implements the IEffect interface. It provides resources Loading Loading @@ -403,6 +428,8 @@ private: void setThread(const sp<ThreadBase>& thread); void setVolumeForOutput_l(uint32_t left, uint32_t right); wp<ThreadBase> mThread; // parent mixer thread mutable Mutex mLock; // mutex protecting effect list Vector< sp<EffectModule> > mEffects; // list of effect modules Loading services/audioflinger/Threads.cpp +14 −9 Original line number Diff line number Diff line Loading @@ -2286,6 +2286,11 @@ float AudioFlinger::PlaybackThread::streamVolume(audio_stream_type_t stream) con return mStreamTypes[stream].volume; } void AudioFlinger::PlaybackThread::setVolumeForOutput_l(float left, float right) const { mOutput->stream->setVolume(left, right); } // addTrack_l() must be called with ThreadBase::mLock held status_t AudioFlinger::PlaybackThread::addTrack_l(const sp<Track>& track) { Loading Loading @@ -5142,20 +5147,20 @@ void AudioFlinger::DirectOutputThread::processVolume_l(Track *track, bool lastTr mLeftVolFloat = left; mRightVolFloat = right; // Convert volumes from float to 8.24 uint32_t vl = (uint32_t)(left * (1 << 24)); uint32_t vr = (uint32_t)(right * (1 << 24)); // Delegate volume control to effect in track effect chain if needed // only one effect chain can be present on DirectOutputThread, so if // there is one, the track is connected to it if (!mEffectChains.isEmpty()) { mEffectChains[0]->setVolume_l(&vl, &vr); left = (float)vl / (1 << 24); right = (float)vr / (1 << 24); // if effect chain exists, volume is handled by it. // Convert volumes from float to 8.24 uint32_t vl = (uint32_t)(left * (1 << 24)); uint32_t vr = (uint32_t)(right * (1 << 24)); // Direct/Offload effect chains set output volume in setVolume_l(). (void)mEffectChains[0]->setVolume_l(&vl, &vr); } else { // otherwise we directly set the volume. setVolumeForOutput_l(left, right); } status_t result = mOutput->stream->setVolume(left, right); ALOGE_IF(result != OK, "Error when setting output stream volume: %d", result); } } } Loading services/audioflinger/Threads.h +2 −0 Original line number Diff line number Diff line Loading @@ -712,6 +712,8 @@ public: virtual void setStreamMute(audio_stream_type_t stream, bool muted); virtual float streamVolume(audio_stream_type_t stream) const; void setVolumeForOutput_l(float left, float right) const; sp<Track> createTrack_l( const sp<AudioFlinger::Client>& client, audio_stream_type_t streamType, Loading Loading
services/audioflinger/Effects.cpp +39 −4 Original line number Diff line number Diff line Loading @@ -263,7 +263,9 @@ bool AudioFlinger::EffectModule::updateState() { } break; case STOPPING: if (stop_l() == NO_ERROR) { // volume control for offload and direct threads must take effect immediately. if (stop_l() == NO_ERROR && !(isVolumeControl() && isOffloadedOrDirect())) { mDisableWaitCnt = mMaxDisableWaitCnt; } else { mDisableWaitCnt = 1; // will cause immediate transition to IDLE Loading Loading @@ -778,6 +780,16 @@ status_t AudioFlinger::EffectModule::stop_l() } status_t cmdStatus = NO_ERROR; uint32_t size = sizeof(status_t); if (isVolumeControl() && isOffloadedOrDirect()) { sp<EffectChain>chain = mChain.promote(); // We have the EffectChain and EffectModule lock, permit a reentrant call to setVolume: // resetVolume_l --> setVolume_l --> EffectModule::setVolume mSetVolumeReentrantTid = gettid(); chain->resetVolume_l(); mSetVolumeReentrantTid = INVALID_PID; } status_t status = mEffectInterface->command(EFFECT_CMD_DISABLE, 0, NULL, Loading Loading @@ -993,6 +1005,16 @@ bool AudioFlinger::EffectModule::isProcessEnabled() const } } bool AudioFlinger::EffectModule::isOffloadedOrDirect() const { return (mThreadType == ThreadBase::OFFLOAD || mThreadType == ThreadBase::DIRECT); } bool AudioFlinger::EffectModule::isVolumeControlEnabled() const { return (isVolumeControl() && (isOffloadedOrDirect() ? isEnabled() : isProcessEnabled())); } void AudioFlinger::EffectModule::setInBuffer(const sp<EffectBufferHalInterface>& buffer) { ALOGVV("setInBuffer %p",(&buffer)); Loading Loading @@ -1091,7 +1113,7 @@ void AudioFlinger::EffectModule::setOutBuffer(const sp<EffectBufferHalInterface> status_t AudioFlinger::EffectModule::setVolume(uint32_t *left, uint32_t *right, bool controller) { Mutex::Autolock _l(mLock); AutoLockReentrant _l(mLock, mSetVolumeReentrantTid); if (mStatus != NO_ERROR) { return mStatus; } Loading Loading @@ -1122,6 +1144,18 @@ status_t AudioFlinger::EffectModule::setVolume(uint32_t *left, uint32_t *right, return status; } void AudioFlinger::EffectChain::setVolumeForOutput_l(uint32_t left, uint32_t right) { sp<ThreadBase> thread = mThread.promote(); if (thread != 0 && (thread->type() == ThreadBase::OFFLOAD || thread->type() == ThreadBase::DIRECT)) { PlaybackThread *t = (PlaybackThread *)thread.get(); float vol_l = (float)left / (1 << 24); float vol_r = (float)right / (1 << 24); t->setVolumeForOutput_l(vol_l, vol_r); } } status_t AudioFlinger::EffectModule::setDevice(audio_devices_t device) { if (device == AUDIO_DEVICE_NONE) { Loading Loading @@ -2200,8 +2234,7 @@ bool AudioFlinger::EffectChain::setVolume_l(uint32_t *left, uint32_t *right, boo // first update volume controller for (size_t i = size; i > 0; i--) { if (mEffects[i - 1]->isProcessEnabled() && (mEffects[i - 1]->desc().flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_CTRL) { if (mEffects[i - 1]->isVolumeControlEnabled()) { ctrlIdx = i - 1; hasControl = true; break; Loading Loading @@ -2247,6 +2280,8 @@ bool AudioFlinger::EffectChain::setVolume_l(uint32_t *left, uint32_t *right, boo *left = newLeft; *right = newRight; setVolumeForOutput_l(*left, *right); return hasControl; } Loading
services/audioflinger/Effects.h +28 −1 Original line number Diff line number Diff line Loading @@ -85,6 +85,8 @@ public: status_t setEnabled_l(bool enabled); bool isEnabled() const; bool isProcessEnabled() const; bool isOffloadedOrDirect() const; bool isVolumeControlEnabled() const; void setInBuffer(const sp<EffectBufferHalInterface>& buffer); int16_t *inBuffer() const { Loading @@ -95,7 +97,8 @@ public: return mOutBuffer != 0 ? reinterpret_cast<int16_t*>(mOutBuffer->ptr()) : NULL; } void setChain(const wp<EffectChain>& chain) { mChain = chain; } void setThread(const wp<ThreadBase>& thread) { mThread = thread; } void setThread(const wp<ThreadBase>& thread) { mThread = thread; mThreadType = thread.promote()->type(); } const wp<ThreadBase>& thread() { return mThread; } status_t addHandle(EffectHandle *handle); Loading Loading @@ -128,6 +131,9 @@ public: { return (mDescriptor.flags & EFFECT_FLAG_HW_ACC_MASK) == 0; } bool isProcessImplemented() const { return (mDescriptor.flags & EFFECT_FLAG_NO_PROCESS) == 0; } bool isVolumeControl() const { return (mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_CTRL; } status_t setOffloaded(bool offloaded, audio_io_handle_t io); bool isOffloaded() const; void addEffectToHal_l(); Loading @@ -150,6 +156,7 @@ private: mutable Mutex mLock; // mutex for process, commands and handles list protection wp<ThreadBase> mThread; // parent thread ThreadBase::type_t mThreadType; // parent thread type wp<EffectChain> mChain; // parent effect chain const int mId; // this instance unique ID const audio_session_t mSessionId; // audio session ID Loading @@ -176,6 +183,24 @@ mutable Mutex mLock; // mutex for process, commands and handl uint32_t mInChannelCountRequested; uint32_t mOutChannelCountRequested; #endif class AutoLockReentrant { public: AutoLockReentrant(Mutex& mutex, pid_t allowedTid) : mMutex(gettid() == allowedTid ? nullptr : &mutex) { if (mMutex != nullptr) mMutex->lock(); } ~AutoLockReentrant() { if (mMutex != nullptr) mMutex->unlock(); } private: Mutex * const mMutex; }; static constexpr pid_t INVALID_PID = (pid_t)-1; // this tid is allowed to call setVolume() without acquiring the mutex. pid_t mSetVolumeReentrantTid = INVALID_PID; }; // The EffectHandle class implements the IEffect interface. It provides resources Loading Loading @@ -403,6 +428,8 @@ private: void setThread(const sp<ThreadBase>& thread); void setVolumeForOutput_l(uint32_t left, uint32_t right); wp<ThreadBase> mThread; // parent mixer thread mutable Mutex mLock; // mutex protecting effect list Vector< sp<EffectModule> > mEffects; // list of effect modules Loading
services/audioflinger/Threads.cpp +14 −9 Original line number Diff line number Diff line Loading @@ -2286,6 +2286,11 @@ float AudioFlinger::PlaybackThread::streamVolume(audio_stream_type_t stream) con return mStreamTypes[stream].volume; } void AudioFlinger::PlaybackThread::setVolumeForOutput_l(float left, float right) const { mOutput->stream->setVolume(left, right); } // addTrack_l() must be called with ThreadBase::mLock held status_t AudioFlinger::PlaybackThread::addTrack_l(const sp<Track>& track) { Loading Loading @@ -5142,20 +5147,20 @@ void AudioFlinger::DirectOutputThread::processVolume_l(Track *track, bool lastTr mLeftVolFloat = left; mRightVolFloat = right; // Convert volumes from float to 8.24 uint32_t vl = (uint32_t)(left * (1 << 24)); uint32_t vr = (uint32_t)(right * (1 << 24)); // Delegate volume control to effect in track effect chain if needed // only one effect chain can be present on DirectOutputThread, so if // there is one, the track is connected to it if (!mEffectChains.isEmpty()) { mEffectChains[0]->setVolume_l(&vl, &vr); left = (float)vl / (1 << 24); right = (float)vr / (1 << 24); // if effect chain exists, volume is handled by it. // Convert volumes from float to 8.24 uint32_t vl = (uint32_t)(left * (1 << 24)); uint32_t vr = (uint32_t)(right * (1 << 24)); // Direct/Offload effect chains set output volume in setVolume_l(). (void)mEffectChains[0]->setVolume_l(&vl, &vr); } else { // otherwise we directly set the volume. setVolumeForOutput_l(left, right); } status_t result = mOutput->stream->setVolume(left, right); ALOGE_IF(result != OK, "Error when setting output stream volume: %d", result); } } } Loading
services/audioflinger/Threads.h +2 −0 Original line number Diff line number Diff line Loading @@ -712,6 +712,8 @@ public: virtual void setStreamMute(audio_stream_type_t stream, bool muted); virtual float streamVolume(audio_stream_type_t stream) const; void setVolumeForOutput_l(float left, float right) const; sp<Track> createTrack_l( const sp<AudioFlinger::Client>& client, audio_stream_type_t streamType, Loading