summaryrefslogtreecommitdiffstats
path: root/audio/AudioPolicyManagerBase.cpp
diff options
context:
space:
mode:
authorEric Laurent <elaurent@google.com>2013-04-03 17:31:04 -0700
committerEric Laurent <elaurent@google.com>2013-04-04 14:18:40 -0700
commit5a950c960cd40648cc3ab8defe817f88e0a7ecf4 (patch)
treeff6d4cc9ebfa63688b764ab314b552bb3762b88b /audio/AudioPolicyManagerBase.cpp
parent80f5b0400f86d49e70aa1a793b34f34492f005bc (diff)
downloadhardware_libhardware_legacy-5a950c960cd40648cc3ab8defe817f88e0a7ecf4.zip
hardware_libhardware_legacy-5a950c960cd40648cc3ab8defe817f88e0a7ecf4.tar.gz
hardware_libhardware_legacy-5a950c960cd40648cc3ab8defe817f88e0a7ecf4.tar.bz2
audio policy: reuse direct output when possible
Modified getOutput() logic to not systematically open a new direct output when a profile matches a request. This causes a problem when transitioning between two multichannel tracks as the audio HAL will most of the times only support one direct output stream open at a time. Instead, reuse an open output if all the parameters match or force close the output before reopening it. Also modify releaseOuput(): - close a direct output only if no client is using it anymore - call closeOutput() instead of removing the output from the open output list: this factors in code executed when closing an output stream. Bug 8388941 Change-Id: Ic3d3beb21063622ddf57a5b932f93d56f2986f54
Diffstat (limited to 'audio/AudioPolicyManagerBase.cpp')
-rw-r--r--audio/AudioPolicyManagerBase.cpp47
1 files changed, 36 insertions, 11 deletions
diff --git a/audio/AudioPolicyManagerBase.cpp b/audio/AudioPolicyManagerBase.cpp
index 90ca4a7..e755d28 100644
--- a/audio/AudioPolicyManagerBase.cpp
+++ b/audio/AudioPolicyManagerBase.cpp
@@ -556,10 +556,27 @@ audio_io_handle_t AudioPolicyManagerBase::getOutput(AudioSystem::stream_type str
channelMask,
(audio_output_flags_t)flags);
if (profile != NULL) {
+ AudioOutputDescriptor *outputDesc = NULL;
- ALOGV("getOutput() opening direct output device %x", device);
-
- AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor(profile);
+ for (size_t i = 0; i < mOutputs.size(); i++) {
+ AudioOutputDescriptor *desc = mOutputs.valueAt(i);
+ if (!desc->isDuplicated() && (profile == desc->mProfile)) {
+ outputDesc = desc;
+ // reuse direct output if currently open and configured with same parameters
+ if ((samplingRate == outputDesc->mSamplingRate) &&
+ (format == outputDesc->mFormat) &&
+ (channelMask == outputDesc->mChannelMask)) {
+ outputDesc->mDirectOpenCount++;
+ ALOGV("getOutput() reusing direct output %d", output);
+ return mOutputs.keyAt(i);
+ }
+ }
+ }
+ // close direct output if currently open and configured with different parameters
+ if (outputDesc != NULL) {
+ closeOutput(outputDesc->mId);
+ }
+ outputDesc = new AudioOutputDescriptor(profile);
outputDesc->mDevice = device;
outputDesc->mSamplingRate = samplingRate;
outputDesc->mFormat = (audio_format_t)format;
@@ -568,6 +585,7 @@ audio_io_handle_t AudioPolicyManagerBase::getOutput(AudioSystem::stream_type str
outputDesc->mFlags = (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_DIRECT);;
outputDesc->mRefCount[stream] = 0;
outputDesc->mStopTime[stream] = 0;
+ outputDesc->mDirectOpenCount = 1;
output = mpClientInterface->openOutput(profile->mModule->mHandle,
&outputDesc->mDevice,
&outputDesc->mSamplingRate,
@@ -592,7 +610,8 @@ audio_io_handle_t AudioPolicyManagerBase::getOutput(AudioSystem::stream_type str
return 0;
}
addOutput(output, outputDesc);
- ALOGV("getOutput() returns direct output %d", output);
+ mPreviousOutputs = mOutputs;
+ ALOGV("getOutput() returns new direct output %d", output);
return output;
}
@@ -808,11 +827,16 @@ void AudioPolicyManagerBase::releaseOutput(audio_io_handle_t output)
}
#endif //AUDIO_POLICY_TEST
- if (mOutputs.valueAt(index)->mFlags & AudioSystem::OUTPUT_FLAG_DIRECT) {
- mpClientInterface->closeOutput(output);
- delete mOutputs.valueAt(index);
- mOutputs.removeItem(output);
- mPreviousOutputs = mOutputs;
+ AudioOutputDescriptor *desc = mOutputs.valueAt(index);
+ if (desc->mFlags & AudioSystem::OUTPUT_FLAG_DIRECT) {
+ if (desc->mDirectOpenCount <= 0) {
+ ALOGW("releaseOutput() invalid open count %d for output %d",
+ desc->mDirectOpenCount, output);
+ return;
+ }
+ if (--desc->mDirectOpenCount == 0) {
+ closeOutput(output);
+ }
}
}
@@ -1822,8 +1846,9 @@ void AudioPolicyManagerBase::closeOutput(audio_io_handle_t output)
mpClientInterface->setParameters(output, param.toString());
mpClientInterface->closeOutput(output);
- delete mOutputs.valueFor(output);
+ delete outputDesc;
mOutputs.removeItem(output);
+ mPreviousOutputs = mOutputs;
}
SortedVector<audio_io_handle_t> AudioPolicyManagerBase::getOutputsForDevice(audio_devices_t device,
@@ -3001,7 +3026,7 @@ AudioPolicyManagerBase::AudioOutputDescriptor::AudioOutputDescriptor(
: mId(0), mSamplingRate(0), mFormat((audio_format_t)0),
mChannelMask((audio_channel_mask_t)0), mLatency(0),
mFlags((audio_output_flags_t)0), mDevice(AUDIO_DEVICE_NONE),
- mOutput1(0), mOutput2(0), mProfile(profile)
+ mOutput1(0), mOutput2(0), mProfile(profile), mDirectOpenCount(0)
{
// clear usage count for all stream types
for (int i = 0; i < AudioSystem::NUM_STREAM_TYPES; i++) {