From: Eric Laurent Date: Thu, 4 Apr 2013 00:31:04 +0000 (-0700) Subject: audio policy: reuse direct output when possible X-Git-Tag: android-x86-4.4-r1~21^2~5 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=5a950c96;p=android-x86%2Fhardware-libhardware_legacy.git 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 --- 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 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++) { diff --git a/include/hardware_legacy/AudioPolicyManagerBase.h b/include/hardware_legacy/AudioPolicyManagerBase.h index c5a917c..7ba71e7 100644 --- a/include/hardware_legacy/AudioPolicyManagerBase.h +++ b/include/hardware_legacy/AudioPolicyManagerBase.h @@ -275,6 +275,7 @@ protected: const IOProfile *mProfile; // I/O profile this output derives from bool mStrategyMutedByDevice[NUM_STRATEGIES]; // strategies muted because of incompatible // device selection. See checkDeviceMuteStrategies() + uint32_t mDirectOpenCount; // number of clients using this output (direct outputs only) }; // descriptor for audio inputs. Used to maintain current configuration of each opened audio input