diff options
author | Eric Laurent <elaurent@google.com> | 2015-04-09 01:11:37 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2015-04-09 01:11:37 +0000 |
commit | 9c7f67264d3b3ace9703b3a96bd7bc4922111b4f (patch) | |
tree | 42a08a11bf4d66aa8edc47f57e8912755bea76ef /services | |
parent | 3277877a576b079ebce444075735f45259660e58 (diff) | |
parent | c75307b73d324d590d0dbc05b44bce9aa89b7145 (diff) | |
download | frameworks_av-9c7f67264d3b3ace9703b3a96bd7bc4922111b4f.zip frameworks_av-9c7f67264d3b3ace9703b3a96bd7bc4922111b4f.tar.gz frameworks_av-9c7f67264d3b3ace9703b3a96bd7bc4922111b4f.tar.bz2 |
Merge "audio policy: volume control reorganization"
Diffstat (limited to 'services')
9 files changed, 571 insertions, 376 deletions
diff --git a/services/audiopolicy/common/managerdefinitions/Android.mk b/services/audiopolicy/common/managerdefinitions/Android.mk index 71ba1cb..7c265aa 100644 --- a/services/audiopolicy/common/managerdefinitions/Android.mk +++ b/services/audiopolicy/common/managerdefinitions/Android.mk @@ -25,6 +25,7 @@ LOCAL_SHARED_LIBRARIES := \ LOCAL_C_INCLUDES += \ $(LOCAL_PATH)/include \ $(TOPDIR)frameworks/av/services/audiopolicy/common/include \ + $(TOPDIR)frameworks/av/services/audiopolicy LOCAL_EXPORT_C_INCLUDE_DIRS := \ $(LOCAL_PATH)/include diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h index cc2a3bd..c6bb975 100644 --- a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h +++ b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h @@ -27,25 +27,36 @@ namespace android { class IOProfile; class AudioMix; +class AudioPolicyClientInterface; // descriptor for audio outputs. Used to maintain current configuration of each opened audio output // and keep track of the usage of this output by each audio stream type. class AudioOutputDescriptor: public AudioPortConfig { public: - AudioOutputDescriptor(const sp<IOProfile>& profile); + AudioOutputDescriptor(const sp<AudioPort>& port, + AudioPolicyClientInterface *clientInterface); + virtual ~AudioOutputDescriptor() {} status_t dump(int fd); void log(const char* indent); - audio_devices_t device() const; - void changeRefCount(audio_stream_type_t stream, int delta); audio_port_handle_t getId() const; - void setIoHandle(audio_io_handle_t ioHandle); - bool isDuplicated() const { return (mOutput1 != NULL && mOutput2 != NULL); } - audio_devices_t supportedDevices(); - uint32_t latency(); - bool sharesHwModuleWith(const sp<AudioOutputDescriptor> outputDesc); + virtual audio_devices_t device() const; + virtual bool sharesHwModuleWith(const sp<AudioOutputDescriptor> outputDesc); + virtual audio_devices_t supportedDevices(); + virtual bool isDuplicated() const { return false; } + virtual uint32_t latency() { return 0; } + virtual bool isFixedVolume(audio_devices_t device); + virtual sp<AudioOutputDescriptor> subOutput1() { return 0; } + virtual sp<AudioOutputDescriptor> subOutput2() { return 0; } + virtual bool setVolume(float volume, + audio_stream_type_t stream, + audio_devices_t device, + uint32_t delayMs, + bool force); + virtual void changeRefCount(audio_stream_type_t stream, int delta); + bool isActive(uint32_t inPastMs = 0) const; bool isStreamActive(audio_stream_type_t stream, uint32_t inPastMs = 0, @@ -53,34 +64,69 @@ public: virtual void toAudioPortConfig(struct audio_port_config *dstConfig, const struct audio_port_config *srcConfig = NULL) const; - virtual sp<AudioPort> getAudioPort() const { return mProfile; } - void toAudioPort(struct audio_port *port) const; + virtual sp<AudioPort> getAudioPort() const { return mPort; } + virtual void toAudioPort(struct audio_port *port) const; audio_module_handle_t getModuleHandle() const; - audio_io_handle_t mIoHandle; // output handle - uint32_t mLatency; // - audio_output_flags_t mFlags; // + sp<AudioPort> mPort; audio_devices_t mDevice; // current device this output is routed to - AudioMix *mPolicyMix; // non NULL when used by a dynamic policy audio_patch_handle_t mPatchHandle; uint32_t mRefCount[AUDIO_STREAM_CNT]; // number of streams of each type using this output nsecs_t mStopTime[AUDIO_STREAM_CNT]; - sp<AudioOutputDescriptor> mOutput1; // used by duplicated outputs: first output - sp<AudioOutputDescriptor> mOutput2; // used by duplicated outputs: second output float mCurVolume[AUDIO_STREAM_CNT]; // current stream volume int mMuteCount[AUDIO_STREAM_CNT]; // mute request counter - const sp<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) + AudioPolicyClientInterface *mClientInterface; -private: +protected: audio_port_handle_t mId; }; -class AudioOutputCollection : - public DefaultKeyedVector< audio_io_handle_t, sp<AudioOutputDescriptor> > +// Audio output driven by a software mixer in audio flinger. +class SwAudioOutputDescriptor: public AudioOutputDescriptor +{ +public: + SwAudioOutputDescriptor(const sp<IOProfile>& profile, + AudioPolicyClientInterface *clientInterface); + virtual ~SwAudioOutputDescriptor() {} + + status_t dump(int fd); + + void setIoHandle(audio_io_handle_t ioHandle); + + virtual audio_devices_t device() const; + virtual bool sharesHwModuleWith(const sp<AudioOutputDescriptor> outputDesc); + virtual audio_devices_t supportedDevices(); + virtual uint32_t latency(); + virtual bool isDuplicated() const { return (mOutput1 != NULL && mOutput2 != NULL); } + virtual bool isFixedVolume(audio_devices_t device); + virtual sp<AudioOutputDescriptor> subOutput1() { return mOutput1; } + virtual sp<AudioOutputDescriptor> subOutput2() { return mOutput2; } + virtual void changeRefCount(audio_stream_type_t stream, int delta); + virtual bool setVolume(float volume, + audio_stream_type_t stream, + audio_devices_t device, + uint32_t delayMs, + bool force); + + virtual void toAudioPortConfig(struct audio_port_config *dstConfig, + const struct audio_port_config *srcConfig = NULL) const; + virtual void toAudioPort(struct audio_port *port) const; + + const sp<IOProfile> mProfile; // I/O profile this output derives from + audio_io_handle_t mIoHandle; // output handle + uint32_t mLatency; // + audio_output_flags_t mFlags; // + AudioMix *mPolicyMix; // non NULL when used by a dynamic policy + sp<SwAudioOutputDescriptor> mOutput1; // used by duplicated outputs: first output + sp<SwAudioOutputDescriptor> mOutput2; // used by duplicated outputs: second output + uint32_t mDirectOpenCount; // number of clients using this output (direct outputs only) +}; + +class SwAudioOutputCollection : + public DefaultKeyedVector< audio_io_handle_t, sp<SwAudioOutputDescriptor> > { public: bool isStreamActive(audio_stream_type_t stream, uint32_t inPastMs = 0) const; @@ -99,9 +145,9 @@ public: */ audio_io_handle_t getA2dpOutput() const; - sp<AudioOutputDescriptor> getOutputFromId(audio_port_handle_t id) const; + sp<SwAudioOutputDescriptor> getOutputFromId(audio_port_handle_t id) const; - sp<AudioOutputDescriptor> getPrimaryOutput() const; + sp<SwAudioOutputDescriptor> getPrimaryOutput() const; /** * return true if any output is playing anything besides the stream to ignore diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h index 988aed6..67285f3 100644 --- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h +++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h @@ -24,7 +24,7 @@ namespace android { -class AudioOutputDescriptor; +class SwAudioOutputDescriptor; /** * custom mix entry in mPolicyMixes @@ -33,9 +33,9 @@ class AudioPolicyMix : public RefBase { public: AudioPolicyMix() {} - const sp<AudioOutputDescriptor> &getOutput() const; + const sp<SwAudioOutputDescriptor> &getOutput() const; - void setOutput(sp<AudioOutputDescriptor> &output); + void setOutput(sp<SwAudioOutputDescriptor> &output); void clearOutput(); @@ -45,7 +45,7 @@ public: private: AudioMix mMix; // Audio policy mix descriptor - sp<AudioOutputDescriptor> mOutput; // Corresponding output stream + sp<SwAudioOutputDescriptor> mOutput; // Corresponding output stream }; @@ -58,18 +58,18 @@ public: status_t unregisterMix(String8 address); - void closeOutput(sp<AudioOutputDescriptor> &desc); + void closeOutput(sp<SwAudioOutputDescriptor> &desc); /** * Try to find an output descriptor for the given attributes. * - * @param[in] attributes to consider for the research of output descriptor. + * @param[in] attributes to consider fowr the research of output descriptor. * @param[out] desc to return if an output could be found. * * @return NO_ERROR if an output was found for the given attribute (in this case, the * descriptor output param is initialized), error code otherwise. */ - status_t getOutputForAttr(audio_attributes_t attributes, sp<AudioOutputDescriptor> &desc); + status_t getOutputForAttr(audio_attributes_t attributes, sp<SwAudioOutputDescriptor> &desc); audio_devices_t getDeviceAndMixForInputSource(audio_source_t inputSource, audio_devices_t availableDeviceTypes, 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]; diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp index 84a53eb..c43bb6a 100644 --- a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp +++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp @@ -26,12 +26,12 @@ namespace android { -void AudioPolicyMix::setOutput(sp<AudioOutputDescriptor> &output) +void AudioPolicyMix::setOutput(sp<SwAudioOutputDescriptor> &output) { mOutput = output; } -const sp<AudioOutputDescriptor> &AudioPolicyMix::getOutput() const +const sp<SwAudioOutputDescriptor> &AudioPolicyMix::getOutput() const { return mOutput; } @@ -88,7 +88,7 @@ status_t AudioPolicyMixCollection::getAudioPolicyMix(String8 address, return NO_ERROR; } -void AudioPolicyMixCollection::closeOutput(sp<AudioOutputDescriptor> &desc) +void AudioPolicyMixCollection::closeOutput(sp<SwAudioOutputDescriptor> &desc) { for (size_t i = 0; i < size(); i++) { sp<AudioPolicyMix> policyMix = valueAt(i); @@ -99,7 +99,7 @@ void AudioPolicyMixCollection::closeOutput(sp<AudioOutputDescriptor> &desc) } status_t AudioPolicyMixCollection::getOutputForAttr(audio_attributes_t attributes, - sp<AudioOutputDescriptor> &desc) + sp<SwAudioOutputDescriptor> &desc) { for (size_t i = 0; i < size(); i++) { sp<AudioPolicyMix> policyMix = valueAt(i); diff --git a/services/audiopolicy/engine/interface/AudioPolicyManagerObserver.h b/services/audiopolicy/engine/interface/AudioPolicyManagerObserver.h index 4f5427e..6d43df2 100755 --- a/services/audiopolicy/engine/interface/AudioPolicyManagerObserver.h +++ b/services/audiopolicy/engine/interface/AudioPolicyManagerObserver.h @@ -43,7 +43,7 @@ public: virtual const AudioPolicyMixCollection &getAudioPolicyMixCollection() const = 0; - virtual const AudioOutputCollection &getOutputs() const = 0; + virtual const SwAudioOutputCollection &getOutputs() const = 0; virtual const AudioInputCollection &getInputs() const = 0; diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp index 417eebc..26a0d09 100755 --- a/services/audiopolicy/enginedefault/src/Engine.cpp +++ b/services/audiopolicy/enginedefault/src/Engine.cpp @@ -243,7 +243,7 @@ routing_strategy Engine::getStrategyForStream(audio_stream_type_t stream) routing_strategy Engine::getStrategyForUsage(audio_usage_t usage) { - const AudioOutputCollection &outputs = mApmObserver->getOutputs(); + const SwAudioOutputCollection &outputs = mApmObserver->getOutputs(); // usage to strategy mapping switch (usage) { @@ -291,7 +291,7 @@ audio_devices_t Engine::getDeviceForStrategy(routing_strategy strategy) const const DeviceVector &availableOutputDevices = mApmObserver->getAvailableOutputDevices(); const DeviceVector &availableInputDevices = mApmObserver->getAvailableInputDevices(); - const AudioOutputCollection &outputs = mApmObserver->getOutputs(); + const SwAudioOutputCollection &outputs = mApmObserver->getOutputs(); uint32_t device = AUDIO_DEVICE_NONE; uint32_t availableOutputDevicesType = availableOutputDevices.types(); @@ -582,7 +582,7 @@ audio_devices_t Engine::getDeviceForInputSource(audio_source_t inputSource) cons { const DeviceVector &availableOutputDevices = mApmObserver->getAvailableOutputDevices(); const DeviceVector &availableInputDevices = mApmObserver->getAvailableInputDevices(); - const AudioOutputCollection &outputs = mApmObserver->getOutputs(); + const SwAudioOutputCollection &outputs = mApmObserver->getOutputs(); audio_devices_t availableDeviceTypes = availableInputDevices.types() & ~AUDIO_DEVICE_BIT_IN; uint32_t device = AUDIO_DEVICE_NONE; diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp index ffa689a..b5ff9a9 100644 --- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp +++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp @@ -157,7 +157,7 @@ status_t AudioPolicyManager::setDeviceConnectionStateInt(audio_devices_t device, // outputs must be closed after checkOutputForAllStrategies() is executed if (!outputs.isEmpty()) { for (size_t i = 0; i < outputs.size(); i++) { - sp<AudioOutputDescriptor> desc = mOutputs.valueFor(outputs[i]); + sp<SwAudioOutputDescriptor> desc = mOutputs.valueFor(outputs[i]); // close unused outputs after device disconnection or direct outputs that have been // opened by checkOutputsForDevice() to query dynamic parameters if ((state == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE) || @@ -176,18 +176,17 @@ status_t AudioPolicyManager::setDeviceConnectionStateInt(audio_devices_t device, updateCallRouting(newDevice); } for (size_t i = 0; i < mOutputs.size(); i++) { - audio_io_handle_t output = mOutputs.keyAt(i); - if ((mEngine->getPhoneState() != AUDIO_MODE_IN_CALL) || (output != mPrimaryOutput)) { - audio_devices_t newDevice = getNewOutputDevice(mOutputs.keyAt(i), - true /*fromCache*/); + sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i); + if ((mEngine->getPhoneState() != AUDIO_MODE_IN_CALL) || (desc != mPrimaryOutput)) { + audio_devices_t newDevice = getNewOutputDevice(desc, true /*fromCache*/); // do not force device change on duplicated output because if device is 0, it will // also force a device 0 for the two outputs it is duplicated to which may override // a valid device selection on those outputs. - bool force = !mOutputs.valueAt(i)->isDuplicated() + bool force = !desc->isDuplicated() && (!device_distinguishes_on_address(device) // always force when disconnecting (a non-duplicated device) || (state == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE)); - setOutputDevice(output, newDevice, force, 0); + setOutputDevice(desc, newDevice, force, 0); } } @@ -349,7 +348,7 @@ void AudioPolicyManager::updateCallRouting(audio_devices_t rxDevice, int delayMs AUDIO_OUTPUT_FLAG_NONE, AUDIO_FORMAT_INVALID); if (output != AUDIO_IO_HANDLE_NONE) { - sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output); + sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueFor(output); ALOG_ASSERT(!outputDesc->isDuplicated(), "updateCallRouting() RX device output is duplicated"); outputDesc->toAudioPortConfig(&patch.sources[1]); @@ -450,13 +449,13 @@ void AudioPolicyManager::setPhoneState(audio_mode_t state) checkOutputForAllStrategies(); updateDevicesAndOutputs(); - sp<AudioOutputDescriptor> hwOutputDesc = mOutputs.valueFor(mPrimaryOutput); + sp<SwAudioOutputDescriptor> hwOutputDesc = mPrimaryOutput; int delayMs = 0; if (isStateInCall(state)) { nsecs_t sysTime = systemTime(); for (size_t i = 0; i < mOutputs.size(); i++) { - sp<AudioOutputDescriptor> desc = mOutputs.valueAt(i); + sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i); // mute media and sonification strategies and delay device switch by the largest // latency of any output where either strategy is active. // This avoid sending the ring tone or music tail into the earpiece or headset. @@ -466,14 +465,14 @@ void AudioPolicyManager::setPhoneState(audio_mode_t state) isStrategyActive(desc, STRATEGY_SONIFICATION, SONIFICATION_HEADSET_MUSIC_DELAY, sysTime)) && - (delayMs < (int)desc->mLatency*2)) { - delayMs = desc->mLatency*2; + (delayMs < (int)desc->latency()*2)) { + delayMs = desc->latency()*2; } - setStrategyMute(STRATEGY_MEDIA, true, mOutputs.keyAt(i)); - setStrategyMute(STRATEGY_MEDIA, false, mOutputs.keyAt(i), MUTE_TIME_MS, + setStrategyMute(STRATEGY_MEDIA, true, desc); + setStrategyMute(STRATEGY_MEDIA, false, desc, MUTE_TIME_MS, getDeviceForStrategy(STRATEGY_MEDIA, true /*fromCache*/)); - setStrategyMute(STRATEGY_SONIFICATION, true, mOutputs.keyAt(i)); - setStrategyMute(STRATEGY_SONIFICATION, false, mOutputs.keyAt(i), MUTE_TIME_MS, + setStrategyMute(STRATEGY_SONIFICATION, true, desc); + setStrategyMute(STRATEGY_SONIFICATION, false, desc, MUTE_TIME_MS, getDeviceForStrategy(STRATEGY_SONIFICATION, true /*fromCache*/)); } } @@ -549,13 +548,13 @@ void AudioPolicyManager::setForceUse(audio_policy_force_use_t usage, updateCallRouting(newDevice); } for (size_t i = 0; i < mOutputs.size(); i++) { - audio_io_handle_t output = mOutputs.keyAt(i); - audio_devices_t newDevice = getNewOutputDevice(output, true /*fromCache*/); - if ((mEngine->getPhoneState() != AUDIO_MODE_IN_CALL) || (output != mPrimaryOutput)) { - setOutputDevice(output, newDevice, (newDevice != AUDIO_DEVICE_NONE)); + sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueAt(i); + audio_devices_t newDevice = getNewOutputDevice(outputDesc, true /*fromCache*/); + if ((mEngine->getPhoneState() != AUDIO_MODE_IN_CALL) || (outputDesc != mPrimaryOutput)) { + setOutputDevice(outputDesc, newDevice, (newDevice != AUDIO_DEVICE_NONE)); } if (forceVolumeReeval && (newDevice != AUDIO_DEVICE_NONE)) { - applyStreamVolumes(output, newDevice, 0, true); + applyStreamVolumes(outputDesc, newDevice, 0, true); } } @@ -642,7 +641,7 @@ status_t AudioPolicyManager::getOutputForAttr(const audio_attributes_t *attr, } stream_type_to_audio_attributes(*stream, &attributes); } - sp<AudioOutputDescriptor> desc; + sp<SwAudioOutputDescriptor> desc; if (mPolicyMixes.getOutputForAttr(attributes, desc) == NO_ERROR) { ALOG_ASSERT(desc != 0, "Invalid desc returned by getOutputForAttr"); if (!audio_is_linear_pcm(format)) { @@ -713,7 +712,8 @@ audio_io_handle_t AudioPolicyManager::getOutputForDevice( if (mTestOutputs[mCurOutput] == 0) { ALOGV("getOutput() opening test output"); - sp<AudioOutputDescriptor> outputDesc = new AudioOutputDescriptor(NULL); + sp<AudioOutputDescriptor> outputDesc = new SwAudioOutputDescriptor(NULL, + mpClientInterface); outputDesc->mDevice = mTestDevice; outputDesc->mLatency = mTestLatencyMs; outputDesc->mFlags = @@ -789,10 +789,10 @@ audio_io_handle_t AudioPolicyManager::getOutputForDevice( } if (profile != 0) { - sp<AudioOutputDescriptor> outputDesc = NULL; + sp<SwAudioOutputDescriptor> outputDesc = NULL; for (size_t i = 0; i < mOutputs.size(); i++) { - sp<AudioOutputDescriptor> desc = mOutputs.valueAt(i); + sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i); if (!desc->isDuplicated() && (profile == desc->mProfile)) { outputDesc = desc; // reuse direct output if currently open and configured with same parameters @@ -809,7 +809,7 @@ audio_io_handle_t AudioPolicyManager::getOutputForDevice( if (outputDesc != NULL) { closeOutput(outputDesc->mIoHandle); } - outputDesc = new AudioOutputDescriptor(profile); + outputDesc = new SwAudioOutputDescriptor(profile, mpClientInterface); outputDesc->mDevice = device; outputDesc->mLatency = 0; outputDesc->mFlags =(audio_output_flags_t) (outputDesc->mFlags | flags); @@ -915,7 +915,7 @@ audio_io_handle_t AudioPolicyManager::selectOutput(const SortedVector<audio_io_h audio_io_handle_t outputPrimary = 0; for (size_t i = 0; i < outputs.size(); i++) { - sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(outputs[i]); + sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueFor(outputs[i]); if (!outputDesc->isDuplicated()) { // if a valid format is specified, skip output if not compatible if (format != AUDIO_FORMAT_INVALID) { @@ -962,8 +962,51 @@ status_t AudioPolicyManager::startOutput(audio_io_handle_t output, return BAD_VALUE; } + sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueAt(index); + + audio_devices_t newDevice; + if (outputDesc->mPolicyMix != NULL) { + newDevice = AUDIO_DEVICE_OUT_REMOTE_SUBMIX; + } else { + newDevice = AUDIO_DEVICE_NONE; + } + + uint32_t delayMs = 0; + + // Routing? + mOutputRoutes.incRouteActivity(session); + + status_t status = startSource(outputDesc, stream, newDevice, &delayMs); + + if (status != NO_ERROR) { + mOutputRoutes.decRouteActivity(session); + } + // Automatically enable the remote submix input when output is started on a re routing mix + // of type MIX_TYPE_RECORDERS + if (audio_is_remote_submix_device(newDevice) && outputDesc->mPolicyMix != NULL && + outputDesc->mPolicyMix->mMixType == MIX_TYPE_RECORDERS) { + setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX, + AUDIO_POLICY_DEVICE_STATE_AVAILABLE, + outputDesc->mPolicyMix->mRegistrationId, + "remote-submix"); + } + + if (delayMs != 0) { + usleep(delayMs * 1000); + } + + return status; +} + +status_t AudioPolicyManager::startSource(sp<AudioOutputDescriptor> outputDesc, + audio_stream_type_t stream, + audio_devices_t device, + uint32_t *delayMs) +{ // cannot start playback of STREAM_TTS if any other output is being used uint32_t beaconMuteLatency = 0; + + *delayMs = 0; if (stream == AUDIO_STREAM_TTS) { ALOGV("\t found BEACON stream"); if (mOutputs.isAnyOutputActive(AUDIO_STREAM_TTS /*streamToIgnore*/)) { @@ -976,22 +1019,15 @@ status_t AudioPolicyManager::startOutput(audio_io_handle_t output, beaconMuteLatency = handleEventForBeacon(STARTING_OUTPUT); } - sp<AudioOutputDescriptor> outputDesc = mOutputs.valueAt(index); // increment usage count for this stream on the requested output: // NOTE that the usage count is the same for duplicated output and hardware output which is // necessary for a correct control of hardware output routing by startOutput() and stopOutput() outputDesc->changeRefCount(stream, 1); - // Routing? - mOutputRoutes.incRouteActivity(session); - if (outputDesc->mRefCount[stream] == 1) { // starting an output being rerouted? - audio_devices_t newDevice; - if (outputDesc->mPolicyMix != NULL) { - newDevice = AUDIO_DEVICE_OUT_REMOTE_SUBMIX; - } else { - newDevice = getNewOutputDevice(output, false /*fromCache*/); + if (device == AUDIO_DEVICE_NONE) { + device = getNewOutputDevice(outputDesc, false /*fromCache*/); } routing_strategy strategy = getStrategy(stream); bool shouldWait = (strategy == STRATEGY_SONIFICATION) || @@ -1007,7 +1043,7 @@ status_t AudioPolicyManager::startOutput(audio_io_handle_t output, // In this case, the audio HAL must receive the new device selection so that it can // change the device currently selected by the other active output. if (outputDesc->sharesHwModuleWith(desc) && - desc->device() != newDevice) { + desc->device() != device) { force = true; } // wait for audio on other active outputs to be presented when starting @@ -1019,7 +1055,7 @@ status_t AudioPolicyManager::startOutput(audio_io_handle_t output, } } } - uint32_t muteWaitMs = setOutputDevice(output, newDevice, force); + uint32_t muteWaitMs = setOutputDevice(outputDesc, device, force); // handle special case for sonification while in call if (isInCall()) { @@ -1028,32 +1064,18 @@ status_t AudioPolicyManager::startOutput(audio_io_handle_t output, // apply volume rules for current stream and device if necessary checkAndSetVolume(stream, - mStreams[stream].getVolumeIndex(newDevice), - output, - newDevice); + mStreams.valueFor(stream).getVolumeIndex(device), + outputDesc, + device); // update the outputs if starting an output with a stream that can affect notification // routing handleNotificationRoutingForStream(stream); - // Automatically enable the remote submix input when output is started on a re routing mix - // of type MIX_TYPE_RECORDERS - if (audio_is_remote_submix_device(newDevice) && outputDesc->mPolicyMix != NULL && - outputDesc->mPolicyMix->mMixType == MIX_TYPE_RECORDERS) { - setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX, - AUDIO_POLICY_DEVICE_STATE_AVAILABLE, - outputDesc->mPolicyMix->mRegistrationId, - "remote-submix"); - } - // force reevaluating accessibility routing when ringtone or alarm starts if (strategy == STRATEGY_SONIFICATION) { mpClientInterface->invalidateStream(AUDIO_STREAM_ACCESSIBILITY); } - - if (waitMs > muteWaitMs) { - usleep((waitMs - muteWaitMs) * 2 * 1000); - } } return NO_ERROR; } @@ -1070,8 +1092,32 @@ status_t AudioPolicyManager::stopOutput(audio_io_handle_t output, return BAD_VALUE; } - sp<AudioOutputDescriptor> outputDesc = mOutputs.valueAt(index); + sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueAt(index); + + if (outputDesc->mRefCount[stream] == 1) { + // Automatically disable the remote submix input when output is stopped on a + // re routing mix of type MIX_TYPE_RECORDERS + if (audio_is_remote_submix_device(outputDesc->mDevice) && + outputDesc->mPolicyMix != NULL && + outputDesc->mPolicyMix->mMixType == MIX_TYPE_RECORDERS) { + setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX, + AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE, + outputDesc->mPolicyMix->mRegistrationId, + "remote-submix"); + } + } + + // Routing? + if (outputDesc->mRefCount[stream] > 0) { + mOutputRoutes.decRouteActivity(session); + } + return stopSource(outputDesc, stream); +} + +status_t AudioPolicyManager::stopSource(sp<AudioOutputDescriptor> outputDesc, + audio_stream_type_t stream) +{ // always handle stream stop, check which stream type is stopping handleEventForBeacon(stream == AUDIO_STREAM_TTS ? STOPPING_BEACON : STOPPING_OUTPUT); @@ -1084,44 +1130,30 @@ status_t AudioPolicyManager::stopOutput(audio_io_handle_t output, // decrement usage count of this stream on the output outputDesc->changeRefCount(stream, -1); - // Routing? - mOutputRoutes.decRouteActivity(session); - // store time at which the stream was stopped - see isStreamActive() if (outputDesc->mRefCount[stream] == 0) { - // Automatically disable the remote submix input when output is stopped on a - // re routing mix of type MIX_TYPE_RECORDERS - if (audio_is_remote_submix_device(outputDesc->mDevice) && - outputDesc->mPolicyMix != NULL && - outputDesc->mPolicyMix->mMixType == MIX_TYPE_RECORDERS) { - setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX, - AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE, - outputDesc->mPolicyMix->mRegistrationId, - "remote-submix"); - } - outputDesc->mStopTime[stream] = systemTime(); - audio_devices_t newDevice = getNewOutputDevice(output, false /*fromCache*/); + audio_devices_t newDevice = getNewOutputDevice(outputDesc, false /*fromCache*/); // delay the device switch by twice the latency because stopOutput() is executed when // the track stop() command is received and at that time the audio track buffer can // still contain data that needs to be drained. The latency only covers the audio HAL // and kernel buffers. Also the latency does not always include additional delay in the // audio path (audio DSP, CODEC ...) - setOutputDevice(output, newDevice, false, outputDesc->mLatency*2); + setOutputDevice(outputDesc, newDevice, false, outputDesc->latency()*2); // force restoring the device selection on other active outputs if it differs from the // one being selected for this output for (size_t i = 0; i < mOutputs.size(); i++) { audio_io_handle_t curOutput = mOutputs.keyAt(i); sp<AudioOutputDescriptor> desc = mOutputs.valueAt(i); - if (curOutput != output && + if (desc != outputDesc && desc->isActive() && outputDesc->sharesHwModuleWith(desc) && (newDevice != desc->device())) { - setOutputDevice(curOutput, - getNewOutputDevice(curOutput, false /*fromCache*/), + setOutputDevice(desc, + getNewOutputDevice(desc, false /*fromCache*/), true, - outputDesc->mLatency*2); + outputDesc->latency()*2); } } // update the outputs if stopping one with a stream that can affect notification routing @@ -1129,7 +1161,7 @@ status_t AudioPolicyManager::stopOutput(audio_io_handle_t output, } return NO_ERROR; } else { - ALOGW("stopOutput() refcount is already 0 for output %d", output); + ALOGW("stopOutput() refcount is already 0"); return INVALID_OPERATION; } } @@ -1161,7 +1193,7 @@ void AudioPolicyManager::releaseOutput(audio_io_handle_t output, // Routing mOutputRoutes.removeRoute(session); - sp<AudioOutputDescriptor> desc = mOutputs.valueAt(index); + sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(index); if (desc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) { if (desc->mDirectOpenCount <= 0) { ALOGW("releaseOutput() invalid open count %d for output %d", @@ -1173,8 +1205,9 @@ void AudioPolicyManager::releaseOutput(audio_io_handle_t output, // If effects where present on the output, audioflinger moved them to the primary // output by default: move them back to the appropriate output. audio_io_handle_t dstOutput = getOutputForEffect(); - if (dstOutput != mPrimaryOutput) { - mpClientInterface->moveEffects(AUDIO_SESSION_OUTPUT_MIX, mPrimaryOutput, dstOutput); + if (dstOutput != mPrimaryOutput->mIoHandle) { + mpClientInterface->moveEffects(AUDIO_SESSION_OUTPUT_MIX, + mPrimaryOutput->mIoHandle, dstOutput); } mpClientInterface->onAudioPortListUpdate(); } @@ -1528,8 +1561,8 @@ status_t AudioPolicyManager::setStreamVolumeIndex(audio_stream_type_t stream, audio_devices_t device) { - if ((index < mStreams[stream].getVolumeIndexMin()) || - (index > mStreams[stream].getVolumeIndexMax())) { + if ((index < mStreams.valueFor(stream).getVolumeIndexMin()) || + (index > mStreams.valueFor(stream).getVolumeIndexMax())) { return BAD_VALUE; } if (!audio_is_output_device(device)) { @@ -1537,7 +1570,7 @@ status_t AudioPolicyManager::setStreamVolumeIndex(audio_stream_type_t stream, } // Force max volume if stream cannot be muted - if (!mStreams.canBeMuted(stream)) index = mStreams[stream].getVolumeIndexMax(); + if (!mStreams.canBeMuted(stream)) index = mStreams.valueFor(stream).getVolumeIndexMax(); ALOGV("setStreamVolumeIndex() stream %d, device %04x, index %d", stream, device, index); @@ -1566,16 +1599,17 @@ status_t AudioPolicyManager::setStreamVolumeIndex(audio_stream_type_t stream, } status_t status = NO_ERROR; for (size_t i = 0; i < mOutputs.size(); i++) { - audio_devices_t curDevice = Volume::getDeviceForVolume(mOutputs.valueAt(i)->device()); + sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i); + audio_devices_t curDevice = Volume::getDeviceForVolume(desc->device()); if ((device == AUDIO_DEVICE_OUT_DEFAULT) || ((curDevice & strategyDevice) != 0)) { - status_t volStatus = checkAndSetVolume(stream, index, mOutputs.keyAt(i), curDevice); + status_t volStatus = checkAndSetVolume(stream, index, desc, curDevice); if (volStatus != NO_ERROR) { status = volStatus; } } if ((device == AUDIO_DEVICE_OUT_DEFAULT) || ((curDevice & accessibilityDevice) != 0)) { status_t volStatus = checkAndSetVolume(AUDIO_STREAM_ACCESSIBILITY, - index, mOutputs.keyAt(i), curDevice); + index, desc, curDevice); } } return status; @@ -1598,7 +1632,7 @@ status_t AudioPolicyManager::getStreamVolumeIndex(audio_stream_type_t stream, } device = Volume::getDeviceForVolume(device); - *index = mStreams[stream].getVolumeIndex(device); + *index = mStreams.valueFor(stream).getVolumeIndex(device); ALOGV("getStreamVolumeIndex() stream %d device %08x index %d", stream, device, *index); return NO_ERROR; } @@ -1622,7 +1656,7 @@ audio_io_handle_t AudioPolicyManager::selectOutputForEffects( audio_io_handle_t outputDeepBuffer = 0; for (size_t i = 0; i < outputs.size(); i++) { - sp<AudioOutputDescriptor> desc = mOutputs.valueFor(outputs[i]); + sp<SwAudioOutputDescriptor> desc = mOutputs.valueFor(outputs[i]); ALOGV("selectOutputForEffects outputs[%zu] flags %x", i, desc->mFlags); if ((desc->mFlags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) { outputOffloaded = outputs[i]; @@ -1676,6 +1710,16 @@ status_t AudioPolicyManager::registerEffect(const effect_descriptor_t *desc, return mEffects.registerEffect(desc, io, strategy, session, id); } +bool AudioPolicyManager::isStreamActive(audio_stream_type_t stream, uint32_t inPastMs) const +{ + return mOutputs.isStreamActive(stream, inPastMs); +} + +bool AudioPolicyManager::isStreamActiveRemotely(audio_stream_type_t stream, uint32_t inPastMs) const +{ + return mOutputs.isStreamActiveRemotely(stream, inPastMs); +} + bool AudioPolicyManager::isSourceActive(audio_source_t source) const { for (size_t i = 0; i < mInputs.size(); i++) { @@ -1826,7 +1870,7 @@ status_t AudioPolicyManager::dump(int fd) snprintf(buffer, SIZE, "\nAudioPolicyManager Dump: %p\n", this); result.append(buffer); - snprintf(buffer, SIZE, " Primary Output: %d\n", mPrimaryOutput); + snprintf(buffer, SIZE, " Primary Output: %d\n", mPrimaryOutput->mIoHandle); result.append(buffer); snprintf(buffer, SIZE, " Phone state: %d\n", mEngine->getPhoneState()); result.append(buffer); @@ -2044,7 +2088,7 @@ status_t AudioPolicyManager::createAudioPatch(const struct audio_patch *patch, } if (patch->sources[0].type == AUDIO_PORT_TYPE_MIX) { - sp<AudioOutputDescriptor> outputDesc = mOutputs.getOutputFromId(patch->sources[0].id); + sp<SwAudioOutputDescriptor> outputDesc = mOutputs.getOutputFromId(patch->sources[0].id); if (outputDesc == NULL) { ALOGV("createAudioPatch() output not found for id %d", patch->sources[0].id); return BAD_VALUE; @@ -2092,7 +2136,7 @@ status_t AudioPolicyManager::createAudioPatch(const struct audio_patch *patch, // TODO: reconfigure output format and channels here ALOGV("createAudioPatch() setting device %08x on output %d", devices.types(), outputDesc->mIoHandle); - setOutputDevice(outputDesc->mIoHandle, devices.types(), true, 0, handle); + setOutputDevice(outputDesc, devices.types(), true, 0, handle); index = mAudioPatches.indexOfKey(*handle); if (index >= 0) { if (patchDesc != 0 && patchDesc != mAudioPatches.valueAt(index)) { @@ -2270,14 +2314,14 @@ status_t AudioPolicyManager::releaseAudioPatch(audio_patch_handle_t handle, struct audio_patch *patch = &patchDesc->mPatch; patchDesc->mUid = mUidCached; if (patch->sources[0].type == AUDIO_PORT_TYPE_MIX) { - sp<AudioOutputDescriptor> outputDesc = mOutputs.getOutputFromId(patch->sources[0].id); + sp<SwAudioOutputDescriptor> outputDesc = mOutputs.getOutputFromId(patch->sources[0].id); if (outputDesc == NULL) { ALOGV("releaseAudioPatch() output not found for id %d", patch->sources[0].id); return BAD_VALUE; } - setOutputDevice(outputDesc->mIoHandle, - getNewOutputDevice(outputDesc->mIoHandle, true /*fromCache*/), + setOutputDevice(outputDesc, + getNewOutputDevice(outputDesc, true /*fromCache*/), true, 0, NULL); @@ -2336,7 +2380,7 @@ status_t AudioPolicyManager::setAudioPortConfig(const struct audio_port_config * sp<AudioPortConfig> audioPortConfig; if (config->type == AUDIO_PORT_TYPE_MIX) { if (config->role == AUDIO_PORT_ROLE_SOURCE) { - sp<AudioOutputDescriptor> outputDesc = mOutputs.getOutputFromId(config->id); + sp<SwAudioOutputDescriptor> outputDesc = mOutputs.getOutputFromId(config->id); if (outputDesc == NULL) { return BAD_VALUE; } @@ -2418,7 +2462,6 @@ AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterfa #ifdef AUDIO_POLICY_TEST Thread(false), #endif //AUDIO_POLICY_TEST - mPrimaryOutput((audio_io_handle_t)0), mLimitRingtoneVolume(false), mLastVoiceVolume(-1.0f), mA2dpSuspended(false), mSpeakerDrcEnabled(false), @@ -2502,7 +2545,8 @@ AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterfa if ((profileType & outputDeviceTypes) == 0) { continue; } - sp<AudioOutputDescriptor> outputDesc = new AudioOutputDescriptor(outProfile); + sp<SwAudioOutputDescriptor> outputDesc = new SwAudioOutputDescriptor(outProfile, + mpClientInterface); outputDesc->mDevice = profileType; audio_config_t config = AUDIO_CONFIG_INITIALIZER; @@ -2538,10 +2582,10 @@ AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterfa } if (mPrimaryOutput == 0 && outProfile->mFlags & AUDIO_OUTPUT_FLAG_PRIMARY) { - mPrimaryOutput = output; + mPrimaryOutput = outputDesc; } addOutput(output, outputDesc); - setOutputDevice(output, + setOutputDevice(outputDesc, outputDesc->mDevice, true); } @@ -2648,7 +2692,7 @@ AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterfa if (mPrimaryOutput != 0) { AudioParameter outputCmd = AudioParameter(); outputCmd.addInt(String8("set_id"), 0); - mpClientInterface->setParameters(mPrimaryOutput, outputCmd.toString()); + mpClientInterface->setParameters(mPrimaryOutput->mIoHandle, outputCmd.toString()); mTestDevice = AUDIO_DEVICE_OUT_SPEAKER; mTestSamplingRate = 44100; @@ -2788,20 +2832,21 @@ bool AudioPolicyManager::threadLoop() if (param.get(String8("test_cmd_policy_reopen"), value) == NO_ERROR) { param.remove(String8("test_cmd_policy_reopen")); - sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(mPrimaryOutput); - mpClientInterface->closeOutput(mPrimaryOutput); + mpClientInterface->closeOutput(mpClientInterface->closeOutput(mPrimaryOutput);); - audio_module_handle_t moduleHandle = outputDesc->getModuleHandle(); + audio_module_handle_t moduleHandle = mPrimaryOutput->getModuleHandle(); - removeOutput(mPrimaryOutput); - sp<AudioOutputDescriptor> outputDesc = new AudioOutputDescriptor(NULL); + removeOutput(mPrimaryOutput->mIoHandle); + sp<SwAudioOutputDescriptor> outputDesc = new AudioOutputDescriptor(NULL, + mpClientInterface); outputDesc->mDevice = AUDIO_DEVICE_OUT_SPEAKER; audio_config_t config = AUDIO_CONFIG_INITIALIZER; config.sample_rate = outputDesc->mSamplingRate; config.channel_mask = outputDesc->mChannelMask; config.format = outputDesc->mFormat; + audio_io_handle_t handle; status_t status = mpClientInterface->openOutput(moduleHandle, - &mPrimaryOutput, + &handle, &config, &outputDesc->mDevice, String8(""), @@ -2815,10 +2860,11 @@ bool AudioPolicyManager::threadLoop() outputDesc->mSamplingRate = config.sample_rate; outputDesc->mChannelMask = config.channel_mask; outputDesc->mFormat = config.format; + mPrimaryOutput = outputDesc; AudioParameter outputCmd = AudioParameter(); outputCmd.addInt(String8("set_id"), 0); - mpClientInterface->setParameters(mPrimaryOutput, outputCmd.toString()); - addOutput(mPrimaryOutput, outputDesc); + mpClientInterface->setParameters(handle, outputCmd.toString()); + addOutput(handle, outputDesc); } } @@ -2850,7 +2896,7 @@ int AudioPolicyManager::testOutputIndex(audio_io_handle_t output) // --- -void AudioPolicyManager::addOutput(audio_io_handle_t output, sp<AudioOutputDescriptor> outputDesc) +void AudioPolicyManager::addOutput(audio_io_handle_t output, sp<SwAudioOutputDescriptor> outputDesc) { outputDesc->setIoHandle(output); mOutputs.add(output, outputDesc); @@ -2869,7 +2915,7 @@ void AudioPolicyManager::addInput(audio_io_handle_t input, sp<AudioInputDescript nextAudioPortGeneration(); } -void AudioPolicyManager::findIoHandlesByAddress(sp<AudioOutputDescriptor> desc /*in*/, +void AudioPolicyManager::findIoHandlesByAddress(sp<SwAudioOutputDescriptor> desc /*in*/, const audio_devices_t device /*in*/, const String8 address /*in*/, SortedVector<audio_io_handle_t>& outputs /*out*/) { @@ -2888,7 +2934,7 @@ status_t AudioPolicyManager::checkOutputsForDevice(const sp<DeviceDescriptor> de const String8 address) { audio_devices_t device = devDesc->type(); - sp<AudioOutputDescriptor> desc; + sp<SwAudioOutputDescriptor> desc; // erase all current sample rates, formats and channel masks devDesc->clearCapabilities(); @@ -2896,7 +2942,7 @@ status_t AudioPolicyManager::checkOutputsForDevice(const sp<DeviceDescriptor> de // first list already open outputs that can be routed to this device for (size_t i = 0; i < mOutputs.size(); i++) { desc = mOutputs.valueAt(i); - if (!desc->isDuplicated() && (desc->mProfile->mSupportedDevices.types() & device)) { + if (!desc->isDuplicated() && (desc->supportedDevices() & device)) { if (!device_distinguishes_on_address(device)) { ALOGV("checkOutputsForDevice(): adding opened output %d", mOutputs.keyAt(i)); outputs.add(mOutputs.keyAt(i)); @@ -2955,7 +3001,7 @@ status_t AudioPolicyManager::checkOutputsForDevice(const sp<DeviceDescriptor> de ALOGV("opening output for device %08x with params %s profile %p", device, address.string(), profile.get()); - desc = new AudioOutputDescriptor(profile); + desc = new SwAudioOutputDescriptor(profile, mpClientInterface); desc->mDevice = device; audio_config_t config = AUDIO_CONFIG_INITIALIZER; config.sample_rate = desc->mSamplingRate; @@ -3068,28 +3114,29 @@ status_t AudioPolicyManager::checkOutputsForDevice(const sp<DeviceDescriptor> de audio_io_handle_t duplicatedOutput = AUDIO_IO_HANDLE_NONE; // set initial stream volume for device - applyStreamVolumes(output, device, 0, true); + applyStreamVolumes(desc, device, 0, true); //TODO: configure audio effect output stage here // open a duplicating output thread for the new output and the primary output - duplicatedOutput = mpClientInterface->openDuplicateOutput(output, - mPrimaryOutput); + duplicatedOutput = + mpClientInterface->openDuplicateOutput(output, + mPrimaryOutput->mIoHandle); if (duplicatedOutput != AUDIO_IO_HANDLE_NONE) { // add duplicated output descriptor - sp<AudioOutputDescriptor> dupOutputDesc = - new AudioOutputDescriptor(NULL); - dupOutputDesc->mOutput1 = mOutputs.valueFor(mPrimaryOutput); - dupOutputDesc->mOutput2 = mOutputs.valueFor(output); + sp<SwAudioOutputDescriptor> dupOutputDesc = + new SwAudioOutputDescriptor(NULL, mpClientInterface); + dupOutputDesc->mOutput1 = mPrimaryOutput; + dupOutputDesc->mOutput2 = desc; dupOutputDesc->mSamplingRate = desc->mSamplingRate; dupOutputDesc->mFormat = desc->mFormat; dupOutputDesc->mChannelMask = desc->mChannelMask; dupOutputDesc->mLatency = desc->mLatency; addOutput(duplicatedOutput, dupOutputDesc); - applyStreamVolumes(duplicatedOutput, device, 0, true); + applyStreamVolumes(dupOutputDesc, device, 0, true); } else { ALOGW("checkOutputsForDevice() could not open dup output for %d and %d", - mPrimaryOutput, output); + mPrimaryOutput->mIoHandle, output); mpClientInterface->closeOutput(output); removeOutput(output); nextAudioPortGeneration(); @@ -3111,7 +3158,7 @@ status_t AudioPolicyManager::checkOutputsForDevice(const sp<DeviceDescriptor> de if (device_distinguishes_on_address(device)) { ALOGV("checkOutputsForDevice(): setOutputDevice(dev=0x%x, addr=%s)", device, address.string()); - setOutputDevice(output, device, true/*force*/, 0/*delay*/, + setOutputDevice(desc, device, true/*force*/, 0/*delay*/, NULL/*patch handle*/, address.string()); } ALOGV("checkOutputsForDevice(): adding output %d", output); @@ -3129,10 +3176,9 @@ status_t AudioPolicyManager::checkOutputsForDevice(const sp<DeviceDescriptor> de if (!desc->isDuplicated()) { // exact match on device if (device_distinguishes_on_address(device) && - (desc->mProfile->mSupportedDevices.types() == device)) { + (desc->supportedDevices() == device)) { findIoHandlesByAddress(desc, device, address, outputs); - } else if (!(desc->mProfile->mSupportedDevices.types() - & mAvailableOutputDevices.types())) { + } else if (!(desc->supportedDevices() & mAvailableOutputDevices.types())) { ALOGV("checkOutputsForDevice(): disconnecting adding output %d", mOutputs.keyAt(i)); outputs.add(mOutputs.keyAt(i)); @@ -3367,7 +3413,7 @@ void AudioPolicyManager::closeOutput(audio_io_handle_t output) { ALOGV("closeOutput(%d)", output); - sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output); + sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueFor(output); if (outputDesc == NULL) { ALOGW("closeOutput() unknown output %d", output); return; @@ -3376,7 +3422,7 @@ void AudioPolicyManager::closeOutput(audio_io_handle_t output) // look for duplicated outputs connected to the output being removed. for (size_t i = 0; i < mOutputs.size(); i++) { - sp<AudioOutputDescriptor> dupOutputDesc = mOutputs.valueAt(i); + sp<SwAudioOutputDescriptor> dupOutputDesc = mOutputs.valueAt(i); if (dupOutputDesc->isDuplicated() && (dupOutputDesc->mOutput1 == outputDesc || dupOutputDesc->mOutput2 == outputDesc)) { @@ -3445,8 +3491,9 @@ void AudioPolicyManager::closeInput(audio_io_handle_t input) mInputs.removeItem(input); } -SortedVector<audio_io_handle_t> AudioPolicyManager::getOutputsForDevice(audio_devices_t device, - AudioOutputCollection openOutputs) +SortedVector<audio_io_handle_t> AudioPolicyManager::getOutputsForDevice( + audio_devices_t device, + SwAudioOutputCollection openOutputs) { SortedVector<audio_io_handle_t> outputs; @@ -3487,14 +3534,14 @@ void AudioPolicyManager::checkOutputForStrategy(routing_strategy strategy) // associated with policies in the "before" and "after" output vectors ALOGVV("checkOutputForStrategy(): policy related outputs"); for (size_t i = 0 ; i < mPreviousOutputs.size() ; i++) { - const sp<AudioOutputDescriptor> desc = mPreviousOutputs.valueAt(i); + const sp<SwAudioOutputDescriptor> desc = mPreviousOutputs.valueAt(i); if (desc != 0 && desc->mPolicyMix != NULL) { srcOutputs.add(desc->mIoHandle); ALOGVV(" previous outputs: adding %d", desc->mIoHandle); } } for (size_t i = 0 ; i < mOutputs.size() ; i++) { - const sp<AudioOutputDescriptor> desc = mOutputs.valueAt(i); + const sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i); if (desc != 0 && desc->mPolicyMix != NULL) { dstOutputs.add(desc->mIoHandle); ALOGVV(" new outputs: adding %d", desc->mIoHandle); @@ -3506,10 +3553,10 @@ void AudioPolicyManager::checkOutputForStrategy(routing_strategy strategy) strategy, srcOutputs[0], dstOutputs[0]); // mute strategy while moving tracks from one output to another for (size_t i = 0; i < srcOutputs.size(); i++) { - sp<AudioOutputDescriptor> desc = mOutputs.valueFor(srcOutputs[i]); + sp<SwAudioOutputDescriptor> desc = mOutputs.valueFor(srcOutputs[i]); if (isStrategyActive(desc, strategy)) { - setStrategyMute(strategy, true, srcOutputs[i]); - setStrategyMute(strategy, false, srcOutputs[i], MUTE_TIME_MS, newDevice); + setStrategyMute(strategy, true, desc); + setStrategyMute(strategy, false, desc, MUTE_TIME_MS, newDevice); } } @@ -3606,12 +3653,11 @@ void AudioPolicyManager::checkA2dpSuspend() } } -audio_devices_t AudioPolicyManager::getNewOutputDevice(audio_io_handle_t output, bool fromCache) +audio_devices_t AudioPolicyManager::getNewOutputDevice(const sp<AudioOutputDescriptor>& outputDesc, + bool fromCache) { audio_devices_t device = AUDIO_DEVICE_NONE; - sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output); - ssize_t index = mAudioPatches.indexOfKey(outputDesc->mPatchHandle); if (index >= 0) { sp<AudioPatch> patchDesc = mAudioPatches.valueAt(index); @@ -3789,9 +3835,9 @@ uint32_t AudioPolicyManager::setBeaconMute(bool mute) { ALOGV("\t muting %d", mute); uint32_t maxLatency = 0; for (size_t i = 0; i < mOutputs.size(); i++) { - sp<AudioOutputDescriptor> desc = mOutputs.valueAt(i); + sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i); setStreamMute(AUDIO_STREAM_TTS, mute/*on*/, - desc->mIoHandle, + desc, 0 /*delay*/, AUDIO_DEVICE_NONE); const uint32_t latency = desc->latency() * 2; if (latency > maxLatency) { @@ -3855,7 +3901,7 @@ uint32_t AudioPolicyManager::checkDeviceMuteStrategies(sp<AudioOutputDescriptor> for (size_t i = 0; i < NUM_STRATEGIES; i++) { audio_devices_t curDevice = getDeviceForStrategy((routing_strategy)i, false /*fromCache*/); - curDevice = curDevice & outputDesc->mProfile->mSupportedDevices.types(); + curDevice = curDevice & outputDesc->supportedDevices(); bool mute = shouldMute && (curDevice & device) && (curDevice != device); bool doMute = false; @@ -3874,10 +3920,9 @@ uint32_t AudioPolicyManager::checkDeviceMuteStrategies(sp<AudioOutputDescriptor> == AUDIO_DEVICE_NONE) { continue; } - audio_io_handle_t curOutput = mOutputs.keyAt(j); - ALOGVV("checkDeviceMuteStrategies() %s strategy %d (curDevice %04x) on output %d", - mute ? "muting" : "unmuting", i, curDevice, curOutput); - setStrategyMute((routing_strategy)i, mute, curOutput, mute ? 0 : delayMs); + ALOGVV("checkDeviceMuteStrategies() %s strategy %d (curDevice %04x)", + mute ? "muting" : "unmuting", i, curDevice); + setStrategyMute((routing_strategy)i, mute, desc, mute ? 0 : delayMs); if (isStrategyActive(desc, (routing_strategy)i)) { if (mute) { // FIXME: should not need to double latency if volume could be applied @@ -3902,9 +3947,9 @@ uint32_t AudioPolicyManager::checkDeviceMuteStrategies(sp<AudioOutputDescriptor> } for (size_t i = 0; i < NUM_STRATEGIES; i++) { if (isStrategyActive(outputDesc, (routing_strategy)i)) { - setStrategyMute((routing_strategy)i, true, outputDesc->mIoHandle); + setStrategyMute((routing_strategy)i, true, outputDesc); // do tempMute unmute after twice the mute wait time - setStrategyMute((routing_strategy)i, false, outputDesc->mIoHandle, + setStrategyMute((routing_strategy)i, false, outputDesc, muteWaitMs *2, device); } } @@ -3919,32 +3964,31 @@ uint32_t AudioPolicyManager::checkDeviceMuteStrategies(sp<AudioOutputDescriptor> return 0; } -uint32_t AudioPolicyManager::setOutputDevice(audio_io_handle_t output, +uint32_t AudioPolicyManager::setOutputDevice(const sp<AudioOutputDescriptor>& outputDesc, audio_devices_t device, bool force, int delayMs, audio_patch_handle_t *patchHandle, const char* address) { - ALOGV("setOutputDevice() output %d device %04x delayMs %d", output, device, delayMs); - sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output); + ALOGV("setOutputDevice() device %04x delayMs %d", device, delayMs); AudioParameter param; uint32_t muteWaitMs; if (outputDesc->isDuplicated()) { - muteWaitMs = setOutputDevice(outputDesc->mOutput1->mIoHandle, device, force, delayMs); - muteWaitMs += setOutputDevice(outputDesc->mOutput2->mIoHandle, device, force, delayMs); + muteWaitMs = setOutputDevice(outputDesc->subOutput1(), device, force, delayMs); + muteWaitMs += setOutputDevice(outputDesc->subOutput2(), device, force, delayMs); return muteWaitMs; } // no need to proceed if new device is not AUDIO_DEVICE_NONE and not supported by current // output profile - if (device != AUDIO_DEVICE_NONE && - (device & outputDesc->mProfile->mSupportedDevices.types()) == 0) { + if ((device != AUDIO_DEVICE_NONE) && + ((device & outputDesc->supportedDevices()) == 0)) { return 0; } // filter devices according to output selected - device = (audio_devices_t)(device & outputDesc->mProfile->mSupportedDevices.types()); + device = (audio_devices_t)(device & outputDesc->supportedDevices()); audio_devices_t prevDevice = outputDesc->mDevice; @@ -3964,8 +4008,7 @@ uint32_t AudioPolicyManager::setOutputDevice(audio_io_handle_t output, if ((device == AUDIO_DEVICE_NONE || device == prevDevice) && !force && outputDesc->mPatchHandle != 0) { - ALOGV("setOutputDevice() setting same device 0x%04x or null device for output %d", - device, output); + ALOGV("setOutputDevice() setting same device 0x%04x or null device", device); return muteWaitMs; } @@ -3973,7 +4016,7 @@ uint32_t AudioPolicyManager::setOutputDevice(audio_io_handle_t output, // do the routing if (device == AUDIO_DEVICE_NONE) { - resetOutputDevice(output, delayMs, NULL); + resetOutputDevice(outputDesc, delayMs, NULL); } else { DeviceVector deviceList = (address == NULL) ? mAvailableOutputDevices.getDevicesFromType(device) @@ -4040,16 +4083,15 @@ uint32_t AudioPolicyManager::setOutputDevice(audio_io_handle_t output, } // update stream volumes according to new device - applyStreamVolumes(output, device, delayMs); + applyStreamVolumes(outputDesc, device, delayMs); return muteWaitMs; } -status_t AudioPolicyManager::resetOutputDevice(audio_io_handle_t output, +status_t AudioPolicyManager::resetOutputDevice(const sp<AudioOutputDescriptor>& outputDesc, int delayMs, audio_patch_handle_t *patchHandle) { - sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output); ssize_t index; if (patchHandle) { index = mAudioPatches.indexOfKey(*patchHandle); @@ -4206,16 +4248,11 @@ audio_devices_t AudioPolicyManager::getDeviceForInputSource(audio_source_t input } float AudioPolicyManager::computeVolume(audio_stream_type_t stream, - int index, - audio_io_handle_t output, - audio_devices_t device) + int index, + audio_devices_t device) { float volume = 1.0; - sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output); - if (device == AUDIO_DEVICE_NONE) { - device = outputDesc->device(); - } volume = mEngine->volIndexToAmpl(Volume::getDeviceCategory(device), stream, index); // if a headset is connected, apply the following rules to ring tones and notifications @@ -4242,8 +4279,7 @@ float AudioPolicyManager::computeVolume(audio_stream_type_t stream, mLimitRingtoneVolume) { audio_devices_t musicDevice = getDeviceForStrategy(STRATEGY_MEDIA, true /*fromCache*/); float musicVol = computeVolume(AUDIO_STREAM_MUSIC, - mStreams[AUDIO_STREAM_MUSIC].getVolumeIndex(musicDevice), - output, + mStreams.valueFor(AUDIO_STREAM_MUSIC).getVolumeIndex(musicDevice), musicDevice); float minVol = (musicVol > SONIFICATION_HEADSET_VOLUME_MIN) ? musicVol : SONIFICATION_HEADSET_VOLUME_MIN; @@ -4258,17 +4294,16 @@ float AudioPolicyManager::computeVolume(audio_stream_type_t stream, } status_t AudioPolicyManager::checkAndSetVolume(audio_stream_type_t stream, - int index, - audio_io_handle_t output, - audio_devices_t device, - int delayMs, - bool force) + int index, + const sp<AudioOutputDescriptor>& outputDesc, + audio_devices_t device, + int delayMs, + bool force) { - // do not change actual stream volume if the stream is muted - if (mOutputs.valueFor(output)->mMuteCount[stream] != 0) { + if (outputDesc->mMuteCount[stream] != 0) { ALOGVV("checkAndSetVolume() stream %d muted count %d", - stream, mOutputs.valueFor(output)->mMuteCount[stream]); + stream, outputDesc->mMuteCount[stream]); return NO_ERROR; } audio_policy_forced_cfg_t forceUseForComm = @@ -4281,45 +4316,28 @@ status_t AudioPolicyManager::checkAndSetVolume(audio_stream_type_t stream, return INVALID_OPERATION; } - float volume = computeVolume(stream, index, output, device); - // unit gain if rerouting to external policy - if (device == AUDIO_DEVICE_OUT_REMOTE_SUBMIX) { - ssize_t index = mOutputs.indexOfKey(output); - if (index >= 0) { - sp<AudioOutputDescriptor> outputDesc = mOutputs.valueAt(index); - if (outputDesc->mPolicyMix != NULL) { - ALOGV("max gain when rerouting for output=%d", output); - volume = 1.0f; - } - } - + if (device == AUDIO_DEVICE_NONE) { + device = outputDesc->device(); } - // We actually change the volume if: - // - the float value returned by computeVolume() changed - // - the force flag is set - if (volume != mOutputs.valueFor(output)->mCurVolume[stream] || - force) { - mOutputs.valueFor(output)->mCurVolume[stream] = volume; - ALOGVV("checkAndSetVolume() for output %d stream %d, volume %f, delay %d", output, stream, volume, delayMs); - // Force VOICE_CALL to track BLUETOOTH_SCO stream volume when bluetooth audio is - // enabled - if (stream == AUDIO_STREAM_BLUETOOTH_SCO) { - mpClientInterface->setStreamVolume(AUDIO_STREAM_VOICE_CALL, volume, output, delayMs); - } - mpClientInterface->setStreamVolume(stream, volume, output, delayMs); + + float volume = computeVolume(stream, index, device); + if (outputDesc->isFixedVolume(device)) { + volume = 1.0f; } + outputDesc->setVolume(volume, stream, device, delayMs, force); + if (stream == AUDIO_STREAM_VOICE_CALL || stream == AUDIO_STREAM_BLUETOOTH_SCO) { float voiceVolume; // Force voice volume to max for bluetooth SCO as volume is managed by the headset if (stream == AUDIO_STREAM_VOICE_CALL) { - voiceVolume = (float)index/(float)mStreams[stream].getVolumeIndexMax(); + voiceVolume = (float)index/(float)mStreams.valueFor(stream).getVolumeIndexMax(); } else { voiceVolume = 1.0; } - if (voiceVolume != mLastVoiceVolume && output == mPrimaryOutput) { + if (voiceVolume != mLastVoiceVolume && outputDesc == mPrimaryOutput) { mpClientInterface->setVoiceVolume(voiceVolume, delayMs); mLastVoiceVolume = voiceVolume; } @@ -4328,20 +4346,20 @@ status_t AudioPolicyManager::checkAndSetVolume(audio_stream_type_t stream, return NO_ERROR; } -void AudioPolicyManager::applyStreamVolumes(audio_io_handle_t output, - audio_devices_t device, - int delayMs, - bool force) +void AudioPolicyManager::applyStreamVolumes(const sp<AudioOutputDescriptor>& outputDesc, + audio_devices_t device, + int delayMs, + bool force) { - ALOGVV("applyStreamVolumes() for output %d and device %x", output, device); + ALOGVV("applyStreamVolumes() for device %08x", device); for (int stream = 0; stream < AUDIO_STREAM_CNT; stream++) { if (stream == AUDIO_STREAM_PATCH) { continue; } checkAndSetVolume((audio_stream_type_t)stream, - mStreams[stream].getVolumeIndex(device), - output, + mStreams.valueFor((audio_stream_type_t)stream).getVolumeIndex(device), + outputDesc, device, delayMs, force); @@ -4349,10 +4367,10 @@ void AudioPolicyManager::applyStreamVolumes(audio_io_handle_t output, } void AudioPolicyManager::setStrategyMute(routing_strategy strategy, - bool on, - audio_io_handle_t output, - int delayMs, - audio_devices_t device) + bool on, + const sp<AudioOutputDescriptor>& outputDesc, + int delayMs, + audio_devices_t device) { ALOGVV("setStrategyMute() strategy %d, mute %d, output %d", strategy, on, output); for (int stream = 0; stream < AUDIO_STREAM_CNT; stream++) { @@ -4360,32 +4378,31 @@ void AudioPolicyManager::setStrategyMute(routing_strategy strategy, continue; } if (getStrategy((audio_stream_type_t)stream) == strategy) { - setStreamMute((audio_stream_type_t)stream, on, output, delayMs, device); + setStreamMute((audio_stream_type_t)stream, on, outputDesc, delayMs, device); } } } void AudioPolicyManager::setStreamMute(audio_stream_type_t stream, - bool on, - audio_io_handle_t output, - int delayMs, - audio_devices_t device) + bool on, + const sp<AudioOutputDescriptor>& outputDesc, + int delayMs, + audio_devices_t device) { - const StreamDescriptor &streamDesc = mStreams[stream]; - sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output); + const StreamDescriptor& streamDesc = mStreams.valueFor(stream); if (device == AUDIO_DEVICE_NONE) { device = outputDesc->device(); } - ALOGVV("setStreamMute() stream %d, mute %d, output %d, mMuteCount %d device %04x", - stream, on, output, outputDesc->mMuteCount[stream], device); + ALOGVV("setStreamMute() stream %d, mute %d, mMuteCount %d device %04x", + stream, on, outputDesc->mMuteCount[stream], device); if (on) { if (outputDesc->mMuteCount[stream] == 0) { if (streamDesc.canBeMuted() && ((stream != AUDIO_STREAM_ENFORCED_AUDIBLE) || (mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_SYSTEM) == AUDIO_POLICY_FORCE_NONE))) { - checkAndSetVolume(stream, 0, output, device, delayMs); + checkAndSetVolume(stream, 0, outputDesc, device, delayMs); } } // increment mMuteCount after calling checkAndSetVolume() so that volume change is not ignored @@ -4398,7 +4415,7 @@ void AudioPolicyManager::setStreamMute(audio_stream_type_t stream, if (--outputDesc->mMuteCount[stream] == 0) { checkAndSetVolume(stream, streamDesc.getVolumeIndex(device), - output, + outputDesc, device, delayMs); } @@ -4417,7 +4434,7 @@ void AudioPolicyManager::handleIncallSonification(audio_stream_type_t stream, const routing_strategy stream_strategy = getStrategy(stream); if ((stream_strategy == STRATEGY_SONIFICATION) || ((stream_strategy == STRATEGY_SONIFICATION_RESPECTFUL))) { - sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(mPrimaryOutput); + sp<SwAudioOutputDescriptor> outputDesc = mPrimaryOutput; ALOGV("handleIncallSonification() stream %d starting %d device %x stateChange %d", stream, starting, outputDesc->mDevice, stateChange); if (outputDesc->mRefCount[stream]) { diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h index 9fab9ef..9baeeb6 100644 --- a/services/audiopolicy/managerdefault/AudioPolicyManager.h +++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h @@ -173,19 +173,15 @@ public: return mEffects.setEffectEnabled(id, enabled); } - virtual bool isStreamActive(audio_stream_type_t stream, uint32_t inPastMs = 0) const - { - return mOutputs.isStreamActive(stream, inPastMs); - } + virtual bool isStreamActive(audio_stream_type_t stream, uint32_t inPastMs = 0) const; // return whether a stream is playing remotely, override to change the definition of // local/remote playback, used for instance by notification manager to not make // media players lose audio focus when not playing locally // For the base implementation, "remotely" means playing during screen mirroring which // uses an output for playback with a non-empty, non "0" address. - virtual bool isStreamActiveRemotely(audio_stream_type_t stream, uint32_t inPastMs = 0) const - { - return mOutputs.isStreamActiveRemotely(stream, inPastMs); - } + virtual bool isStreamActiveRemotely(audio_stream_type_t stream, + uint32_t inPastMs = 0) const; + virtual bool isSourceActive(audio_source_t source) const; virtual status_t dump(int fd); @@ -281,7 +277,7 @@ protected: { return mPolicyMixes; } - virtual const AudioOutputCollection &getOutputs() const + virtual const SwAudioOutputCollection &getOutputs() const { return mOutputs; } @@ -306,7 +302,7 @@ protected: return mDefaultOutputDevice; } protected: - void addOutput(audio_io_handle_t output, sp<AudioOutputDescriptor> outputDesc); + void addOutput(audio_io_handle_t output, sp<SwAudioOutputDescriptor> outputDesc); void removeOutput(audio_io_handle_t output); void addInput(audio_io_handle_t input, sp<AudioInputDescriptor> inputDesc); @@ -329,13 +325,13 @@ protected: // change the route of the specified output. Returns the number of ms we have slept to // allow new routing to take effect in certain cases. - virtual uint32_t setOutputDevice(audio_io_handle_t output, + virtual uint32_t setOutputDevice(const sp<AudioOutputDescriptor>& outputDesc, audio_devices_t device, bool force = false, int delayMs = 0, audio_patch_handle_t *patchHandle = NULL, const char* address = NULL); - status_t resetOutputDevice(audio_io_handle_t output, + status_t resetOutputDevice(const sp<AudioOutputDescriptor>& outputDesc, int delayMs = 0, audio_patch_handle_t *patchHandle = NULL); status_t setInputDevice(audio_io_handle_t input, @@ -350,29 +346,31 @@ protected: // compute the actual volume for a given stream according to the requested index and a particular // device - virtual float computeVolume(audio_stream_type_t stream, int index, - audio_io_handle_t output, audio_devices_t device); + virtual float computeVolume(audio_stream_type_t stream, + int index, + audio_devices_t device); // check that volume change is permitted, compute and send new volume to audio hardware virtual status_t checkAndSetVolume(audio_stream_type_t stream, int index, - audio_io_handle_t output, + const sp<AudioOutputDescriptor>& outputDesc, audio_devices_t device, int delayMs = 0, bool force = false); // apply all stream volumes to the specified output and device - void applyStreamVolumes(audio_io_handle_t output, audio_devices_t device, int delayMs = 0, bool force = false); + void applyStreamVolumes(const sp<AudioOutputDescriptor>& outputDesc, + audio_devices_t device, int delayMs = 0, bool force = false); // Mute or unmute all streams handled by the specified strategy on the specified output void setStrategyMute(routing_strategy strategy, bool on, - audio_io_handle_t output, + const sp<AudioOutputDescriptor>& outputDesc, int delayMs = 0, audio_devices_t device = (audio_devices_t)0); // Mute or unmute the stream on the specified output void setStreamMute(audio_stream_type_t stream, bool on, - audio_io_handle_t output, + const sp<AudioOutputDescriptor>& outputDesc, int delayMs = 0, audio_devices_t device = (audio_devices_t)0); @@ -425,7 +423,8 @@ protected: // must be called every time a condition that affects the device choice for a given output is // changed: connected device, phone state, force use, output start, output stop.. // see getDeviceForStrategy() for the use of fromCache parameter - audio_devices_t getNewOutputDevice(audio_io_handle_t output, bool fromCache); + audio_devices_t getNewOutputDevice(const sp<AudioOutputDescriptor>& outputDesc, + bool fromCache); // updates cache of device used by all strategies (mDeviceForStrategy[]) // must be called every time a condition that affects the device choice for a given strategy is @@ -453,7 +452,7 @@ protected: #endif //AUDIO_POLICY_TEST SortedVector<audio_io_handle_t> getOutputsForDevice(audio_devices_t device, - AudioOutputCollection openOutputs); + SwAudioOutputCollection openOutputs); bool vectorsEqual(SortedVector<audio_io_handle_t>& outputs1, SortedVector<audio_io_handle_t>& outputs2); @@ -494,25 +493,33 @@ protected: audio_devices_t availablePrimaryOutputDevices() const { - return mOutputs.getSupportedDevices(mPrimaryOutput) & mAvailableOutputDevices.types(); + return mPrimaryOutput->supportedDevices() & mAvailableOutputDevices.types(); } audio_devices_t availablePrimaryInputDevices() const { - return mAvailableInputDevices.getDevicesFromHwModule( - mOutputs.valueFor(mPrimaryOutput)->getModuleHandle()); + return mAvailableInputDevices.getDevicesFromHwModule(mPrimaryOutput->getModuleHandle()); } void updateCallRouting(audio_devices_t rxDevice, int delayMs = 0); + status_t startSource(sp<AudioOutputDescriptor> outputDesc, + audio_stream_type_t stream, + audio_devices_t device, + uint32_t *delayMs); + status_t stopSource(sp<AudioOutputDescriptor> outputDesc, + audio_stream_type_t stream); + uid_t mUidCached; AudioPolicyClientInterface *mpClientInterface; // audio policy client interface - audio_io_handle_t mPrimaryOutput; // primary output handle + sp<SwAudioOutputDescriptor> mPrimaryOutput; // primary output descriptor // list of descriptors for outputs currently opened - AudioOutputCollection mOutputs; + + SwAudioOutputCollection mOutputs; // copy of mOutputs before setDeviceConnectionState() opens new outputs // reset to mOutputs when updateDevicesAndOutputs() is called. - AudioOutputCollection mPreviousOutputs; + SwAudioOutputCollection mPreviousOutputs; AudioInputCollection mInputs; // list of input descriptors + DeviceVector mAvailableOutputDevices; // all available output devices DeviceVector mAvailableInputDevices; // all available input devices @@ -583,7 +590,7 @@ private: // in mProfile->mSupportedDevices) matches the device whose address is to be matched. // see deviceDistinguishesOnAddress(audio_devices_t) for whether the device type is one // where addresses are used to distinguish between one connected device and another. - void findIoHandlesByAddress(sp<AudioOutputDescriptor> desc /*in*/, + void findIoHandlesByAddress(sp<SwAudioOutputDescriptor> desc /*in*/, const audio_devices_t device /*in*/, const String8 address /*in*/, SortedVector<audio_io_handle_t>& outputs /*out*/); |