Loading media/libaudioclient/AudioPolicy.cpp +3 −2 Original line number Diff line number Diff line Loading @@ -203,9 +203,10 @@ bool AudioMix::hasUserIdRule(bool match, int userId) const { return false; } bool AudioMix::hasMatchUserIdRule() const { bool AudioMix::hasUserIdRule(bool match) const { const uint32_t rule = match ? RULE_MATCH_USERID : RULE_EXCLUDE_USERID; for (size_t i = 0; i < mCriteria.size(); i++) { if (mCriteria[i].mRule == RULE_MATCH_USERID) { if (mCriteria[i].mRule == rule) { return true; } } Loading media/libaudioclient/include/media/AudioPolicy.h +12 −4 Original line number Diff line number Diff line Loading @@ -61,7 +61,10 @@ namespace android { #define MIX_ROUTE_FLAG_LOOP_BACK (0x1 << 1) /** Loop back some audio while it is rendered */ #define MIX_ROUTE_FLAG_LOOP_BACK_AND_RENDER (MIX_ROUTE_FLAG_RENDER | MIX_ROUTE_FLAG_LOOP_BACK) #define MIX_ROUTE_FLAG_ALL (MIX_ROUTE_FLAG_RENDER | MIX_ROUTE_FLAG_LOOP_BACK) /** Control if audio routing disallows preferred device routing **/ #define MIX_ROUTE_FLAG_DISALLOWS_PREFERRED_DEVICE (0x1 << 2) #define MIX_ROUTE_FLAG_ALL (MIX_ROUTE_FLAG_RENDER | MIX_ROUTE_FLAG_LOOP_BACK | \ MIX_ROUTE_FLAG_DISALLOWS_PREFERRED_DEVICE) #define MAX_MIXES_PER_POLICY 10 #define MAX_CRITERIA_PER_MIX 20 Loading Loading @@ -112,9 +115,9 @@ public: void setMatchUserId(int userId); /** returns true if this mix has a rule to match or exclude the given userId */ bool hasUserIdRule(bool match, int userId) const; /** returns true if this mix has a rule for userId match (any userId) */ bool hasMatchUserIdRule() const; /** returns true if this mix can be used for uid-device affinity routing */ /** returns true if this mix has a rule to match or exclude (any userId) */ bool hasUserIdRule(bool match) const; /** returns true if this mix has a rule for userId exclude (any userId) */ bool isDeviceAffinityCompatible() const; std::vector<AudioMixMatchCriterion> mCriteria; Loading Loading @@ -147,6 +150,11 @@ static inline bool is_mix_loopback(uint32_t routeFlags) { == MIX_ROUTE_FLAG_LOOP_BACK; } static inline bool is_mix_disallows_preferred_device(uint32_t routeFlags) { return (routeFlags & MIX_ROUTE_FLAG_DISALLOWS_PREFERRED_DEVICE) == MIX_ROUTE_FLAG_DISALLOWS_PREFERRED_DEVICE; } }; // namespace android #endif // ANDROID_AUDIO_POLICY_H services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h +28 −5 Original line number Diff line number Diff line Loading @@ -62,11 +62,24 @@ public: void closeOutput(sp<SwAudioOutputDescriptor> &desc); /** * Try to find an output descriptor for the given attributes. * Tries to find the best matching audio policy mix * * @param[in] attributes to consider for the research of the audio policy mix. * @param[in] config to consider for the research of the audio policy mix. * @param[in] uid to consider for the research of the audio policy mix. * @param[in] session to consider for the research of the audio policy mix. * @param[in] flags to consider for the research of the audio policy mix. * @param[in] availableOutputDevices available output devices can be use during the research * of the audio policy mix * @param[in] requestedDevice currently requested device that can be used determined if the * matching audio policy mix should be used instead of the currently set preferred device. * @param[out] primaryMix to return in case a matching audio plicy mix could be found. * @param[out] secondaryMixes that audio should be routed to in case a matching * secondary mixes could be found. * @param[out] usePrimaryOutputFromPolicyMixes to return in case the audio policy mix * should be use, including the case where the requested device is explicitly disallowed * by the audio policy. * * @param[in] attributes to consider fowr the research of output descriptor. * @param[out] desc to return if an primary output could be found. * @param[out] secondaryDesc other desc that the audio should be routed to. * @return OK if the request is valid * otherwise if the request is not supported */ Loading @@ -75,8 +88,11 @@ public: uid_t uid, audio_session_t session, audio_output_flags_t flags, const DeviceVector &availableOutputDevices, const sp<DeviceDescriptor>& requestedDevice, sp<AudioPolicyMix> &primaryMix, std::vector<sp<AudioPolicyMix>> *secondaryMixes); std::vector<sp<AudioPolicyMix>> *secondaryMixes, bool& usePrimaryOutputFromPolicyMixes); sp<DeviceDescriptor> getDeviceAndMixForInputSource(const audio_attributes_t& attributes, const DeviceVector &availableDeviceTypes, Loading Loading @@ -132,6 +148,13 @@ private: const audio_config_base_t& config, uid_t uid, audio_session_t session); bool mixDisallowsRequestedDevice(const AudioMix* mix, const sp<DeviceDescriptor>& requestedDevice, const sp<DeviceDescriptor>& mixDevice, const uid_t uid); sp<DeviceDescriptor> getOutputDeviceForMix(const AudioMix* mix, const DeviceVector& availableOutputDevices); }; std::optional<std::string> extractAddressFromAudioAttributes(const audio_attributes_t& attr); Loading services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp +53 −9 Original line number Diff line number Diff line Loading @@ -259,14 +259,25 @@ status_t AudioPolicyMixCollection::getOutputForAttr( const audio_attributes_t& attributes, const audio_config_base_t& config, const uid_t uid, const audio_session_t session, audio_output_flags_t flags, const DeviceVector &availableOutputDevices, const sp<DeviceDescriptor>& requestedDevice, sp<AudioPolicyMix> &primaryMix, std::vector<sp<AudioPolicyMix>> *secondaryMixes) std::vector<sp<AudioPolicyMix>> *secondaryMixes, bool& usePrimaryOutputFromPolicyMixes) { ALOGV("getOutputForAttr() querying %zu mixes:", size()); primaryMix.clear(); bool mixesDisallowsRequestedDevice = false; for (size_t i = 0; i < size(); i++) { sp<AudioPolicyMix> policyMix = itemAt(i); const bool primaryOutputMix = !is_mix_loopback_render(policyMix->mRouteFlags); sp<DeviceDescriptor> mixDevice = getOutputDeviceForMix(policyMix.get(), availableOutputDevices); if (mixDisallowsRequestedDevice(policyMix.get(), requestedDevice, mixDevice, uid)) { ALOGV("%s: Mix %zu: does not allows device", __func__, i); mixesDisallowsRequestedDevice = true; } if (!primaryOutputMix && (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ)) { // AAudio does not support MMAP_NO_IRQ loopback render, and there is no way with // the current MmapStreamInterface::start to reject a specific client added to a shared Loading @@ -288,6 +299,11 @@ status_t AudioPolicyMixCollection::getOutputForAttr( continue; // skip the mix } if (mixDevice != nullptr && mixDevice->equals(requestedDevice)) { ALOGV("%s: Mix %zu: requested device mathches", __func__, i); mixesDisallowsRequestedDevice = false; } if (primaryOutputMix) { primaryMix = policyMix; ALOGV("%s: Mix %zu: set primary desc", __func__, i); Loading @@ -298,9 +314,36 @@ status_t AudioPolicyMixCollection::getOutputForAttr( } } } // Explicit routing is higher priority than dynamic policy primary output, but policy may // explicitly deny it usePrimaryOutputFromPolicyMixes = (mixesDisallowsRequestedDevice || requestedDevice == nullptr) && primaryMix != nullptr; return NO_ERROR; } sp<DeviceDescriptor> AudioPolicyMixCollection::getOutputDeviceForMix(const AudioMix* mix, const DeviceVector& availableOutputDevices) { ALOGV("%s: device (0x%x, addr=%s) forced by mix", __func__, mix->mDeviceType, mix->mDeviceAddress.c_str()); return availableOutputDevices.getDevice(mix->mDeviceType, mix->mDeviceAddress, AUDIO_FORMAT_DEFAULT); } bool AudioPolicyMixCollection::mixDisallowsRequestedDevice(const AudioMix* mix, const sp<DeviceDescriptor>& requestedDevice, const sp<DeviceDescriptor>& mixDevice, const uid_t uid) { if (requestedDevice == nullptr || mixDevice == nullptr) { return false; } return is_mix_disallows_preferred_device(mix->mRouteFlags) && requestedDevice->equals(mixDevice) && mix->hasUserIdRule(false /* match */, multiuser_get_user_id(uid)); } bool AudioPolicyMixCollection::mixMatch(const AudioMix* mix, size_t mixIndex, const audio_attributes_t& attributes, const audio_config_base_t& config, uid_t uid, audio_session_t session) { Loading Loading @@ -361,11 +404,7 @@ sp<DeviceDescriptor> AudioPolicyMixCollection::getDeviceAndMixForOutput( for (size_t i = 0; i < size(); i++) { if (itemAt(i)->getOutput() == output) { // This Desc is involved in a Mix, which has the highest prio audio_devices_t deviceType = itemAt(i)->mDeviceType; String8 address = itemAt(i)->mDeviceAddress; ALOGV("%s: device (0x%x, addr=%s) forced by mix", __FUNCTION__, deviceType, address.c_str()); return availableOutputDevices.getDevice(deviceType, address, AUDIO_FORMAT_DEFAULT); return getOutputDeviceForMix(itemAt(i).get(), availableOutputDevices); } } return nullptr; Loading Loading @@ -568,13 +607,14 @@ status_t AudioPolicyMixCollection::setUserIdDeviceAffinities(int userId, break; } } if (!deviceMatch && !mix->hasMatchUserIdRule()) { if (!deviceMatch && !mix->hasUserIdRule(true /*match*/)) { // this mix doesn't go to one of the listed devices for the given userId, // and it's not already restricting the mix on a userId, // modify its rules to exclude the userId if (!mix->hasUserIdRule(false /* match */, userId)) { // no need to do it again if userId is already excluded mix->setExcludeUserId(userId); mix->mRouteFlags = mix->mRouteFlags | MIX_ROUTE_FLAG_DISALLOWS_PREFERRED_DEVICE; } } } Loading @@ -595,6 +635,10 @@ status_t AudioPolicyMixCollection::removeUserIdDeviceAffinities(int userId) { EraseCriteriaIf(mix->mCriteria, [userId](const AudioMixMatchCriterion& c) { return c.mRule == RULE_EXCLUDE_USERID && c.mValue.mUserId == userId; }); if (!mix->hasUserIdRule(false /* match */)) { mix->mRouteFlags = mix->mRouteFlags & ~MIX_ROUTE_FLAG_DISALLOWS_PREFERRED_DEVICE; } } return NO_ERROR; } Loading services/audiopolicy/managerdefault/AudioPolicyManager.cpp +16 −8 Original line number Diff line number Diff line Loading @@ -1168,6 +1168,8 @@ status_t AudioPolicyManager::getOutputForAttrInt( ALOGV("%s() attributes=%s stream=%s session %d selectedDeviceId %d", __func__, toString(*resultAttr).c_str(), toString(*stream).c_str(), session, requestedPortId); bool usePrimaryOutputFromPolicyMixes = false; // The primary output is the explicit routing (eg. setPreferredDevice) if specified, // otherwise, fallback to the dynamic policies, if none match, query the engine. // Secondary outputs are always found by dynamic policies as the engine do not support them Loading @@ -1177,14 +1179,12 @@ status_t AudioPolicyManager::getOutputForAttrInt( .format = config->format, }; status = mPolicyMixes.getOutputForAttr(*resultAttr, clientConfig, uid, session, *flags, primaryMix, secondaryMixes); mAvailableOutputDevices, requestedDevice, primaryMix, secondaryMixes, usePrimaryOutputFromPolicyMixes); if (status != OK) { return status; } // Explicit routing is higher priority then any dynamic policy primary output bool usePrimaryOutputFromPolicyMixes = requestedDevice == nullptr && primaryMix != nullptr; // FIXME: in case of RENDER policy, the output capabilities should be checked if ((secondaryMixes != nullptr && !secondaryMixes->empty()) && !audio_is_linear_pcm(config->format)) { Loading Loading @@ -6730,6 +6730,7 @@ void AudioPolicyManager::checkOutputForAttributes(const audio_attributes_t &attr SortedVector<audio_io_handle_t> dstOutputs = getOutputsForDevices(newDevices, mOutputs); uint32_t maxLatency = 0; bool unneededUsePrimaryOutputFromPolicyMixes = false; std::vector<sp<SwAudioOutputDescriptor>> invalidatedOutputs; // 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 Loading @@ -6744,7 +6745,9 @@ void AudioPolicyManager::checkOutputForAttributes(const audio_attributes_t &attr } sp<AudioPolicyMix> primaryMix; status_t status = mPolicyMixes.getOutputForAttr(client->attributes(), client->config(), client->uid(), client->session(), client->flags(), primaryMix, nullptr); client->uid(), client->session(), client->flags(), mAvailableOutputDevices, nullptr /* requestedDevice */, primaryMix, nullptr /* secondaryMixes */, unneededUsePrimaryOutputFromPolicyMixes); if (status != OK) { continue; } Loading Loading @@ -6842,13 +6845,16 @@ void AudioPolicyManager::checkOutputForAllStrategies() void AudioPolicyManager::checkSecondaryOutputs() { PortHandleVector clientsToInvalidate; TrackSecondaryOutputsMap trackSecondaryOutputs; bool unneededUsePrimaryOutputFromPolicyMixes = false; for (size_t i = 0; i < mOutputs.size(); i++) { const sp<SwAudioOutputDescriptor>& outputDescriptor = mOutputs[i]; for (const sp<TrackClientDescriptor>& client : outputDescriptor->getClientIterable()) { sp<AudioPolicyMix> primaryMix; std::vector<sp<AudioPolicyMix>> secondaryMixes; status_t status = mPolicyMixes.getOutputForAttr(client->attributes(), client->config(), client->uid(), client->session(), client->flags(), primaryMix, &secondaryMixes); client->uid(), client->session(), client->flags(), mAvailableOutputDevices, nullptr /* requestedDevice */, primaryMix, &secondaryMixes, unneededUsePrimaryOutputFromPolicyMixes); std::vector<sp<SwAudioOutputDescriptor>> secondaryDescs; for (auto &secondaryMix : secondaryMixes) { sp<SwAudioOutputDescriptor> outputDesc = secondaryMix->getOutput(); Loading Loading @@ -8282,9 +8288,11 @@ status_t AudioPolicyManager::getDevicesForAttributes( // check dynamic policies but only for primary descriptors (secondary not used for audible // audio routing, only used for duplication for playback capture) sp<AudioPolicyMix> policyMix; bool unneededUsePrimaryOutputFromPolicyMixes = false; status_t status = mPolicyMixes.getOutputForAttr(attr, AUDIO_CONFIG_BASE_INITIALIZER, 0 /*uid unknown here*/, AUDIO_SESSION_NONE, AUDIO_OUTPUT_FLAG_NONE, policyMix, nullptr /* secondaryMixes */); 0 /*uid unknown here*/, AUDIO_SESSION_NONE, AUDIO_OUTPUT_FLAG_NONE, mAvailableOutputDevices, nullptr /* requestedDevice */, policyMix, nullptr /* secondaryMixes */, unneededUsePrimaryOutputFromPolicyMixes); if (status != OK) { return status; } Loading Loading
media/libaudioclient/AudioPolicy.cpp +3 −2 Original line number Diff line number Diff line Loading @@ -203,9 +203,10 @@ bool AudioMix::hasUserIdRule(bool match, int userId) const { return false; } bool AudioMix::hasMatchUserIdRule() const { bool AudioMix::hasUserIdRule(bool match) const { const uint32_t rule = match ? RULE_MATCH_USERID : RULE_EXCLUDE_USERID; for (size_t i = 0; i < mCriteria.size(); i++) { if (mCriteria[i].mRule == RULE_MATCH_USERID) { if (mCriteria[i].mRule == rule) { return true; } } Loading
media/libaudioclient/include/media/AudioPolicy.h +12 −4 Original line number Diff line number Diff line Loading @@ -61,7 +61,10 @@ namespace android { #define MIX_ROUTE_FLAG_LOOP_BACK (0x1 << 1) /** Loop back some audio while it is rendered */ #define MIX_ROUTE_FLAG_LOOP_BACK_AND_RENDER (MIX_ROUTE_FLAG_RENDER | MIX_ROUTE_FLAG_LOOP_BACK) #define MIX_ROUTE_FLAG_ALL (MIX_ROUTE_FLAG_RENDER | MIX_ROUTE_FLAG_LOOP_BACK) /** Control if audio routing disallows preferred device routing **/ #define MIX_ROUTE_FLAG_DISALLOWS_PREFERRED_DEVICE (0x1 << 2) #define MIX_ROUTE_FLAG_ALL (MIX_ROUTE_FLAG_RENDER | MIX_ROUTE_FLAG_LOOP_BACK | \ MIX_ROUTE_FLAG_DISALLOWS_PREFERRED_DEVICE) #define MAX_MIXES_PER_POLICY 10 #define MAX_CRITERIA_PER_MIX 20 Loading Loading @@ -112,9 +115,9 @@ public: void setMatchUserId(int userId); /** returns true if this mix has a rule to match or exclude the given userId */ bool hasUserIdRule(bool match, int userId) const; /** returns true if this mix has a rule for userId match (any userId) */ bool hasMatchUserIdRule() const; /** returns true if this mix can be used for uid-device affinity routing */ /** returns true if this mix has a rule to match or exclude (any userId) */ bool hasUserIdRule(bool match) const; /** returns true if this mix has a rule for userId exclude (any userId) */ bool isDeviceAffinityCompatible() const; std::vector<AudioMixMatchCriterion> mCriteria; Loading Loading @@ -147,6 +150,11 @@ static inline bool is_mix_loopback(uint32_t routeFlags) { == MIX_ROUTE_FLAG_LOOP_BACK; } static inline bool is_mix_disallows_preferred_device(uint32_t routeFlags) { return (routeFlags & MIX_ROUTE_FLAG_DISALLOWS_PREFERRED_DEVICE) == MIX_ROUTE_FLAG_DISALLOWS_PREFERRED_DEVICE; } }; // namespace android #endif // ANDROID_AUDIO_POLICY_H
services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h +28 −5 Original line number Diff line number Diff line Loading @@ -62,11 +62,24 @@ public: void closeOutput(sp<SwAudioOutputDescriptor> &desc); /** * Try to find an output descriptor for the given attributes. * Tries to find the best matching audio policy mix * * @param[in] attributes to consider for the research of the audio policy mix. * @param[in] config to consider for the research of the audio policy mix. * @param[in] uid to consider for the research of the audio policy mix. * @param[in] session to consider for the research of the audio policy mix. * @param[in] flags to consider for the research of the audio policy mix. * @param[in] availableOutputDevices available output devices can be use during the research * of the audio policy mix * @param[in] requestedDevice currently requested device that can be used determined if the * matching audio policy mix should be used instead of the currently set preferred device. * @param[out] primaryMix to return in case a matching audio plicy mix could be found. * @param[out] secondaryMixes that audio should be routed to in case a matching * secondary mixes could be found. * @param[out] usePrimaryOutputFromPolicyMixes to return in case the audio policy mix * should be use, including the case where the requested device is explicitly disallowed * by the audio policy. * * @param[in] attributes to consider fowr the research of output descriptor. * @param[out] desc to return if an primary output could be found. * @param[out] secondaryDesc other desc that the audio should be routed to. * @return OK if the request is valid * otherwise if the request is not supported */ Loading @@ -75,8 +88,11 @@ public: uid_t uid, audio_session_t session, audio_output_flags_t flags, const DeviceVector &availableOutputDevices, const sp<DeviceDescriptor>& requestedDevice, sp<AudioPolicyMix> &primaryMix, std::vector<sp<AudioPolicyMix>> *secondaryMixes); std::vector<sp<AudioPolicyMix>> *secondaryMixes, bool& usePrimaryOutputFromPolicyMixes); sp<DeviceDescriptor> getDeviceAndMixForInputSource(const audio_attributes_t& attributes, const DeviceVector &availableDeviceTypes, Loading Loading @@ -132,6 +148,13 @@ private: const audio_config_base_t& config, uid_t uid, audio_session_t session); bool mixDisallowsRequestedDevice(const AudioMix* mix, const sp<DeviceDescriptor>& requestedDevice, const sp<DeviceDescriptor>& mixDevice, const uid_t uid); sp<DeviceDescriptor> getOutputDeviceForMix(const AudioMix* mix, const DeviceVector& availableOutputDevices); }; std::optional<std::string> extractAddressFromAudioAttributes(const audio_attributes_t& attr); Loading
services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp +53 −9 Original line number Diff line number Diff line Loading @@ -259,14 +259,25 @@ status_t AudioPolicyMixCollection::getOutputForAttr( const audio_attributes_t& attributes, const audio_config_base_t& config, const uid_t uid, const audio_session_t session, audio_output_flags_t flags, const DeviceVector &availableOutputDevices, const sp<DeviceDescriptor>& requestedDevice, sp<AudioPolicyMix> &primaryMix, std::vector<sp<AudioPolicyMix>> *secondaryMixes) std::vector<sp<AudioPolicyMix>> *secondaryMixes, bool& usePrimaryOutputFromPolicyMixes) { ALOGV("getOutputForAttr() querying %zu mixes:", size()); primaryMix.clear(); bool mixesDisallowsRequestedDevice = false; for (size_t i = 0; i < size(); i++) { sp<AudioPolicyMix> policyMix = itemAt(i); const bool primaryOutputMix = !is_mix_loopback_render(policyMix->mRouteFlags); sp<DeviceDescriptor> mixDevice = getOutputDeviceForMix(policyMix.get(), availableOutputDevices); if (mixDisallowsRequestedDevice(policyMix.get(), requestedDevice, mixDevice, uid)) { ALOGV("%s: Mix %zu: does not allows device", __func__, i); mixesDisallowsRequestedDevice = true; } if (!primaryOutputMix && (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ)) { // AAudio does not support MMAP_NO_IRQ loopback render, and there is no way with // the current MmapStreamInterface::start to reject a specific client added to a shared Loading @@ -288,6 +299,11 @@ status_t AudioPolicyMixCollection::getOutputForAttr( continue; // skip the mix } if (mixDevice != nullptr && mixDevice->equals(requestedDevice)) { ALOGV("%s: Mix %zu: requested device mathches", __func__, i); mixesDisallowsRequestedDevice = false; } if (primaryOutputMix) { primaryMix = policyMix; ALOGV("%s: Mix %zu: set primary desc", __func__, i); Loading @@ -298,9 +314,36 @@ status_t AudioPolicyMixCollection::getOutputForAttr( } } } // Explicit routing is higher priority than dynamic policy primary output, but policy may // explicitly deny it usePrimaryOutputFromPolicyMixes = (mixesDisallowsRequestedDevice || requestedDevice == nullptr) && primaryMix != nullptr; return NO_ERROR; } sp<DeviceDescriptor> AudioPolicyMixCollection::getOutputDeviceForMix(const AudioMix* mix, const DeviceVector& availableOutputDevices) { ALOGV("%s: device (0x%x, addr=%s) forced by mix", __func__, mix->mDeviceType, mix->mDeviceAddress.c_str()); return availableOutputDevices.getDevice(mix->mDeviceType, mix->mDeviceAddress, AUDIO_FORMAT_DEFAULT); } bool AudioPolicyMixCollection::mixDisallowsRequestedDevice(const AudioMix* mix, const sp<DeviceDescriptor>& requestedDevice, const sp<DeviceDescriptor>& mixDevice, const uid_t uid) { if (requestedDevice == nullptr || mixDevice == nullptr) { return false; } return is_mix_disallows_preferred_device(mix->mRouteFlags) && requestedDevice->equals(mixDevice) && mix->hasUserIdRule(false /* match */, multiuser_get_user_id(uid)); } bool AudioPolicyMixCollection::mixMatch(const AudioMix* mix, size_t mixIndex, const audio_attributes_t& attributes, const audio_config_base_t& config, uid_t uid, audio_session_t session) { Loading Loading @@ -361,11 +404,7 @@ sp<DeviceDescriptor> AudioPolicyMixCollection::getDeviceAndMixForOutput( for (size_t i = 0; i < size(); i++) { if (itemAt(i)->getOutput() == output) { // This Desc is involved in a Mix, which has the highest prio audio_devices_t deviceType = itemAt(i)->mDeviceType; String8 address = itemAt(i)->mDeviceAddress; ALOGV("%s: device (0x%x, addr=%s) forced by mix", __FUNCTION__, deviceType, address.c_str()); return availableOutputDevices.getDevice(deviceType, address, AUDIO_FORMAT_DEFAULT); return getOutputDeviceForMix(itemAt(i).get(), availableOutputDevices); } } return nullptr; Loading Loading @@ -568,13 +607,14 @@ status_t AudioPolicyMixCollection::setUserIdDeviceAffinities(int userId, break; } } if (!deviceMatch && !mix->hasMatchUserIdRule()) { if (!deviceMatch && !mix->hasUserIdRule(true /*match*/)) { // this mix doesn't go to one of the listed devices for the given userId, // and it's not already restricting the mix on a userId, // modify its rules to exclude the userId if (!mix->hasUserIdRule(false /* match */, userId)) { // no need to do it again if userId is already excluded mix->setExcludeUserId(userId); mix->mRouteFlags = mix->mRouteFlags | MIX_ROUTE_FLAG_DISALLOWS_PREFERRED_DEVICE; } } } Loading @@ -595,6 +635,10 @@ status_t AudioPolicyMixCollection::removeUserIdDeviceAffinities(int userId) { EraseCriteriaIf(mix->mCriteria, [userId](const AudioMixMatchCriterion& c) { return c.mRule == RULE_EXCLUDE_USERID && c.mValue.mUserId == userId; }); if (!mix->hasUserIdRule(false /* match */)) { mix->mRouteFlags = mix->mRouteFlags & ~MIX_ROUTE_FLAG_DISALLOWS_PREFERRED_DEVICE; } } return NO_ERROR; } Loading
services/audiopolicy/managerdefault/AudioPolicyManager.cpp +16 −8 Original line number Diff line number Diff line Loading @@ -1168,6 +1168,8 @@ status_t AudioPolicyManager::getOutputForAttrInt( ALOGV("%s() attributes=%s stream=%s session %d selectedDeviceId %d", __func__, toString(*resultAttr).c_str(), toString(*stream).c_str(), session, requestedPortId); bool usePrimaryOutputFromPolicyMixes = false; // The primary output is the explicit routing (eg. setPreferredDevice) if specified, // otherwise, fallback to the dynamic policies, if none match, query the engine. // Secondary outputs are always found by dynamic policies as the engine do not support them Loading @@ -1177,14 +1179,12 @@ status_t AudioPolicyManager::getOutputForAttrInt( .format = config->format, }; status = mPolicyMixes.getOutputForAttr(*resultAttr, clientConfig, uid, session, *flags, primaryMix, secondaryMixes); mAvailableOutputDevices, requestedDevice, primaryMix, secondaryMixes, usePrimaryOutputFromPolicyMixes); if (status != OK) { return status; } // Explicit routing is higher priority then any dynamic policy primary output bool usePrimaryOutputFromPolicyMixes = requestedDevice == nullptr && primaryMix != nullptr; // FIXME: in case of RENDER policy, the output capabilities should be checked if ((secondaryMixes != nullptr && !secondaryMixes->empty()) && !audio_is_linear_pcm(config->format)) { Loading Loading @@ -6730,6 +6730,7 @@ void AudioPolicyManager::checkOutputForAttributes(const audio_attributes_t &attr SortedVector<audio_io_handle_t> dstOutputs = getOutputsForDevices(newDevices, mOutputs); uint32_t maxLatency = 0; bool unneededUsePrimaryOutputFromPolicyMixes = false; std::vector<sp<SwAudioOutputDescriptor>> invalidatedOutputs; // 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 Loading @@ -6744,7 +6745,9 @@ void AudioPolicyManager::checkOutputForAttributes(const audio_attributes_t &attr } sp<AudioPolicyMix> primaryMix; status_t status = mPolicyMixes.getOutputForAttr(client->attributes(), client->config(), client->uid(), client->session(), client->flags(), primaryMix, nullptr); client->uid(), client->session(), client->flags(), mAvailableOutputDevices, nullptr /* requestedDevice */, primaryMix, nullptr /* secondaryMixes */, unneededUsePrimaryOutputFromPolicyMixes); if (status != OK) { continue; } Loading Loading @@ -6842,13 +6845,16 @@ void AudioPolicyManager::checkOutputForAllStrategies() void AudioPolicyManager::checkSecondaryOutputs() { PortHandleVector clientsToInvalidate; TrackSecondaryOutputsMap trackSecondaryOutputs; bool unneededUsePrimaryOutputFromPolicyMixes = false; for (size_t i = 0; i < mOutputs.size(); i++) { const sp<SwAudioOutputDescriptor>& outputDescriptor = mOutputs[i]; for (const sp<TrackClientDescriptor>& client : outputDescriptor->getClientIterable()) { sp<AudioPolicyMix> primaryMix; std::vector<sp<AudioPolicyMix>> secondaryMixes; status_t status = mPolicyMixes.getOutputForAttr(client->attributes(), client->config(), client->uid(), client->session(), client->flags(), primaryMix, &secondaryMixes); client->uid(), client->session(), client->flags(), mAvailableOutputDevices, nullptr /* requestedDevice */, primaryMix, &secondaryMixes, unneededUsePrimaryOutputFromPolicyMixes); std::vector<sp<SwAudioOutputDescriptor>> secondaryDescs; for (auto &secondaryMix : secondaryMixes) { sp<SwAudioOutputDescriptor> outputDesc = secondaryMix->getOutput(); Loading Loading @@ -8282,9 +8288,11 @@ status_t AudioPolicyManager::getDevicesForAttributes( // check dynamic policies but only for primary descriptors (secondary not used for audible // audio routing, only used for duplication for playback capture) sp<AudioPolicyMix> policyMix; bool unneededUsePrimaryOutputFromPolicyMixes = false; status_t status = mPolicyMixes.getOutputForAttr(attr, AUDIO_CONFIG_BASE_INITIALIZER, 0 /*uid unknown here*/, AUDIO_SESSION_NONE, AUDIO_OUTPUT_FLAG_NONE, policyMix, nullptr /* secondaryMixes */); 0 /*uid unknown here*/, AUDIO_SESSION_NONE, AUDIO_OUTPUT_FLAG_NONE, mAvailableOutputDevices, nullptr /* requestedDevice */, policyMix, nullptr /* secondaryMixes */, unneededUsePrimaryOutputFromPolicyMixes); if (status != OK) { return status; } Loading