diff options
author | Eric Laurent <elaurent@google.com> | 2015-03-17 15:29:32 -0700 |
---|---|---|
committer | Eric Laurent <elaurent@google.com> | 2015-04-08 18:08:11 -0700 |
commit | c75307b73d324d590d0dbc05b44bce9aa89b7145 (patch) | |
tree | 824a23a9ffbebb3ace63146c171e938df6630fdd /services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp | |
parent | 303db9de6506db0c2b300863c39ece81721dd4e9 (diff) | |
download | frameworks_av-c75307b73d324d590d0dbc05b44bce9aa89b7145.zip frameworks_av-c75307b73d324d590d0dbc05b44bce9aa89b7145.tar.gz frameworks_av-c75307b73d324d590d0dbc05b44bce9aa89b7145.tar.bz2 |
audio policy: volume control reorganization
Output volume and routing control by AudioOutputDescriptor
is reorganized to prepare hardware source volume and routing
control.
AudioOutputDescriptor contains all volume, device and activity
state common to software (audio flinger mixers) and
hardware sources (tuners, A2DP, HDMI).
A new class SwAudioOutputDescriptor is derived from
AudioOutputDescriptor and is specific to software sources.
Low level routing and volume control methods receive an
AudioOutputDescriptor parameter instead of an IO handle.
mPrimaryOutput is now an AudioOutputDescriptor.
Change-Id: Ie90943ee3102cdb8adf89fdd2addd2c279b1e5bf
Diffstat (limited to 'services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp')
-rw-r--r-- | services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp | 290 |
1 files changed, 207 insertions, 83 deletions
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp index 8de8cd8..0837a54 100644 --- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp +++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp @@ -17,6 +17,7 @@ #define LOG_TAG "APM::AudioOutputDescriptor" //#define LOG_NDEBUG 0 +#include <AudioPolicyInterface.h> #include "AudioOutputDescriptor.h" #include "IOProfile.h" #include "AudioGain.h" @@ -29,12 +30,10 @@ namespace android { -AudioOutputDescriptor::AudioOutputDescriptor(const sp<IOProfile>& profile) - : mIoHandle(0), mLatency(0), - mFlags((audio_output_flags_t)0), mDevice(AUDIO_DEVICE_NONE), mPolicyMix(NULL), - mPatchHandle(0), - mOutput1(0), mOutput2(0), mProfile(profile), mDirectOpenCount(0), - mId(0) +AudioOutputDescriptor::AudioOutputDescriptor(const sp<AudioPort>& port, + AudioPolicyClientInterface *clientInterface) + : mPort(port), mDevice(AUDIO_DEVICE_NONE), + mPatchHandle(0), mClientInterface(clientInterface), mId(0) { // clear usage count for all stream types for (int i = 0; i < AUDIO_STREAM_CNT; i++) { @@ -46,23 +45,19 @@ AudioOutputDescriptor::AudioOutputDescriptor(const sp<IOProfile>& profile) for (int i = 0; i < NUM_STRATEGIES; i++) { mStrategyMutedByDevice[i] = false; } - if (profile != NULL) { - mFlags = (audio_output_flags_t)profile->mFlags; - mSamplingRate = profile->pickSamplingRate(); - mFormat = profile->pickFormat(); - mChannelMask = profile->pickChannelMask(); - if (profile->mGains.size() > 0) { - profile->mGains[0]->getDefaultConfig(&mGain); + if (port != NULL) { + mSamplingRate = port->pickSamplingRate(); + mFormat = port->pickFormat(); + mChannelMask = port->pickChannelMask(); + if (port->mGains.size() > 0) { + port->mGains[0]->getDefaultConfig(&mGain); } } } audio_module_handle_t AudioOutputDescriptor::getModuleHandle() const { - if (mProfile == 0) { - return 0; - } - return mProfile->getModuleHandle(); + return mPort->getModuleHandle(); } audio_port_handle_t AudioOutputDescriptor::getId() const @@ -72,35 +67,20 @@ audio_port_handle_t AudioOutputDescriptor::getId() const audio_devices_t AudioOutputDescriptor::device() const { - if (isDuplicated()) { - return (audio_devices_t)(mOutput1->mDevice | mOutput2->mDevice); - } else { - return mDevice; - } + return mDevice; } -void AudioOutputDescriptor::setIoHandle(audio_io_handle_t ioHandle) -{ - mId = AudioPort::getNextUniqueId(); - mIoHandle = ioHandle; -} - -uint32_t AudioOutputDescriptor::latency() +audio_devices_t AudioOutputDescriptor::supportedDevices() { - if (isDuplicated()) { - return (mOutput1->mLatency > mOutput2->mLatency) ? mOutput1->mLatency : mOutput2->mLatency; - } else { - return mLatency; - } + return mDevice; } bool AudioOutputDescriptor::sharesHwModuleWith( const sp<AudioOutputDescriptor> outputDesc) { - if (isDuplicated()) { - return mOutput1->sharesHwModuleWith(outputDesc) || mOutput2->sharesHwModuleWith(outputDesc); - } else if (outputDesc->isDuplicated()){ - return sharesHwModuleWith(outputDesc->mOutput1) || sharesHwModuleWith(outputDesc->mOutput2); + if (outputDesc->isDuplicated()) { + return sharesHwModuleWith(outputDesc->subOutput1()) || + sharesHwModuleWith(outputDesc->subOutput2()); } else { return (getModuleHandle() == outputDesc->getModuleHandle()); } @@ -109,11 +89,6 @@ bool AudioOutputDescriptor::sharesHwModuleWith( void AudioOutputDescriptor::changeRefCount(audio_stream_type_t stream, int delta) { - // forward usage count change to attached outputs - if (isDuplicated()) { - mOutput1->changeRefCount(stream, delta); - mOutput2->changeRefCount(stream, delta); - } if ((delta + (int)mRefCount[stream]) < 0) { ALOGW("changeRefCount() invalid delta %d for stream %d, refCount %d", delta, stream, mRefCount[stream]); @@ -124,15 +99,6 @@ void AudioOutputDescriptor::changeRefCount(audio_stream_type_t stream, ALOGV("changeRefCount() stream %d, count %d", stream, mRefCount[stream]); } -audio_devices_t AudioOutputDescriptor::supportedDevices() -{ - if (isDuplicated()) { - return (audio_devices_t)(mOutput1->supportedDevices() | mOutput2->supportedDevices()); - } else { - return mProfile->mSupportedDevices.types() ; - } -} - bool AudioOutputDescriptor::isActive(uint32_t inPastMs) const { nsecs_t sysTime = 0; @@ -169,12 +135,33 @@ bool AudioOutputDescriptor::isStreamActive(audio_stream_type_t stream, return false; } + +bool AudioOutputDescriptor::isFixedVolume(audio_devices_t device __unused) +{ + return false; +} + +bool AudioOutputDescriptor::setVolume(float volume, + audio_stream_type_t stream, + audio_devices_t device __unused, + uint32_t delayMs, + bool force) +{ + // We actually change the volume if: + // - the float value returned by computeVolume() changed + // - the force flag is set + if (volume != mCurVolume[stream] || force) { + ALOGV("setVolume() for stream %d, volume %f, delay %d", stream, volume, delayMs); + mCurVolume[stream] = volume; + return true; + } + return false; +} + void AudioOutputDescriptor::toAudioPortConfig( struct audio_port_config *dstConfig, const struct audio_port_config *srcConfig) const { - ALOG_ASSERT(!isDuplicated(), "toAudioPortConfig() called on duplicated output %d", mIoHandle); - dstConfig->config_mask = AUDIO_PORT_CONFIG_SAMPLE_RATE|AUDIO_PORT_CONFIG_CHANNEL_MASK| AUDIO_PORT_CONFIG_FORMAT|AUDIO_PORT_CONFIG_GAIN; if (srcConfig != NULL) { @@ -186,21 +173,15 @@ void AudioOutputDescriptor::toAudioPortConfig( dstConfig->role = AUDIO_PORT_ROLE_SOURCE; dstConfig->type = AUDIO_PORT_TYPE_MIX; dstConfig->ext.mix.hw_module = getModuleHandle(); - dstConfig->ext.mix.handle = mIoHandle; dstConfig->ext.mix.usecase.stream = AUDIO_STREAM_DEFAULT; } void AudioOutputDescriptor::toAudioPort( struct audio_port *port) const { - ALOG_ASSERT(!isDuplicated(), "toAudioPort() called on duplicated output %d", mIoHandle); - mProfile->toAudioPort(port); + mPort->toAudioPort(port); port->id = mId; - toAudioPortConfig(&port->active_config); port->ext.mix.hw_module = getModuleHandle(); - port->ext.mix.handle = mIoHandle; - port->ext.mix.latency_class = - mFlags & AUDIO_OUTPUT_FLAG_FAST ? AUDIO_LATENCY_LOW : AUDIO_LATENCY_NORMAL; } status_t AudioOutputDescriptor::dump(int fd) @@ -209,7 +190,7 @@ status_t AudioOutputDescriptor::dump(int fd) char buffer[SIZE]; String8 result; - snprintf(buffer, SIZE, " ID: %d\n", getId()); + snprintf(buffer, SIZE, " ID: %d\n", mId); result.append(buffer); snprintf(buffer, SIZE, " Sampling rate: %d\n", mSamplingRate); result.append(buffer); @@ -217,10 +198,6 @@ status_t AudioOutputDescriptor::dump(int fd) result.append(buffer); snprintf(buffer, SIZE, " Channels: %08x\n", mChannelMask); result.append(buffer); - snprintf(buffer, SIZE, " Latency: %d\n", mLatency); - result.append(buffer); - snprintf(buffer, SIZE, " Flags %08x\n", mFlags); - result.append(buffer); snprintf(buffer, SIZE, " Devices %08x\n", device()); result.append(buffer); snprintf(buffer, SIZE, " Stream volume refCount muteCount\n"); @@ -237,15 +214,162 @@ status_t AudioOutputDescriptor::dump(int fd) void AudioOutputDescriptor::log(const char* indent) { - ALOGI("%sID: %d,0x%X, [rt:%d fmt:0x%X ch:0x%X] hndl:%d", - indent, mId, mId, mSamplingRate, mFormat, mChannelMask, mIoHandle); + ALOGI("%sID: %d,0x%X, [rt:%d fmt:0x%X ch:0x%X]", + indent, mId, mId, mSamplingRate, mFormat, mChannelMask); +} + +// SwAudioOutputDescriptor implementation +SwAudioOutputDescriptor::SwAudioOutputDescriptor( + const sp<IOProfile>& profile, AudioPolicyClientInterface *clientInterface) + : AudioOutputDescriptor(profile, clientInterface), + mProfile(profile), mIoHandle(0), mLatency(0), + mFlags((audio_output_flags_t)0), mPolicyMix(NULL), + mOutput1(0), mOutput2(0), mDirectOpenCount(0) +{ + if (profile != NULL) { + mFlags = (audio_output_flags_t)profile->mFlags; + } +} + +void SwAudioOutputDescriptor::setIoHandle(audio_io_handle_t ioHandle) +{ + mId = AudioPort::getNextUniqueId(); + mIoHandle = ioHandle; +} + + +status_t SwAudioOutputDescriptor::dump(int fd) +{ + const size_t SIZE = 256; + char buffer[SIZE]; + String8 result; + + snprintf(buffer, SIZE, " Latency: %d\n", mLatency); + result.append(buffer); + snprintf(buffer, SIZE, " Flags %08x\n", mFlags); + result.append(buffer); + write(fd, result.string(), result.size()); + + AudioOutputDescriptor::dump(fd); + + return NO_ERROR; +} + +audio_devices_t SwAudioOutputDescriptor::device() const +{ + if (isDuplicated()) { + return (audio_devices_t)(mOutput1->mDevice | mOutput2->mDevice); + } else { + return mDevice; + } } -bool AudioOutputCollection::isStreamActive(audio_stream_type_t stream, uint32_t inPastMs) const +bool SwAudioOutputDescriptor::sharesHwModuleWith( + const sp<AudioOutputDescriptor> outputDesc) +{ + if (isDuplicated()) { + return mOutput1->sharesHwModuleWith(outputDesc) || mOutput2->sharesHwModuleWith(outputDesc); + } else if (outputDesc->isDuplicated()){ + return sharesHwModuleWith(outputDesc->subOutput1()) || + sharesHwModuleWith(outputDesc->subOutput2()); + } else { + return AudioOutputDescriptor::sharesHwModuleWith(outputDesc); + } +} + +audio_devices_t SwAudioOutputDescriptor::supportedDevices() +{ + if (isDuplicated()) { + return (audio_devices_t)(mOutput1->supportedDevices() | mOutput2->supportedDevices()); + } else { + return mProfile->mSupportedDevices.types() ; + } +} + +uint32_t SwAudioOutputDescriptor::latency() +{ + if (isDuplicated()) { + return (mOutput1->mLatency > mOutput2->mLatency) ? mOutput1->mLatency : mOutput2->mLatency; + } else { + return mLatency; + } +} + +void SwAudioOutputDescriptor::changeRefCount(audio_stream_type_t stream, + int delta) +{ + // forward usage count change to attached outputs + if (isDuplicated()) { + mOutput1->changeRefCount(stream, delta); + mOutput2->changeRefCount(stream, delta); + } + AudioOutputDescriptor::changeRefCount(stream, delta); +} + + +bool SwAudioOutputDescriptor::isFixedVolume(audio_devices_t device) +{ + // unit gain if rerouting to external policy + if (device == AUDIO_DEVICE_OUT_REMOTE_SUBMIX) { + if (mPolicyMix != NULL) { + ALOGV("max gain when rerouting for output=%d", mIoHandle); + return true; + } + } + return false; +} + +void SwAudioOutputDescriptor::toAudioPortConfig( + struct audio_port_config *dstConfig, + const struct audio_port_config *srcConfig) const +{ + + ALOG_ASSERT(!isDuplicated(), "toAudioPortConfig() called on duplicated output %d", mIoHandle); + AudioOutputDescriptor::toAudioPortConfig(dstConfig, srcConfig); + + dstConfig->ext.mix.handle = mIoHandle; +} + +void SwAudioOutputDescriptor::toAudioPort( + struct audio_port *port) const +{ + ALOG_ASSERT(!isDuplicated(), "toAudioPort() called on duplicated output %d", mIoHandle); + + AudioOutputDescriptor::toAudioPort(port); + + toAudioPortConfig(&port->active_config); + port->ext.mix.handle = mIoHandle; + port->ext.mix.latency_class = + mFlags & AUDIO_OUTPUT_FLAG_FAST ? AUDIO_LATENCY_LOW : AUDIO_LATENCY_NORMAL; +} + +bool SwAudioOutputDescriptor::setVolume(float volume, + audio_stream_type_t stream, + audio_devices_t device, + uint32_t delayMs, + bool force) +{ + bool changed = AudioOutputDescriptor::setVolume(volume, stream, device, delayMs, force); + + if (changed) { + // Force VOICE_CALL to track BLUETOOTH_SCO stream volume when bluetooth audio is + // enabled + if (stream == AUDIO_STREAM_BLUETOOTH_SCO) { + mClientInterface->setStreamVolume( + AUDIO_STREAM_VOICE_CALL, mCurVolume[stream], mIoHandle, delayMs); + } + mClientInterface->setStreamVolume(stream, mCurVolume[stream], mIoHandle, delayMs); + } + return changed; +} + +// SwAudioOutputCollection implementation + +bool SwAudioOutputCollection::isStreamActive(audio_stream_type_t stream, uint32_t inPastMs) const { nsecs_t sysTime = systemTime(); for (size_t i = 0; i < this->size(); i++) { - const sp<AudioOutputDescriptor> outputDesc = this->valueAt(i); + const sp<SwAudioOutputDescriptor> outputDesc = this->valueAt(i); if (outputDesc->isStreamActive(stream, inPastMs, sysTime)) { return true; } @@ -253,12 +377,12 @@ bool AudioOutputCollection::isStreamActive(audio_stream_type_t stream, uint32_t return false; } -bool AudioOutputCollection::isStreamActiveRemotely(audio_stream_type_t stream, +bool SwAudioOutputCollection::isStreamActiveRemotely(audio_stream_type_t stream, uint32_t inPastMs) const { nsecs_t sysTime = systemTime(); for (size_t i = 0; i < size(); i++) { - const sp<AudioOutputDescriptor> outputDesc = valueAt(i); + const sp<SwAudioOutputDescriptor> outputDesc = valueAt(i); if (((outputDesc->device() & APM_AUDIO_OUT_DEVICE_REMOTE_ALL) != 0) && outputDesc->isStreamActive(stream, inPastMs, sysTime)) { // do not consider re routing (when the output is going to a dynamic policy) @@ -271,10 +395,10 @@ bool AudioOutputCollection::isStreamActiveRemotely(audio_stream_type_t stream, return false; } -audio_io_handle_t AudioOutputCollection::getA2dpOutput() const +audio_io_handle_t SwAudioOutputCollection::getA2dpOutput() const { for (size_t i = 0; i < size(); i++) { - sp<AudioOutputDescriptor> outputDesc = valueAt(i); + sp<SwAudioOutputDescriptor> outputDesc = valueAt(i); if (!outputDesc->isDuplicated() && outputDesc->device() & AUDIO_DEVICE_OUT_ALL_A2DP) { return this->keyAt(i); } @@ -282,10 +406,10 @@ audio_io_handle_t AudioOutputCollection::getA2dpOutput() const return 0; } -sp<AudioOutputDescriptor> AudioOutputCollection::getPrimaryOutput() const +sp<SwAudioOutputDescriptor> SwAudioOutputCollection::getPrimaryOutput() const { for (size_t i = 0; i < size(); i++) { - const sp<AudioOutputDescriptor> outputDesc = valueAt(i); + const sp<SwAudioOutputDescriptor> outputDesc = valueAt(i); if (outputDesc->mFlags & AUDIO_OUTPUT_FLAG_PRIMARY) { return outputDesc; } @@ -293,9 +417,9 @@ sp<AudioOutputDescriptor> AudioOutputCollection::getPrimaryOutput() const return NULL; } -sp<AudioOutputDescriptor> AudioOutputCollection::getOutputFromId(audio_port_handle_t id) const +sp<SwAudioOutputDescriptor> SwAudioOutputCollection::getOutputFromId(audio_port_handle_t id) const { - sp<AudioOutputDescriptor> outputDesc = NULL; + sp<SwAudioOutputDescriptor> outputDesc = NULL; for (size_t i = 0; i < size(); i++) { outputDesc = valueAt(i); if (outputDesc->getId() == id) { @@ -305,14 +429,14 @@ sp<AudioOutputDescriptor> AudioOutputCollection::getOutputFromId(audio_port_hand return outputDesc; } -bool AudioOutputCollection::isAnyOutputActive(audio_stream_type_t streamToIgnore) const +bool SwAudioOutputCollection::isAnyOutputActive(audio_stream_type_t streamToIgnore) const { for (size_t s = 0 ; s < AUDIO_STREAM_CNT ; s++) { if (s == (size_t) streamToIgnore) { continue; } for (size_t i = 0; i < size(); i++) { - const sp<AudioOutputDescriptor> outputDesc = valueAt(i); + const sp<SwAudioOutputDescriptor> outputDesc = valueAt(i); if (outputDesc->mRefCount[s] != 0) { return true; } @@ -321,15 +445,15 @@ bool AudioOutputCollection::isAnyOutputActive(audio_stream_type_t streamToIgnore return false; } -audio_devices_t AudioOutputCollection::getSupportedDevices(audio_io_handle_t handle) const +audio_devices_t SwAudioOutputCollection::getSupportedDevices(audio_io_handle_t handle) const { - sp<AudioOutputDescriptor> outputDesc = valueFor(handle); + sp<SwAudioOutputDescriptor> outputDesc = valueFor(handle); audio_devices_t devices = outputDesc->mProfile->mSupportedDevices.types(); return devices; } -status_t AudioOutputCollection::dump(int fd) const +status_t SwAudioOutputCollection::dump(int fd) const { const size_t SIZE = 256; char buffer[SIZE]; |