summaryrefslogtreecommitdiffstats
path: root/services/audioflinger/AudioFlinger.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'services/audioflinger/AudioFlinger.cpp')
-rw-r--r--services/audioflinger/AudioFlinger.cpp537
1 files changed, 365 insertions, 172 deletions
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 771d885..b88e69d 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -63,6 +63,8 @@
// ----------------------------------------------------------------------------
+extern const char * const gEffectLibPath;
+
namespace android {
static const char* kDeadlockedString = "AudioFlinger may be deadlocked\n";
@@ -127,8 +129,7 @@ static bool settingsAllowed() {
AudioFlinger::AudioFlinger()
: BnAudioFlinger(),
- mAudioHardware(0), mMasterVolume(1.0f), mMasterMute(false), mNextUniqueId(1),
- mTotalEffectsCpuLoad(0), mTotalEffectsMemory(0)
+ mAudioHardware(0), mMasterVolume(1.0f), mMasterMute(false), mNextUniqueId(1)
{
mHardwareStatus = AUDIO_HW_IDLE;
@@ -321,13 +322,19 @@ sp<IAudioTrack> AudioFlinger::createTrack(
mClients.add(pid, client);
}
- // If no audio session id is provided, create one here
- // TODO: enforce same stream type for all tracks in same audio session?
- // TODO: prevent same audio session on different output threads
LOGV("createTrack() sessionId: %d", (sessionId == NULL) ? -2 : *sessionId);
- if (sessionId != NULL && *sessionId != 0) {
+ if (sessionId != NULL && *sessionId != AudioSystem::SESSION_OUTPUT_MIX) {
+ // prevent same audio session on different output threads
+ for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
+ if (mPlaybackThreads.keyAt(i) != output &&
+ mPlaybackThreads.valueAt(i)->hasAudioSession(*sessionId)) {
+ lStatus = BAD_VALUE;
+ goto Exit;
+ }
+ }
lSessionId = *sessionId;
} else {
+ // if no audio session id is provided, create one here
lSessionId = nextUniqueId();
if (sessionId != NULL) {
*sessionId = lSessionId;
@@ -1141,6 +1148,23 @@ sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTra
{ // scope for mLock
Mutex::Autolock _l(mLock);
+
+ // all tracks in same audio session must share the same routing strategy otherwise
+ // conflicts will happen when tracks are moved from one output to another by audio policy
+ // manager
+ uint32_t strategy =
+ AudioSystem::getStrategyForStream((AudioSystem::stream_type)streamType);
+ for (size_t i = 0; i < mTracks.size(); ++i) {
+ sp<Track> t = mTracks[i];
+ if (t != 0) {
+ if (sessionId == t->sessionId() &&
+ strategy != AudioSystem::getStrategyForStream((AudioSystem::stream_type)t->type())) {
+ lStatus = BAD_VALUE;
+ goto Exit;
+ }
+ }
+ }
+
track = new Track(this, client, streamType, sampleRate, format,
channelCount, frameCount, sharedBuffer, sessionId);
if (track->getCblk() == NULL || track->name() < 0) {
@@ -1153,6 +1177,7 @@ sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTra
if (chain != 0) {
LOGV("createTrack_l() setting main buffer %p", chain->inBuffer());
track->setMainBuffer(chain->inBuffer());
+ chain->setStrategy(AudioSystem::getStrategyForStream((AudioSystem::stream_type)track->type()));
}
}
lStatus = NO_ERROR;
@@ -1344,7 +1369,16 @@ void AudioFlinger::PlaybackThread::readOutputParameters()
mMixBuffer = new int16_t[mFrameCount * 2];
memset(mMixBuffer, 0, mFrameCount * 2 * sizeof(int16_t));
- //TODO handle effects reconfig
+ // force reconfiguration of effect chains and engines to take new buffer size and audio
+ // parameters into account
+ // Note that mLock is not held when readOutputParameters() is called from the constructor
+ // but in this case nothing is done below as no audio sessions have effect yet so it doesn't
+ // matter.
+ // create a copy of mEffectChains as calling moveEffectChain_l() can reorder some effect chains
+ Vector< sp<EffectChain> > effectChains = mEffectChains;
+ for (size_t i = 0; i < effectChains.size(); i ++) {
+ mAudioFlinger->moveEffectChain_l(effectChains[i]->sessionId(), this, this);
+ }
}
status_t AudioFlinger::PlaybackThread::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames)
@@ -1369,7 +1403,8 @@ bool AudioFlinger::PlaybackThread::hasAudioSession(int sessionId)
for (size_t i = 0; i < mTracks.size(); ++i) {
sp<Track> track = mTracks[i];
- if (sessionId == track->sessionId()) {
+ if (sessionId == track->sessionId() &&
+ !(track->mCblk->flags & CBLK_INVALID_MSK)) {
return true;
}
}
@@ -1377,6 +1412,23 @@ bool AudioFlinger::PlaybackThread::hasAudioSession(int sessionId)
return false;
}
+uint32_t AudioFlinger::PlaybackThread::getStrategyForSession_l(int sessionId)
+{
+ // session AudioSystem::SESSION_OUTPUT_MIX is placed in same strategy as MUSIC stream so that
+ // it is moved to correct output by audio policy manager when A2DP is connected or disconnected
+ if (sessionId == AudioSystem::SESSION_OUTPUT_MIX) {
+ return AudioSystem::getStrategyForStream(AudioSystem::MUSIC);
+ }
+ for (size_t i = 0; i < mTracks.size(); i++) {
+ sp<Track> track = mTracks[i];
+ if (sessionId == track->sessionId() &&
+ !(track->mCblk->flags & CBLK_INVALID_MSK)) {
+ return AudioSystem::getStrategyForStream((AudioSystem::stream_type) track->type());
+ }
+ }
+ return AudioSystem::getStrategyForStream(AudioSystem::MUSIC);
+}
+
sp<AudioFlinger::EffectChain> AudioFlinger::PlaybackThread::getEffectChain(int sessionId)
{
Mutex::Autolock _l(mLock);
@@ -1402,7 +1454,7 @@ void AudioFlinger::PlaybackThread::setMode(uint32_t mode)
Mutex::Autolock _l(mLock);
size_t size = mEffectChains.size();
for (size_t i = 0; i < size; i++) {
- mEffectChains[i]->setMode(mode);
+ mEffectChains[i]->setMode_l(mode);
}
}
@@ -1503,8 +1555,7 @@ bool AudioFlinger::MixerThread::threadLoop()
// prevent any changes in effect chain list and in each effect chain
// during mixing and effect process as the audio buffers could be deleted
// or modified if an effect is created or deleted
- effectChains = mEffectChains;
- lockEffectChains_l();
+ lockEffectChains_l(effectChains);
}
if (LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
@@ -1540,7 +1591,7 @@ bool AudioFlinger::MixerThread::threadLoop()
effectChains[i]->process_l();
}
// enable changes in effect chain
- unlockEffectChains();
+ unlockEffectChains(effectChains);
#ifdef LVMX
int audioOutputType = LifeVibes::getMixerType(mId, mType);
if (LifeVibes::audioOutputTypeIsLifeVibes(audioOutputType)) {
@@ -1571,7 +1622,7 @@ bool AudioFlinger::MixerThread::threadLoop()
mStandby = false;
} else {
// enable changes in effect chain
- unlockEffectChains();
+ unlockEffectChains(effectChains);
usleep(sleepTime);
}
@@ -1625,10 +1676,10 @@ uint32_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track
}
#endif
// Delegate master volume control to effect in output mix effect chain if needed
- sp<EffectChain> chain = getEffectChain_l(0);
+ sp<EffectChain> chain = getEffectChain_l(AudioSystem::SESSION_OUTPUT_MIX);
if (chain != 0) {
uint32_t v = (uint32_t)(masterVolume * (1 << 24));
- chain->setVolume(&v, &v);
+ chain->setVolume_l(&v, &v);
masterVolume = (float)((v + (1 << 23)) >> 24);
chain.clear();
}
@@ -1706,7 +1757,7 @@ uint32_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track
uint32_t vr = (uint32_t)(v * cblk->volume[1]) << 12;
// Delegate volume control to effect in track effect chain if needed
- if (chain != 0 && chain->setVolume(&vl, &vr)) {
+ if (chain != 0 && chain->setVolume_l(&vl, &vr)) {
// Do not ramp volume is volume is controlled by effect
param = AudioMixer::VOLUME;
}
@@ -1814,8 +1865,10 @@ uint32_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track
void AudioFlinger::MixerThread::invalidateTracks(int streamType)
{
- LOGV ("MixerThread::invalidateTracks() mixer %p, streamType %d, mTracks.size %d", this, streamType, mTracks.size());
+ LOGV ("MixerThread::invalidateTracks() mixer %p, streamType %d, mTracks.size %d",
+ this, streamType, mTracks.size());
Mutex::Autolock _l(mLock);
+
size_t size = mTracks.size();
for (size_t i = 0; i < size; i++) {
sp<Track> t = mTracks[i];
@@ -1885,7 +1938,7 @@ bool AudioFlinger::MixerThread::checkForNewParameters_l()
// aware of attached audio device.
mDevice = (uint32_t)value;
for (size_t i = 0; i < mEffectChains.size(); i++) {
- mEffectChains[i]->setDevice(mDevice);
+ mEffectChains[i]->setDevice_l(mDevice);
}
}
@@ -2070,7 +2123,6 @@ bool AudioFlinger::DirectOutputThread::threadLoop()
// hardware resources as soon as possible
nsecs_t standbyDelay = microseconds(activeSleepTime*2);
-
while (!exitPending())
{
bool rampVolume;
@@ -2198,7 +2250,7 @@ bool AudioFlinger::DirectOutputThread::threadLoop()
// there is one, the track is connected to it
if (!effectChains.isEmpty()) {
// Do not ramp volume is volume is controlled by effect
- if(effectChains[0]->setVolume(&vl, &vr)) {
+ if(effectChains[0]->setVolume_l(&vl, &vr)) {
rampVolume = false;
}
}
@@ -2246,7 +2298,8 @@ bool AudioFlinger::DirectOutputThread::threadLoop()
if (UNLIKELY(trackToRemove != 0)) {
mActiveTracks.remove(trackToRemove);
if (!effectChains.isEmpty()) {
- LOGV("stopping track on chain %p for session Id: %d", effectChains[0].get(), trackToRemove->sessionId());
+ LOGV("stopping track on chain %p for session Id: %d", effectChains[0].get(),
+ trackToRemove->sessionId());
effectChains[0]->stopTrack();
}
if (trackToRemove->isTerminated()) {
@@ -2255,7 +2308,7 @@ bool AudioFlinger::DirectOutputThread::threadLoop()
}
}
- lockEffectChains_l();
+ lockEffectChains_l(effectChains);
}
if (LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
@@ -2301,7 +2354,7 @@ bool AudioFlinger::DirectOutputThread::threadLoop()
for (size_t i = 0; i < effectChains.size(); i ++) {
effectChains[i]->process_l();
}
- unlockEffectChains();
+ unlockEffectChains(effectChains);
mLastWriteTime = systemTime();
mInWrite = true;
@@ -2312,7 +2365,7 @@ bool AudioFlinger::DirectOutputThread::threadLoop()
mInWrite = false;
mStandby = false;
} else {
- unlockEffectChains();
+ unlockEffectChains(effectChains);
usleep(sleepTime);
}
@@ -2505,8 +2558,7 @@ bool AudioFlinger::DuplicatingThread::threadLoop()
// prevent any changes in effect chain list and in each effect chain
// during mixing and effect process as the audio buffers could be deleted
// or modified if an effect is created or deleted
- effectChains = mEffectChains;
- lockEffectChains_l();
+ lockEffectChains_l(effectChains);
}
if (LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
@@ -2547,7 +2599,7 @@ bool AudioFlinger::DuplicatingThread::threadLoop()
effectChains[i]->process_l();
}
// enable changes in effect chain
- unlockEffectChains();
+ unlockEffectChains(effectChains);
standbyTime = systemTime() + kStandbyTimeInNsecs;
for (size_t i = 0; i < outputTracks.size(); i++) {
@@ -2557,7 +2609,7 @@ bool AudioFlinger::DuplicatingThread::threadLoop()
mBytesWritten += mixBufferSize;
} else {
// enable changes in effect chain
- unlockEffectChains();
+ unlockEffectChains(effectChains);
usleep(sleepTime);
}
@@ -2859,7 +2911,9 @@ void AudioFlinger::PlaybackThread::Track::destroy()
if (thread != 0) {
if (!isOutputTrack()) {
if (mState == ACTIVE || mState == RESUMING) {
- AudioSystem::stopOutput(thread->id(), (AudioSystem::stream_type)mStreamType);
+ AudioSystem::stopOutput(thread->id(),
+ (AudioSystem::stream_type)mStreamType,
+ mSessionId);
}
AudioSystem::releaseOutput(thread->id());
}
@@ -2948,7 +3002,8 @@ bool AudioFlinger::PlaybackThread::Track::isReady() const {
status_t AudioFlinger::PlaybackThread::Track::start()
{
status_t status = NO_ERROR;
- LOGV("start(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid());
+ LOGV("start(%d), calling thread %d session %d",
+ mName, IPCThreadState::self()->getCallingPid(), mSessionId);
sp<ThreadBase> thread = mThread.promote();
if (thread != 0) {
Mutex::Autolock _l(thread->mLock);
@@ -2965,7 +3020,9 @@ status_t AudioFlinger::PlaybackThread::Track::start()
if (!isOutputTrack() && state != ACTIVE && state != RESUMING) {
thread->mLock.unlock();
- status = AudioSystem::startOutput(thread->id(), (AudioSystem::stream_type)mStreamType);
+ status = AudioSystem::startOutput(thread->id(),
+ (AudioSystem::stream_type)mStreamType,
+ mSessionId);
thread->mLock.lock();
}
if (status == NO_ERROR) {
@@ -2998,7 +3055,9 @@ void AudioFlinger::PlaybackThread::Track::stop()
}
if (!isOutputTrack() && (state == ACTIVE || state == RESUMING)) {
thread->mLock.unlock();
- AudioSystem::stopOutput(thread->id(), (AudioSystem::stream_type)mStreamType);
+ AudioSystem::stopOutput(thread->id(),
+ (AudioSystem::stream_type)mStreamType,
+ mSessionId);
thread->mLock.lock();
}
}
@@ -3015,7 +3074,9 @@ void AudioFlinger::PlaybackThread::Track::pause()
LOGV("ACTIVE/RESUMING => PAUSING (%d) on thread %p", mName, thread.get());
if (!isOutputTrack()) {
thread->mLock.unlock();
- AudioSystem::stopOutput(thread->id(), (AudioSystem::stream_type)mStreamType);
+ AudioSystem::stopOutput(thread->id(),
+ (AudioSystem::stream_type)mStreamType,
+ mSessionId);
thread->mLock.lock();
}
}
@@ -3584,7 +3645,7 @@ sp<IAudioRecord> AudioFlinger::openRecord(
}
// If no audio session id is provided, create one here
- if (sessionId != NULL && *sessionId != 0) {
+ if (sessionId != NULL && *sessionId != AudioSystem::SESSION_OUTPUT_MIX) {
lSessionId = *sessionId;
} else {
lSessionId = nextUniqueId();
@@ -4415,8 +4476,8 @@ status_t AudioFlinger::setStreamOutput(uint32_t stream, int output)
thread->type() != PlaybackThread::DIRECT) {
MixerThread *srcThread = (MixerThread *)thread;
srcThread->invalidateTracks(stream);
- }
}
+ }
return NO_ERROR;
}
@@ -4471,12 +4532,26 @@ int AudioFlinger::nextUniqueId()
status_t AudioFlinger::loadEffectLibrary(const char *libPath, int *handle)
{
+ // check calling permissions
+ if (!settingsAllowed()) {
+ return PERMISSION_DENIED;
+ }
+ // only allow libraries loaded from /system/lib/soundfx for now
+ if (strncmp(gEffectLibPath, libPath, strlen(gEffectLibPath)) != 0) {
+ return PERMISSION_DENIED;
+ }
+
Mutex::Autolock _l(mLock);
return EffectLoadLibrary(libPath, handle);
}
status_t AudioFlinger::unloadEffectLibrary(int handle)
{
+ // check calling permissions
+ if (!settingsAllowed()) {
+ return PERMISSION_DENIED;
+ }
+
Mutex::Autolock _l(mLock);
return EffectUnloadLibrary(handle);
}
@@ -4521,7 +4596,8 @@ sp<IEffect> AudioFlinger::createEffect(pid_t pid,
sp<Client> client;
wp<Client> wclient;
- LOGV("createEffect pid %d, client %p, priority %d, sessionId %d, output %d", pid, effectClient.get(), priority, sessionId, output);
+ LOGV("createEffect pid %d, client %p, priority %d, sessionId %d, output %d",
+ pid, effectClient.get(), priority, sessionId, output);
if (pDesc == NULL) {
lStatus = BAD_VALUE;
@@ -4576,7 +4652,7 @@ sp<IEffect> AudioFlinger::createEffect(pid_t pid,
// an auxiliary version of this effect type is available
found = true;
memcpy(&d, &desc, sizeof(effect_descriptor_t));
- if (sessionId != 0 ||
+ if (sessionId != AudioSystem::SESSION_OUTPUT_MIX ||
(desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
break;
}
@@ -4589,22 +4665,23 @@ sp<IEffect> AudioFlinger::createEffect(pid_t pid,
}
// For same effect type, chose auxiliary version over insert version if
// connect to output mix (Compliance to OpenSL ES)
- if (sessionId == 0 &&
+ if (sessionId == AudioSystem::SESSION_OUTPUT_MIX &&
(d.flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_AUXILIARY) {
memcpy(&desc, &d, sizeof(effect_descriptor_t));
}
}
// Do not allow auxiliary effects on a session different from 0 (output mix)
- if (sessionId != 0 &&
+ if (sessionId != AudioSystem::SESSION_OUTPUT_MIX &&
(desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
lStatus = INVALID_OPERATION;
goto Exit;
}
- // Session -1 is reserved for output stage effects that can only be created
- // by audio policy manager (running in same process)
- if (sessionId == -1 && getpid() != IPCThreadState::self()->getCallingPid()) {
+ // Session AudioSystem::SESSION_OUTPUT_STAGE is reserved for output stage effects
+ // that can only be created by audio policy manager (running in same process)
+ if (sessionId == AudioSystem::SESSION_OUTPUT_STAGE &&
+ getpid() != IPCThreadState::self()->getCallingPid()) {
lStatus = INVALID_OPERATION;
goto Exit;
}
@@ -4616,13 +4693,14 @@ sp<IEffect> AudioFlinger::createEffect(pid_t pid,
// output threads.
// TODO: allow attachment of effect to inputs
if (output == 0) {
- if (sessionId <= 0) {
- // default to first output
- // TODO: define criteria to choose output when not specified. Or
- // receive output from audio policy manager
- if (mPlaybackThreads.size() != 0) {
- output = mPlaybackThreads.keyAt(0);
- }
+ if (sessionId == AudioSystem::SESSION_OUTPUT_STAGE) {
+ // output must be specified by AudioPolicyManager when using session
+ // AudioSystem::SESSION_OUTPUT_STAGE
+ lStatus = BAD_VALUE;
+ goto Exit;
+ } else if (sessionId == AudioSystem::SESSION_OUTPUT_MIX) {
+ output = AudioSystem::getOutputForEffect(&desc);
+ LOGV("createEffect() got output %d for effect %s", output, desc.name);
} else {
// look for the thread where the specified audio session is present
for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
@@ -4635,7 +4713,7 @@ sp<IEffect> AudioFlinger::createEffect(pid_t pid,
}
PlaybackThread *thread = checkPlaybackThread_l(output);
if (thread == NULL) {
- LOGE("unknown output thread");
+ LOGE("createEffect() unknown output thread");
lStatus = BAD_VALUE;
goto Exit;
}
@@ -4650,7 +4728,8 @@ sp<IEffect> AudioFlinger::createEffect(pid_t pid,
}
// create effect on selected output trhead
- handle = thread->createEffect_l(client, effectClient, priority, sessionId, &desc, enabled, &lStatus);
+ handle = thread->createEffect_l(client, effectClient, priority, sessionId,
+ &desc, enabled, &lStatus);
if (handle != 0 && id != NULL) {
*id = handle->id();
}
@@ -4663,31 +4742,64 @@ Exit:
return handle;
}
-status_t AudioFlinger::registerEffectResource_l(effect_descriptor_t *desc) {
- if (mTotalEffectsCpuLoad + desc->cpuLoad > MAX_EFFECTS_CPU_LOAD) {
- LOGW("registerEffectResource() CPU Load limit exceeded for Fx %s, CPU %f MIPS",
- desc->name, (float)desc->cpuLoad/10);
- return INVALID_OPERATION;
+status_t AudioFlinger::moveEffects(int session, int srcOutput, int dstOutput)
+{
+ LOGV("moveEffects() session %d, srcOutput %d, dstOutput %d",
+ session, srcOutput, dstOutput);
+ Mutex::Autolock _l(mLock);
+ if (srcOutput == dstOutput) {
+ LOGW("moveEffects() same dst and src outputs %d", dstOutput);
+ return NO_ERROR;
}
- if (mTotalEffectsMemory + desc->memoryUsage > MAX_EFFECTS_MEMORY) {
- LOGW("registerEffectResource() memory limit exceeded for Fx %s, Memory %d KB",
- desc->name, desc->memoryUsage);
- return INVALID_OPERATION;
+ PlaybackThread *srcThread = checkPlaybackThread_l(srcOutput);
+ if (srcThread == NULL) {
+ LOGW("moveEffects() bad srcOutput %d", srcOutput);
+ return BAD_VALUE;
+ }
+ PlaybackThread *dstThread = checkPlaybackThread_l(dstOutput);
+ if (dstThread == NULL) {
+ LOGW("moveEffects() bad dstOutput %d", dstOutput);
+ return BAD_VALUE;
}
- mTotalEffectsCpuLoad += desc->cpuLoad;
- mTotalEffectsMemory += desc->memoryUsage;
- LOGV("registerEffectResource_l() effect %s, CPU %d, memory %d",
- desc->name, desc->cpuLoad, desc->memoryUsage);
- LOGV(" total CPU %d, total memory %d", mTotalEffectsCpuLoad, mTotalEffectsMemory);
+
+ Mutex::Autolock _dl(dstThread->mLock);
+ Mutex::Autolock _sl(srcThread->mLock);
+ moveEffectChain_l(session, srcThread, dstThread);
+
return NO_ERROR;
}
-void AudioFlinger::unregisterEffectResource_l(effect_descriptor_t *desc) {
- mTotalEffectsCpuLoad -= desc->cpuLoad;
- mTotalEffectsMemory -= desc->memoryUsage;
- LOGV("unregisterEffectResource_l() effect %s, CPU %d, memory %d",
- desc->name, desc->cpuLoad, desc->memoryUsage);
- LOGV(" total CPU %d, total memory %d", mTotalEffectsCpuLoad, mTotalEffectsMemory);
+// moveEffectChain_l mustbe called with both srcThread and dstThread mLocks held
+status_t AudioFlinger::moveEffectChain_l(int session,
+ AudioFlinger::PlaybackThread *srcThread,
+ AudioFlinger::PlaybackThread *dstThread)
+{
+ LOGV("moveEffectChain_l() session %d from thread %p to thread %p",
+ session, srcThread, dstThread);
+
+ sp<EffectChain> chain = srcThread->getEffectChain_l(session);
+ if (chain == 0) {
+ LOGW("moveEffectChain_l() effect chain for session %d not on source thread %p",
+ session, srcThread);
+ return INVALID_OPERATION;
+ }
+
+ // remove chain first. This is usefull only if reconfiguring effect chain on same output thread,
+ // so that a new chain is created with correct parameters when first effect is added. This is
+ // otherwise unecessary as removeEffect_l() will remove the chain when last effect is
+ // removed.
+ srcThread->removeEffectChain_l(chain);
+
+ // transfer all effects one by one so that new effect chain is created on new thread with
+ // correct buffer sizes and audio parameters and effect engines reconfigured accordingly
+ sp<EffectModule> effect = chain->getEffectFromId_l(0);
+ while (effect != 0) {
+ srcThread->removeEffect_l(effect);
+ dstThread->addEffect_l(effect);
+ effect = chain->getEffectFromId_l(0);
+ }
+
+ return NO_ERROR;
}
// PlaybackThread::createEffect_l() must be called with AudioFlinger::mLock held
@@ -4706,6 +4818,7 @@ sp<AudioFlinger::EffectHandle> AudioFlinger::PlaybackThread::createEffect_l(
status_t lStatus;
sp<Track> track;
sp<EffectChain> chain;
+ bool chainCreated = false;
bool effectCreated = false;
bool effectRegistered = false;
@@ -4717,16 +4830,18 @@ sp<AudioFlinger::EffectHandle> AudioFlinger::PlaybackThread::createEffect_l(
// Do not allow auxiliary effect on session other than 0
if ((desc->flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY &&
- sessionId != 0) {
- LOGW("createEffect_l() Cannot add auxiliary effect %s to session %d", desc->name, sessionId);
+ sessionId != AudioSystem::SESSION_OUTPUT_MIX) {
+ LOGW("createEffect_l() Cannot add auxiliary effect %s to session %d",
+ desc->name, sessionId);
lStatus = BAD_VALUE;
goto Exit;
}
// Do not allow effects with session ID 0 on direct output or duplicating threads
// TODO: add rule for hw accelerated effects on direct outputs with non PCM format
- if (sessionId == 0 && mType != MIXER) {
- LOGW("createEffect_l() Cannot add auxiliary effect %s to session %d", desc->name, sessionId);
+ if (sessionId == AudioSystem::SESSION_OUTPUT_MIX && mType != MIXER) {
+ LOGW("createEffect_l() Cannot add auxiliary effect %s to session %d",
+ desc->name, sessionId);
lStatus = BAD_VALUE;
goto Exit;
}
@@ -4743,26 +4858,29 @@ sp<AudioFlinger::EffectHandle> AudioFlinger::PlaybackThread::createEffect_l(
LOGV("createEffect_l() new effect chain for session %d", sessionId);
chain = new EffectChain(this, sessionId);
addEffectChain_l(chain);
+ chain->setStrategy(getStrategyForSession_l(sessionId));
+ chainCreated = true;
} else {
- effect = chain->getEffectFromDesc(desc);
+ effect = chain->getEffectFromDesc_l(desc);
}
LOGV("createEffect_l() got effect %p on chain %p", effect == 0 ? 0 : effect.get(), chain.get());
if (effect == 0) {
+ int id = mAudioFlinger->nextUniqueId();
// Check CPU and memory usage
- lStatus = mAudioFlinger->registerEffectResource_l(desc);
+ lStatus = AudioSystem::registerEffect(desc, mId, chain->strategy(), sessionId, id);
if (lStatus != NO_ERROR) {
goto Exit;
}
effectRegistered = true;
// create a new effect module if none present in the chain
- effect = new EffectModule(this, chain, desc, mAudioFlinger->nextUniqueId(), sessionId);
+ effect = new EffectModule(this, chain, desc, id, sessionId);
lStatus = effect->status();
if (lStatus != NO_ERROR) {
goto Exit;
}
- lStatus = chain->addEffect(effect);
+ lStatus = chain->addEffect_l(effect);
if (lStatus != NO_ERROR) {
goto Exit;
}
@@ -4781,13 +4899,15 @@ sp<AudioFlinger::EffectHandle> AudioFlinger::PlaybackThread::createEffect_l(
Exit:
if (lStatus != NO_ERROR && lStatus != ALREADY_EXISTS) {
+ Mutex::Autolock _l(mLock);
if (effectCreated) {
- if (chain->removeEffect(effect) == 0) {
- removeEffectChain_l(chain);
- }
+ chain->removeEffect_l(effect);
}
if (effectRegistered) {
- mAudioFlinger->unregisterEffectResource_l(desc);
+ AudioSystem::unregisterEffect(effect->id());
+ }
+ if (chainCreated) {
+ removeEffectChain_l(chain);
}
handle.clear();
}
@@ -4798,26 +4918,71 @@ Exit:
return handle;
}
-void AudioFlinger::PlaybackThread::disconnectEffect(const sp< EffectModule>& effect,
- const wp<EffectHandle>& handle) {
+// PlaybackThread::addEffect_l() must be called with AudioFlinger::mLock and
+// PlaybackThread::mLock held
+status_t AudioFlinger::PlaybackThread::addEffect_l(const sp<EffectModule>& effect)
+{
+ // check for existing effect chain with the requested audio session
+ int sessionId = effect->sessionId();
+ sp<EffectChain> chain = getEffectChain_l(sessionId);
+ bool chainCreated = false;
+
+ if (chain == 0) {
+ // create a new chain for this session
+ LOGV("addEffect_l() new effect chain for session %d", sessionId);
+ chain = new EffectChain(this, sessionId);
+ addEffectChain_l(chain);
+ chain->setStrategy(getStrategyForSession_l(sessionId));
+ chainCreated = true;
+ }
+ LOGV("addEffect_l() %p chain %p effect %p", this, chain.get(), effect.get());
+
+ if (chain->getEffectFromId_l(effect->id()) != 0) {
+ LOGW("addEffect_l() %p effect %s already present in chain %p",
+ this, effect->desc().name, chain.get());
+ return BAD_VALUE;
+ }
+
+ status_t status = chain->addEffect_l(effect);
+ if (status != NO_ERROR) {
+ if (chainCreated) {
+ removeEffectChain_l(chain);
+ }
+ return status;
+ }
+
+ effect->setDevice(mDevice);
+ effect->setMode(mAudioFlinger->getMode());
+ return NO_ERROR;
+}
+
+void AudioFlinger::PlaybackThread::removeEffect_l(const sp<EffectModule>& effect) {
+
+ LOGV("removeEffect_l() %p effect %p", this, effect.get());
effect_descriptor_t desc = effect->desc();
+ if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
+ detachAuxEffect_l(effect->id());
+ }
+
+ sp<EffectChain> chain = effect->chain().promote();
+ if (chain != 0) {
+ // remove effect chain if removing last effect
+ if (chain->removeEffect_l(effect) == 0) {
+ removeEffectChain_l(chain);
+ }
+ } else {
+ LOGW("removeEffect_l() %p cannot promote chain for effect %p", this, effect.get());
+ }
+}
+
+void AudioFlinger::PlaybackThread::disconnectEffect(const sp<EffectModule>& effect,
+ const wp<EffectHandle>& handle) {
Mutex::Autolock _l(mLock);
+ LOGV("disconnectEffect() %p effect %p", this, effect.get());
// delete the effect module if removing last handle on it
if (effect->removeHandle(handle) == 0) {
- if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
- detachAuxEffect_l(effect->id());
- }
- sp<EffectChain> chain = effect->chain().promote();
- if (chain != 0) {
- // remove effect chain if remove last effect
- if (chain->removeEffect(effect) == 0) {
- removeEffectChain_l(chain);
- }
- }
- mLock.unlock();
- mAudioFlinger->mLock.lock();
- mAudioFlinger->unregisterEffectResource_l(&desc);
- mAudioFlinger->mLock.unlock();
+ removeEffect_l(effect);
+ AudioSystem::unregisterEffect(effect->id());
}
}
@@ -4861,13 +5026,16 @@ status_t AudioFlinger::PlaybackThread::addEffectChain_l(const sp<EffectChain>& c
chain->setInBuffer(buffer, ownsBuffer);
chain->setOutBuffer(mMixBuffer);
- // Effect chain for session -1 is inserted at end of effect chains list
- // in order to be processed last as it contains output stage effects
- // Effect chain for session 0 is inserted before session -1 to be processed
+ // Effect chain for session AudioSystem::SESSION_OUTPUT_STAGE is inserted at end of effect
+ // chains list in order to be processed last as it contains output stage effects
+ // Effect chain for session AudioSystem::SESSION_OUTPUT_MIX is inserted before
+ // session AudioSystem::SESSION_OUTPUT_STAGE to be processed
// after track specific effects and before output stage
- // Effect chain for session other than 0 is inserted at beginning of effect
- // chains list to be processed before output mix effects. Relative order between
- // sessions other than 0 is not important
+ // It is therefore mandatory that AudioSystem::SESSION_OUTPUT_MIX == 0 and
+ // that AudioSystem::SESSION_OUTPUT_STAGE < AudioSystem::SESSION_OUTPUT_MIX
+ // Effect chain for other sessions are inserted at beginning of effect
+ // chains list to be processed before output mix effects. Relative order between other
+ // sessions is not important
size_t size = mEffectChains.size();
size_t i = 0;
for (i = 0; i < size; i++) {
@@ -4894,52 +5062,58 @@ size_t AudioFlinger::PlaybackThread::removeEffectChain_l(const sp<EffectChain>&
track->setMainBuffer(mMixBuffer);
}
}
+ break;
}
}
return mEffectChains.size();
}
-void AudioFlinger::PlaybackThread::lockEffectChains_l()
+void AudioFlinger::PlaybackThread::lockEffectChains_l(
+ Vector<sp <AudioFlinger::EffectChain> >& effectChains)
{
+ effectChains = mEffectChains;
for (size_t i = 0; i < mEffectChains.size(); i++) {
mEffectChains[i]->lock();
}
}
-void AudioFlinger::PlaybackThread::unlockEffectChains()
+void AudioFlinger::PlaybackThread::unlockEffectChains(
+ Vector<sp <AudioFlinger::EffectChain> >& effectChains)
{
- Mutex::Autolock _l(mLock);
- for (size_t i = 0; i < mEffectChains.size(); i++) {
- mEffectChains[i]->unlock();
+ for (size_t i = 0; i < effectChains.size(); i++) {
+ effectChains[i]->unlock();
}
}
+
sp<AudioFlinger::EffectModule> AudioFlinger::PlaybackThread::getEffect_l(int sessionId, int effectId)
{
sp<EffectModule> effect;
sp<EffectChain> chain = getEffectChain_l(sessionId);
if (chain != 0) {
- effect = chain->getEffectFromId(effectId);
+ effect = chain->getEffectFromId_l(effectId);
}
return effect;
}
-status_t AudioFlinger::PlaybackThread::attachAuxEffect(const sp<AudioFlinger::PlaybackThread::Track> track, int EffectId)
+status_t AudioFlinger::PlaybackThread::attachAuxEffect(
+ const sp<AudioFlinger::PlaybackThread::Track> track, int EffectId)
{
Mutex::Autolock _l(mLock);
return attachAuxEffect_l(track, EffectId);
}
-status_t AudioFlinger::PlaybackThread::attachAuxEffect_l(const sp<AudioFlinger::PlaybackThread::Track> track, int EffectId)
+status_t AudioFlinger::PlaybackThread::attachAuxEffect_l(
+ const sp<AudioFlinger::PlaybackThread::Track> track, int EffectId)
{
status_t status = NO_ERROR;
if (EffectId == 0) {
track->setAuxBuffer(0, NULL);
} else {
- // Auxiliary effects are always in audio session 0
- sp<EffectModule> effect = getEffect_l(0, EffectId);
+ // Auxiliary effects are always in audio session AudioSystem::SESSION_OUTPUT_MIX
+ sp<EffectModule> effect = getEffect_l(AudioSystem::SESSION_OUTPUT_MIX, EffectId);
if (effect != 0) {
if ((effect->desc().flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
track->setAuxBuffer(EffectId, (int32_t *)effect->inBuffer());
@@ -5135,7 +5309,7 @@ void AudioFlinger::EffectModule::process()
if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
AudioMixer::ditherAndClamp(mConfig.inputCfg.buffer.s32,
mConfig.inputCfg.buffer.s32,
- mConfig.inputCfg.buffer.frameCount);
+ mConfig.inputCfg.buffer.frameCount/2);
}
// do the actual processing in the effect engine
@@ -5212,7 +5386,8 @@ status_t AudioFlinger::EffectModule::configure()
mConfig.outputCfg.bufferProvider.releaseBuffer = NULL;
mConfig.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
// Insert effect:
- // - in session 0 or -1, always overwrites output buffer: input buffer == output buffer
+ // - in session AudioSystem::SESSION_OUTPUT_MIX or AudioSystem::SESSION_OUTPUT_STAGE,
+ // always overwrites output buffer: input buffer == output buffer
// - in other sessions:
// last effect in the chain accumulates in output buffer: input buffer != output buffer
// other effect: overwrites output buffer: input buffer == output buffer
@@ -5229,6 +5404,9 @@ status_t AudioFlinger::EffectModule::configure()
mConfig.inputCfg.buffer.frameCount = thread->frameCount();
mConfig.outputCfg.buffer.frameCount = mConfig.inputCfg.buffer.frameCount;
+ LOGV("configure() %p thread %p buffer %p framecount %d",
+ this, thread.get(), mConfig.inputCfg.buffer.raw, mConfig.inputCfg.buffer.frameCount);
+
status_t cmdStatus;
int size = sizeof(int);
status_t status = (*mEffectInterface)->command(mEffectInterface, EFFECT_CMD_CONFIGURE, sizeof(effect_config_t), &mConfig, &size, &cmdStatus);
@@ -5365,7 +5543,9 @@ status_t AudioFlinger::EffectModule::setVolume(uint32_t *left, uint32_t *right,
// Send volume indication if EFFECT_FLAG_VOLUME_IND is set and read back altered volume
// if controller flag is set (Note that controller == TRUE => EFFECT_FLAG_VOLUME_CTRL set)
- if ((mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) & (EFFECT_FLAG_VOLUME_CTRL|EFFECT_FLAG_VOLUME_IND)) {
+ if ((mState >= ACTIVE) &&
+ ((mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_CTRL ||
+ (mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_IND)) {
status_t cmdStatus;
uint32_t volume[2];
uint32_t *pVolume = NULL;
@@ -5745,9 +5925,11 @@ void AudioFlinger::EffectHandle::dump(char* buffer, size_t size)
AudioFlinger::EffectChain::EffectChain(const wp<ThreadBase>& wThread,
int sessionId)
- : mThread(wThread), mSessionId(sessionId), mVolumeCtrlIdx(-1), mActiveTrackCnt(0), mOwnInBuffer(false)
+ : mThread(wThread), mSessionId(sessionId), mActiveTrackCnt(0), mOwnInBuffer(false),
+ mVolumeCtrlIdx(-1), mLeftVolume(0), mRightVolume(0),
+ mNewLeftVolume(0), mNewRightVolume(0)
{
-
+ mStrategy = AudioSystem::getStrategyForStream(AudioSystem::MUSIC);
}
AudioFlinger::EffectChain::~EffectChain()
@@ -5758,7 +5940,8 @@ AudioFlinger::EffectChain::~EffectChain()
}
-sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromDesc(effect_descriptor_t *descriptor)
+// getEffectFromDesc_l() must be called with PlaybackThread::mLock held
+sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromDesc_l(effect_descriptor_t *descriptor)
{
sp<EffectModule> effect;
size_t size = mEffects.size();
@@ -5772,13 +5955,15 @@ sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromDesc(effe
return effect;
}
-sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromId(int id)
+// getEffectFromId_l() must be called with PlaybackThread::mLock held
+sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromId_l(int id)
{
sp<EffectModule> effect;
size_t size = mEffects.size();
for (size_t i = 0; i < size; i++) {
- if (mEffects[i]->id() == id) {
+ // by convention, return first effect if id provided is 0 (0 is never a valid id)
+ if (id == 0 || mEffects[i]->id() == id) {
effect = mEffects[i];
break;
}
@@ -5807,21 +5992,25 @@ void AudioFlinger::EffectChain::process_l()
}
}
-status_t AudioFlinger::EffectChain::addEffect(sp<EffectModule>& effect)
+// addEffect_l() must be called with PlaybackThread::mLock held
+status_t AudioFlinger::EffectChain::addEffect_l(const sp<EffectModule>& effect)
{
effect_descriptor_t desc = effect->desc();
uint32_t insertPref = desc.flags & EFFECT_FLAG_INSERT_MASK;
Mutex::Autolock _l(mLock);
+ effect->setChain(this);
+ sp<ThreadBase> thread = mThread.promote();
+ if (thread == 0) {
+ return NO_INIT;
+ }
+ effect->setThread(thread);
if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
// Auxiliary effects are inserted at the beginning of mEffects vector as
// they are processed first and accumulated in chain input buffer
mEffects.insertAt(effect, 0);
- sp<ThreadBase> thread = mThread.promote();
- if (thread == 0) {
- return NO_INIT;
- }
+
// the input buffer for auxiliary effect contains mono samples in
// 32 bit format. This is to avoid saturation in AudoMixer
// accumulation stage. Saturation is done in EffectModule::process() before
@@ -5860,7 +6049,7 @@ status_t AudioFlinger::EffectChain::addEffect(sp<EffectModule>& effect)
// check invalid effect chaining combinations
if (insertPref == EFFECT_FLAG_INSERT_EXCLUSIVE ||
iPref == EFFECT_FLAG_INSERT_EXCLUSIVE) {
- LOGW("addEffect() could not insert effect %s: exclusive conflict with %s", desc.name, d.name);
+ LOGW("addEffect_l() could not insert effect %s: exclusive conflict with %s", desc.name, d.name);
return INVALID_OPERATION;
}
// remember position of first insert effect and by default
@@ -5910,22 +6099,17 @@ status_t AudioFlinger::EffectChain::addEffect(sp<EffectModule>& effect)
effect->setOutBuffer(mInBuffer);
}
mEffects.insertAt(effect, idx_insert);
- // Always give volume control to last effect in chain with volume control capability
- if (((desc.flags & EFFECT_FLAG_VOLUME_MASK) & EFFECT_FLAG_VOLUME_CTRL) &&
- mVolumeCtrlIdx < idx_insert) {
- mVolumeCtrlIdx = idx_insert;
- }
- LOGV("addEffect() effect %p, added in chain %p at rank %d", effect.get(), this, idx_insert);
+ LOGV("addEffect_l() effect %p, added in chain %p at rank %d", effect.get(), this, idx_insert);
}
effect->configure();
return NO_ERROR;
}
-size_t AudioFlinger::EffectChain::removeEffect(const sp<EffectModule>& effect)
+// removeEffect_l() must be called with PlaybackThread::mLock held
+size_t AudioFlinger::EffectChain::removeEffect_l(const sp<EffectModule>& effect)
{
Mutex::Autolock _l(mLock);
-
int size = (int)mEffects.size();
int i;
uint32_t type = effect->desc().flags & EFFECT_FLAG_TYPE_MASK;
@@ -5941,26 +6125,16 @@ size_t AudioFlinger::EffectChain::removeEffect(const sp<EffectModule>& effect)
}
}
mEffects.removeAt(i);
- LOGV("removeEffect() effect %p, removed from chain %p at rank %d", effect.get(), this, i);
+ LOGV("removeEffect_l() effect %p, removed from chain %p at rank %d", effect.get(), this, i);
break;
}
}
- // Return volume control to last effect in chain with volume control capability
- if (mVolumeCtrlIdx == i) {
- size = (int)mEffects.size();
- for (i = size; i > 0; i--) {
- if ((mEffects[i - 1]->desc().flags & EFFECT_FLAG_VOLUME_MASK) & EFFECT_FLAG_VOLUME_CTRL) {
- break;
- }
- }
- // mVolumeCtrlIdx reset to -1 if no effect found with volume control flag set
- mVolumeCtrlIdx = i - 1;
- }
return mEffects.size();
}
-void AudioFlinger::EffectChain::setDevice(uint32_t device)
+// setDevice_l() must be called with PlaybackThread::mLock held
+void AudioFlinger::EffectChain::setDevice_l(uint32_t device)
{
size_t size = mEffects.size();
for (size_t i = 0; i < size; i++) {
@@ -5968,7 +6142,8 @@ void AudioFlinger::EffectChain::setDevice(uint32_t device)
}
}
-void AudioFlinger::EffectChain::setMode(uint32_t mode)
+// setMode_l() must be called with PlaybackThread::mLock held
+void AudioFlinger::EffectChain::setMode_l(uint32_t mode)
{
size_t size = mEffects.size();
for (size_t i = 0; i < size; i++) {
@@ -5976,27 +6151,56 @@ void AudioFlinger::EffectChain::setMode(uint32_t mode)
}
}
-bool AudioFlinger::EffectChain::setVolume(uint32_t *left, uint32_t *right)
+// setVolume_l() must be called with PlaybackThread::mLock held
+bool AudioFlinger::EffectChain::setVolume_l(uint32_t *left, uint32_t *right)
{
uint32_t newLeft = *left;
uint32_t newRight = *right;
bool hasControl = false;
+ int ctrlIdx = -1;
+ size_t size = mEffects.size();
+
+ // first update volume controller
+ for (size_t i = size; i > 0; i--) {
+ if ((mEffects[i - 1]->state() >= EffectModule::ACTIVE) &&
+ (mEffects[i - 1]->desc().flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_CTRL) {
+ ctrlIdx = i - 1;
+ hasControl = true;
+ break;
+ }
+ }
- // first get volume update from volume controller
- if (mVolumeCtrlIdx >= 0) {
- mEffects[mVolumeCtrlIdx]->setVolume(&newLeft, &newRight, true);
+ if (ctrlIdx == mVolumeCtrlIdx && *left == mLeftVolume && *right == mRightVolume) {
+ if (hasControl) {
+ *left = mNewLeftVolume;
+ *right = mNewRightVolume;
+ }
+ return hasControl;
+ }
+
+ if (mVolumeCtrlIdx != -1) {
hasControl = true;
}
+ mVolumeCtrlIdx = ctrlIdx;
+ mLeftVolume = newLeft;
+ mRightVolume = newRight;
+
+ // second get volume update from volume controller
+ if (ctrlIdx >= 0) {
+ mEffects[ctrlIdx]->setVolume(&newLeft, &newRight, true);
+ mNewLeftVolume = newLeft;
+ mNewRightVolume = newRight;
+ }
// then indicate volume to all other effects in chain.
// Pass altered volume to effects before volume controller
// and requested volume to effects after controller
uint32_t lVol = newLeft;
uint32_t rVol = newRight;
- size_t size = mEffects.size();
+
for (size_t i = 0; i < size; i++) {
- if ((int)i == mVolumeCtrlIdx) continue;
- // this also works for mVolumeCtrlIdx == -1 when there is no volume controller
- if ((int)i > mVolumeCtrlIdx) {
+ if ((int)i == ctrlIdx) continue;
+ // this also works for ctrlIdx == -1 when there is no volume controller
+ if ((int)i > ctrlIdx) {
lVol = *left;
rVol = *right;
}
@@ -6008,16 +6212,6 @@ bool AudioFlinger::EffectChain::setVolume(uint32_t *left, uint32_t *right)
return hasControl;
}
-sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getVolumeController()
-{
- sp<EffectModule> effect;
- if (mVolumeCtrlIdx >= 0) {
- effect = mEffects[mVolumeCtrlIdx];
- }
- return effect;
-}
-
-
status_t AudioFlinger::EffectChain::dump(int fd, const Vector<String16>& args)
{
const size_t SIZE = 256;
@@ -6033,12 +6227,11 @@ status_t AudioFlinger::EffectChain::dump(int fd, const Vector<String16>& args)
result.append("\tCould not lock mutex:\n");
}
- result.append("\tNum fx In buffer Out buffer Vol ctrl Active tracks:\n");
- snprintf(buffer, SIZE, "\t%02d 0x%08x 0x%08x %02d %d\n",
+ result.append("\tNum fx In buffer Out buffer Active tracks:\n");
+ snprintf(buffer, SIZE, "\t%02d 0x%08x 0x%08x %d\n",
mEffects.size(),
(uint32_t)mInBuffer,
(uint32_t)mOutBuffer,
- (mVolumeCtrlIdx == -1) ? 0 : mEffects[mVolumeCtrlIdx]->id(),
mActiveTrackCnt);
result.append(buffer);
write(fd, result.string(), result.size());