Merge "Set volume for output when effect is enabled/disabled."

gugelfrei
Treehugger Robot 6 years ago committed by Gerrit Code Review
commit e778547997

@ -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
@ -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,
@ -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));
@ -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;
}
@ -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) {
@ -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;
@ -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;
}

@ -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 {
@ -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);
@ -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();
@ -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
@ -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
@ -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

@ -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)
{
@ -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);
}
}
}

@ -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…
Cancel
Save