Loading services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h +8 −3 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ namespace android { class AudioPolicyMix; class DeviceDescriptor; class HwAudioOutputDescriptor; class SwAudioOutputDescriptor; Loading Loading @@ -90,11 +91,12 @@ public: product_strategy_t strategy, VolumeSource volumeSource, audio_output_flags_t flags, bool isPreferredDeviceForExclusiveUse, std::vector<wp<SwAudioOutputDescriptor>> secondaryOutputs) : std::vector<wp<SwAudioOutputDescriptor>> secondaryOutputs, wp<AudioPolicyMix> primaryMix) : ClientDescriptor(portId, uid, sessionId, attributes, config, preferredDeviceId, isPreferredDeviceForExclusiveUse), mStream(stream), mStrategy(strategy), mVolumeSource(volumeSource), mFlags(flags), mSecondaryOutputs(std::move(secondaryOutputs)) {} mSecondaryOutputs(std::move(secondaryOutputs)), mPrimaryMix(primaryMix) {} ~TrackClientDescriptor() override = default; using ClientDescriptor::dump; Loading @@ -108,6 +110,9 @@ public: return mSecondaryOutputs; }; VolumeSource volumeSource() const { return mVolumeSource; } const sp<AudioPolicyMix> getPrimaryMix() const { return mPrimaryMix.promote(); }; void setActive(bool active) override { Loading Loading @@ -136,7 +141,7 @@ private: const VolumeSource mVolumeSource; const audio_output_flags_t mFlags; const std::vector<wp<SwAudioOutputDescriptor>> mSecondaryOutputs; const wp<AudioPolicyMix> mPrimaryMix; /** * required for duplicating thread, prevent from removing active client from an output * involved in a duplication. Loading services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp +4 −1 Original line number Diff line number Diff line Loading @@ -28,7 +28,7 @@ namespace android { void AudioPolicyMix::dump(String8 *dst, int spaces, int index) const { dst->appendFormat("%*sAudio Policy Mix %d:\n", spaces, "", index + 1); dst->appendFormat("%*sAudio Policy Mix %d (%p):\n", spaces, "", index + 1, this); std::string mixTypeLiteral; if (!MixTypeConverter::toString(mMixType, mixTypeLiteral)) { ALOGE("%s: failed to convert mix type %d", __FUNCTION__, mMixType); Loading @@ -44,6 +44,9 @@ void AudioPolicyMix::dump(String8 *dst, int spaces, int index) const dst->appendFormat("%*s- device address: %s\n", spaces, "", mDeviceAddress.string()); dst->appendFormat("%*s- output: %d\n", spaces, "", mOutput == nullptr ? 0 : mOutput->mIoHandle); int indexCriterion = 0; for (const auto &criterion : mCriteria) { dst->appendFormat("%*s- Criterion %d: ", spaces + 2, "", indexCriterion++); Loading services/audiopolicy/common/managerdefinitions/src/ClientDescriptor.cpp +8 −1 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ #include <TypeConverter.h> #include "AudioOutputDescriptor.h" #include "AudioPatch.h" #include "AudioPolicyMix.h" #include "ClientDescriptor.h" #include "DeviceDescriptor.h" #include "HwModule.h" Loading Loading @@ -55,6 +56,12 @@ void TrackClientDescriptor::dump(String8 *dst, int spaces, int index) const ClientDescriptor::dump(dst, spaces, index); dst->appendFormat("%*s- Stream: %d flags: %08x\n", spaces, "", mStream, mFlags); dst->appendFormat("%*s- Refcount: %d\n", spaces, "", mActivityCount); dst->appendFormat("%*s- DAP Primary Mix: %p\n", spaces, "", mPrimaryMix.promote().get()); dst->appendFormat("%*s- DAP Secondary Outputs:\n", spaces, ""); for (auto desc : mSecondaryOutputs) { dst->appendFormat("%*s - %d\n", spaces, "", desc.promote() == nullptr ? 0 : desc.promote()->mIoHandle); } } std::string TrackClientDescriptor::toShortString() const Loading Loading @@ -88,7 +95,7 @@ SourceClientDescriptor::SourceClientDescriptor(audio_port_handle_t portId, uid_t TrackClientDescriptor::TrackClientDescriptor(portId, uid, AUDIO_SESSION_NONE, attributes, {config.sample_rate, config.channel_mask, config.format}, AUDIO_PORT_HANDLE_NONE, stream, strategy, volumeSource, AUDIO_OUTPUT_FLAG_NONE, false, {} /* Sources do not support secondary outputs*/), mSrcDevice(srcDevice) {} /* Sources do not support secondary outputs*/, nullptr), mSrcDevice(srcDevice) { } Loading services/audiopolicy/managerdefault/AudioPolicyManager.cpp +42 −23 Original line number Diff line number Diff line Loading @@ -1102,14 +1102,15 @@ status_t AudioPolicyManager::getOutputForAttr(const audio_attributes_t *attr, }; *portId = PolicyAudioPort::getNextUniqueId(); sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueFor(*output); sp<TrackClientDescriptor> clientDesc = new TrackClientDescriptor(*portId, uid, session, resultAttr, clientConfig, sanitizedRequestedPortId, *stream, mEngine->getProductStrategyForAttributes(resultAttr), toVolumeSource(resultAttr), *flags, isRequestedDeviceForExclusiveUse, std::move(weakSecondaryOutputDescs)); sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueFor(*output); std::move(weakSecondaryOutputDescs), outputDesc->mPolicyMix); outputDesc->addClient(clientDesc); ALOGV("%s() returns output %d requestedPortId %d selectedDeviceId %d for port ID %d", __func__, Loading Loading @@ -2877,7 +2878,7 @@ status_t AudioPolicyManager::registerPolicyMixes(const Vector<AudioMix>& mixes) { ALOGV("registerPolicyMixes() %zu mix(es)", mixes.size()); status_t res = NO_ERROR; bool checkOutputs = false; sp<HwModule> rSubmixModule; // examine each mix's route type for (size_t i = 0; i < mixes.size(); i++) { Loading Loading @@ -2996,11 +2997,16 @@ status_t AudioPolicyManager::registerPolicyMixes(const Vector<AudioMix>& mixes) i, type, address.string()); res = INVALID_OPERATION; break; } else { checkOutputs = true; } } } if (res != NO_ERROR) { unregisterPolicyMixes(mixes); } else if (checkOutputs) { checkForDeviceAndOutputChanges(); updateCallAndOutputRouting(); } return res; } Loading @@ -3009,6 +3015,7 @@ status_t AudioPolicyManager::unregisterPolicyMixes(Vector<AudioMix> mixes) { ALOGV("unregisterPolicyMixes() num mixes %zu", mixes.size()); status_t res = NO_ERROR; bool checkOutputs = false; sp<HwModule> rSubmixModule; // examine each mix's route type for (const auto& mix : mixes) { Loading Loading @@ -3049,9 +3056,15 @@ status_t AudioPolicyManager::unregisterPolicyMixes(Vector<AudioMix> mixes) if (mPolicyMixes.unregisterMix(mix) != NO_ERROR) { res = INVALID_OPERATION; continue; } else { checkOutputs = true; } } } if (res == NO_ERROR && checkOutputs) { checkForDeviceAndOutputChanges(); updateCallAndOutputRouting(); } return res; } Loading Loading @@ -5226,32 +5239,38 @@ void AudioPolicyManager::checkOutputForAttributes(const audio_attributes_t &attr SortedVector<audio_io_handle_t> srcOutputs = getOutputsForDevices(oldDevices, mPreviousOutputs); SortedVector<audio_io_handle_t> dstOutputs = getOutputsForDevices(newDevices, mOutputs); // also take into account external policy-related changes: add all outputs which are // associated with policies in the "before" and "after" output vectors ALOGVV("%s(): policy related outputs", __func__); bool hasDynamicPolicy = false; for (size_t i = 0 ; i < mPreviousOutputs.size() ; i++) { const sp<SwAudioOutputDescriptor> desc = mPreviousOutputs.valueAt(i); if (desc != 0 && desc->mPolicyMix != NULL) { srcOutputs.add(desc->mIoHandle); hasDynamicPolicy = true; ALOGVV(" previous outputs: adding %d", desc->mIoHandle); uint32_t maxLatency = 0; bool invalidate = false; // take into account dynamic audio policies related changes: if a client is now associated // to a different policy mix than at creation time, invalidate corresponding stream for (size_t i = 0; i < mPreviousOutputs.size() && !invalidate; i++) { const sp<SwAudioOutputDescriptor>& desc = mPreviousOutputs.valueAt(i); if (desc->isDuplicated()) { continue; } for (const sp<TrackClientDescriptor>& client : desc->getClientIterable()) { if (mEngine->getProductStrategyForAttributes(client->attributes()) != psId) { continue; } sp<AudioPolicyMix> primaryMix; status_t status = mPolicyMixes.getOutputForAttr(client->attributes(), client->uid(), client->flags(), primaryMix, nullptr); if (status != OK) { continue; } if (client->getPrimaryMix() != primaryMix) { invalidate = true; if (desc->isStrategyActive(psId)) { maxLatency = desc->latency(); } break; } for (size_t i = 0 ; i < mOutputs.size() ; i++) { const sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i); if (desc != 0 && desc->mPolicyMix != NULL) { dstOutputs.add(desc->mIoHandle); hasDynamicPolicy = true; ALOGVV(" new outputs: adding %d", desc->mIoHandle); } } if (srcOutputs != dstOutputs) { if (srcOutputs != dstOutputs || invalidate) { // get maximum latency of all source outputs to determine the minimum mute time guaranteeing // audio from invalidated tracks will be rendered when unmuting uint32_t maxLatency = 0; bool invalidate = hasDynamicPolicy; for (audio_io_handle_t srcOut : srcOutputs) { sp<SwAudioOutputDescriptor> desc = mPreviousOutputs.valueFor(srcOut); if (desc == nullptr) continue; Loading Loading
services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h +8 −3 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ namespace android { class AudioPolicyMix; class DeviceDescriptor; class HwAudioOutputDescriptor; class SwAudioOutputDescriptor; Loading Loading @@ -90,11 +91,12 @@ public: product_strategy_t strategy, VolumeSource volumeSource, audio_output_flags_t flags, bool isPreferredDeviceForExclusiveUse, std::vector<wp<SwAudioOutputDescriptor>> secondaryOutputs) : std::vector<wp<SwAudioOutputDescriptor>> secondaryOutputs, wp<AudioPolicyMix> primaryMix) : ClientDescriptor(portId, uid, sessionId, attributes, config, preferredDeviceId, isPreferredDeviceForExclusiveUse), mStream(stream), mStrategy(strategy), mVolumeSource(volumeSource), mFlags(flags), mSecondaryOutputs(std::move(secondaryOutputs)) {} mSecondaryOutputs(std::move(secondaryOutputs)), mPrimaryMix(primaryMix) {} ~TrackClientDescriptor() override = default; using ClientDescriptor::dump; Loading @@ -108,6 +110,9 @@ public: return mSecondaryOutputs; }; VolumeSource volumeSource() const { return mVolumeSource; } const sp<AudioPolicyMix> getPrimaryMix() const { return mPrimaryMix.promote(); }; void setActive(bool active) override { Loading Loading @@ -136,7 +141,7 @@ private: const VolumeSource mVolumeSource; const audio_output_flags_t mFlags; const std::vector<wp<SwAudioOutputDescriptor>> mSecondaryOutputs; const wp<AudioPolicyMix> mPrimaryMix; /** * required for duplicating thread, prevent from removing active client from an output * involved in a duplication. Loading
services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp +4 −1 Original line number Diff line number Diff line Loading @@ -28,7 +28,7 @@ namespace android { void AudioPolicyMix::dump(String8 *dst, int spaces, int index) const { dst->appendFormat("%*sAudio Policy Mix %d:\n", spaces, "", index + 1); dst->appendFormat("%*sAudio Policy Mix %d (%p):\n", spaces, "", index + 1, this); std::string mixTypeLiteral; if (!MixTypeConverter::toString(mMixType, mixTypeLiteral)) { ALOGE("%s: failed to convert mix type %d", __FUNCTION__, mMixType); Loading @@ -44,6 +44,9 @@ void AudioPolicyMix::dump(String8 *dst, int spaces, int index) const dst->appendFormat("%*s- device address: %s\n", spaces, "", mDeviceAddress.string()); dst->appendFormat("%*s- output: %d\n", spaces, "", mOutput == nullptr ? 0 : mOutput->mIoHandle); int indexCriterion = 0; for (const auto &criterion : mCriteria) { dst->appendFormat("%*s- Criterion %d: ", spaces + 2, "", indexCriterion++); Loading
services/audiopolicy/common/managerdefinitions/src/ClientDescriptor.cpp +8 −1 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ #include <TypeConverter.h> #include "AudioOutputDescriptor.h" #include "AudioPatch.h" #include "AudioPolicyMix.h" #include "ClientDescriptor.h" #include "DeviceDescriptor.h" #include "HwModule.h" Loading Loading @@ -55,6 +56,12 @@ void TrackClientDescriptor::dump(String8 *dst, int spaces, int index) const ClientDescriptor::dump(dst, spaces, index); dst->appendFormat("%*s- Stream: %d flags: %08x\n", spaces, "", mStream, mFlags); dst->appendFormat("%*s- Refcount: %d\n", spaces, "", mActivityCount); dst->appendFormat("%*s- DAP Primary Mix: %p\n", spaces, "", mPrimaryMix.promote().get()); dst->appendFormat("%*s- DAP Secondary Outputs:\n", spaces, ""); for (auto desc : mSecondaryOutputs) { dst->appendFormat("%*s - %d\n", spaces, "", desc.promote() == nullptr ? 0 : desc.promote()->mIoHandle); } } std::string TrackClientDescriptor::toShortString() const Loading Loading @@ -88,7 +95,7 @@ SourceClientDescriptor::SourceClientDescriptor(audio_port_handle_t portId, uid_t TrackClientDescriptor::TrackClientDescriptor(portId, uid, AUDIO_SESSION_NONE, attributes, {config.sample_rate, config.channel_mask, config.format}, AUDIO_PORT_HANDLE_NONE, stream, strategy, volumeSource, AUDIO_OUTPUT_FLAG_NONE, false, {} /* Sources do not support secondary outputs*/), mSrcDevice(srcDevice) {} /* Sources do not support secondary outputs*/, nullptr), mSrcDevice(srcDevice) { } Loading
services/audiopolicy/managerdefault/AudioPolicyManager.cpp +42 −23 Original line number Diff line number Diff line Loading @@ -1102,14 +1102,15 @@ status_t AudioPolicyManager::getOutputForAttr(const audio_attributes_t *attr, }; *portId = PolicyAudioPort::getNextUniqueId(); sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueFor(*output); sp<TrackClientDescriptor> clientDesc = new TrackClientDescriptor(*portId, uid, session, resultAttr, clientConfig, sanitizedRequestedPortId, *stream, mEngine->getProductStrategyForAttributes(resultAttr), toVolumeSource(resultAttr), *flags, isRequestedDeviceForExclusiveUse, std::move(weakSecondaryOutputDescs)); sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueFor(*output); std::move(weakSecondaryOutputDescs), outputDesc->mPolicyMix); outputDesc->addClient(clientDesc); ALOGV("%s() returns output %d requestedPortId %d selectedDeviceId %d for port ID %d", __func__, Loading Loading @@ -2877,7 +2878,7 @@ status_t AudioPolicyManager::registerPolicyMixes(const Vector<AudioMix>& mixes) { ALOGV("registerPolicyMixes() %zu mix(es)", mixes.size()); status_t res = NO_ERROR; bool checkOutputs = false; sp<HwModule> rSubmixModule; // examine each mix's route type for (size_t i = 0; i < mixes.size(); i++) { Loading Loading @@ -2996,11 +2997,16 @@ status_t AudioPolicyManager::registerPolicyMixes(const Vector<AudioMix>& mixes) i, type, address.string()); res = INVALID_OPERATION; break; } else { checkOutputs = true; } } } if (res != NO_ERROR) { unregisterPolicyMixes(mixes); } else if (checkOutputs) { checkForDeviceAndOutputChanges(); updateCallAndOutputRouting(); } return res; } Loading @@ -3009,6 +3015,7 @@ status_t AudioPolicyManager::unregisterPolicyMixes(Vector<AudioMix> mixes) { ALOGV("unregisterPolicyMixes() num mixes %zu", mixes.size()); status_t res = NO_ERROR; bool checkOutputs = false; sp<HwModule> rSubmixModule; // examine each mix's route type for (const auto& mix : mixes) { Loading Loading @@ -3049,9 +3056,15 @@ status_t AudioPolicyManager::unregisterPolicyMixes(Vector<AudioMix> mixes) if (mPolicyMixes.unregisterMix(mix) != NO_ERROR) { res = INVALID_OPERATION; continue; } else { checkOutputs = true; } } } if (res == NO_ERROR && checkOutputs) { checkForDeviceAndOutputChanges(); updateCallAndOutputRouting(); } return res; } Loading Loading @@ -5226,32 +5239,38 @@ void AudioPolicyManager::checkOutputForAttributes(const audio_attributes_t &attr SortedVector<audio_io_handle_t> srcOutputs = getOutputsForDevices(oldDevices, mPreviousOutputs); SortedVector<audio_io_handle_t> dstOutputs = getOutputsForDevices(newDevices, mOutputs); // also take into account external policy-related changes: add all outputs which are // associated with policies in the "before" and "after" output vectors ALOGVV("%s(): policy related outputs", __func__); bool hasDynamicPolicy = false; for (size_t i = 0 ; i < mPreviousOutputs.size() ; i++) { const sp<SwAudioOutputDescriptor> desc = mPreviousOutputs.valueAt(i); if (desc != 0 && desc->mPolicyMix != NULL) { srcOutputs.add(desc->mIoHandle); hasDynamicPolicy = true; ALOGVV(" previous outputs: adding %d", desc->mIoHandle); uint32_t maxLatency = 0; bool invalidate = false; // take into account dynamic audio policies related changes: if a client is now associated // to a different policy mix than at creation time, invalidate corresponding stream for (size_t i = 0; i < mPreviousOutputs.size() && !invalidate; i++) { const sp<SwAudioOutputDescriptor>& desc = mPreviousOutputs.valueAt(i); if (desc->isDuplicated()) { continue; } for (const sp<TrackClientDescriptor>& client : desc->getClientIterable()) { if (mEngine->getProductStrategyForAttributes(client->attributes()) != psId) { continue; } sp<AudioPolicyMix> primaryMix; status_t status = mPolicyMixes.getOutputForAttr(client->attributes(), client->uid(), client->flags(), primaryMix, nullptr); if (status != OK) { continue; } if (client->getPrimaryMix() != primaryMix) { invalidate = true; if (desc->isStrategyActive(psId)) { maxLatency = desc->latency(); } break; } for (size_t i = 0 ; i < mOutputs.size() ; i++) { const sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i); if (desc != 0 && desc->mPolicyMix != NULL) { dstOutputs.add(desc->mIoHandle); hasDynamicPolicy = true; ALOGVV(" new outputs: adding %d", desc->mIoHandle); } } if (srcOutputs != dstOutputs) { if (srcOutputs != dstOutputs || invalidate) { // get maximum latency of all source outputs to determine the minimum mute time guaranteeing // audio from invalidated tracks will be rendered when unmuting uint32_t maxLatency = 0; bool invalidate = hasDynamicPolicy; for (audio_io_handle_t srcOut : srcOutputs) { sp<SwAudioOutputDescriptor> desc = mPreviousOutputs.valueFor(srcOut); if (desc == nullptr) continue; Loading