Audiopolicy: Move AudioPolicyMixCollection in helper function
No functional changes
Test: adb shell audiorecorder --target /data/file.raw
Bug: 111453086
Change-Id: I300450742a3d6f0b22f69a25eeda7800e0a27943
Signed-off-by: Kevin Rocard <krocard@google.com>
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
index 7296c95..e5c7d48 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
@@ -99,6 +99,11 @@
status_t getDevicesForUid(uid_t uid, Vector<AudioDeviceTypeAddr>& devices) const;
void dump(String8 *dst) const;
+
+private:
+ enum class MixMatchStatus { MATCH, NO_MATCH, INVALID_MIX };
+ MixMatchStatus mixMatch(const AudioMix* mix, size_t mixIndex,
+ audio_attributes_t attributes, uid_t uid);
};
} // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
index 2489e76..32c90b1 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
@@ -156,128 +156,144 @@
}
}
-status_t AudioPolicyMixCollection::getOutputForAttr(audio_attributes_t attributes, uid_t uid,
- sp<SwAudioOutputDescriptor> &desc)
+status_t AudioPolicyMixCollection::getOutputForAttr(
+ audio_attributes_t attributes, uid_t uid, sp<SwAudioOutputDescriptor> &desc)
{
ALOGV("getOutputForAttr() querying %zu mixes:", size());
desc = 0;
for (size_t i = 0; i < size(); i++) {
sp<AudioPolicyMix> policyMix = valueAt(i);
+ sp<SwAudioOutputDescriptor> policyDesc = policyMix->getOutput();
+ if (!policyDesc) {
+ ALOGV("Skiping %zu: Mix has no output", i);
+ continue;
+ }
+
AudioMix *mix = policyMix->getMix();
+ switch (mixMatch(mix, i, attributes, uid)) {
+ case MixMatchStatus::INVALID_MIX: return BAD_VALUE; // TODO: Do we really want to abort ?
+ case MixMatchStatus::NO_MATCH: continue; // skip the mix
+ case MixMatchStatus::MATCH:;
+ }
- if (mix->mMixType == MIX_TYPE_PLAYERS) {
- // TODO if adding more player rules (currently only 2), make rule handling "generic"
- // as there is no difference in the treatment of usage- or uid-based rules
- bool hasUsageMatchRules = false;
- bool hasUsageExcludeRules = false;
- bool usageMatchFound = false;
- bool usageExclusionFound = false;
+ desc = policyMix->getOutput();
+ desc->mPolicyMix = mix;
+ return NO_ERROR;
+ }
+ return BAD_VALUE;
+}
- bool hasUidMatchRules = false;
- bool hasUidExcludeRules = false;
- bool uidMatchFound = false;
- bool uidExclusionFound = false;
+AudioPolicyMixCollection::MixMatchStatus AudioPolicyMixCollection::mixMatch(
+ const AudioMix* mix, size_t mixIndex, audio_attributes_t attributes, uid_t uid) {
- bool hasAddrMatch = false;
+ if (mix->mMixType == MIX_TYPE_PLAYERS) {
+ // TODO if adding more player rules (currently only 2), make rule handling "generic"
+ // as there is no difference in the treatment of usage- or uid-based rules
+ bool hasUsageMatchRules = false;
+ bool hasUsageExcludeRules = false;
+ bool usageMatchFound = false;
+ bool usageExclusionFound = false;
- // iterate over all mix criteria to list what rules this mix contains
- for (size_t j = 0; j < mix->mCriteria.size(); j++) {
- ALOGV(" getOutputForAttr: mix %zu: inspecting mix criteria %zu of %zu",
- i, j, mix->mCriteria.size());
+ bool hasUidMatchRules = false;
+ bool hasUidExcludeRules = false;
+ bool uidMatchFound = false;
+ bool uidExclusionFound = false;
- // if there is an address match, prioritize that match
- if (strncmp(attributes.tags, "addr=", strlen("addr=")) == 0 &&
- strncmp(attributes.tags + strlen("addr="),
- mix->mDeviceAddress.string(),
- AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - strlen("addr=") - 1) == 0) {
- hasAddrMatch = true;
- break;
- }
+ bool hasAddrMatch = false;
- switch (mix->mCriteria[j].mRule) {
- case RULE_MATCH_ATTRIBUTE_USAGE:
- ALOGV("\tmix has RULE_MATCH_ATTRIBUTE_USAGE for usage %d",
- mix->mCriteria[j].mValue.mUsage);
- hasUsageMatchRules = true;
- if (mix->mCriteria[j].mValue.mUsage == attributes.usage) {
- // found one match against all allowed usages
- usageMatchFound = true;
- }
- break;
- case RULE_EXCLUDE_ATTRIBUTE_USAGE:
- ALOGV("\tmix has RULE_EXCLUDE_ATTRIBUTE_USAGE for usage %d",
- mix->mCriteria[j].mValue.mUsage);
- hasUsageExcludeRules = true;
- if (mix->mCriteria[j].mValue.mUsage == attributes.usage) {
- // found this usage is to be excluded
- usageExclusionFound = true;
- }
- break;
- case RULE_MATCH_UID:
- ALOGV("\tmix has RULE_MATCH_UID for uid %d", mix->mCriteria[j].mValue.mUid);
- hasUidMatchRules = true;
- if (mix->mCriteria[j].mValue.mUid == uid) {
- // found one UID match against all allowed UIDs
- uidMatchFound = true;
- }
- break;
- case RULE_EXCLUDE_UID:
- ALOGV("\tmix has RULE_EXCLUDE_UID for uid %d", mix->mCriteria[j].mValue.mUid);
- hasUidExcludeRules = true;
- if (mix->mCriteria[j].mValue.mUid == uid) {
- // found this UID is to be excluded
- uidExclusionFound = true;
- }
- break;
- default:
- break;
- }
+ // iterate over all mix criteria to list what rules this mix contains
+ for (size_t j = 0; j < mix->mCriteria.size(); j++) {
+ ALOGV(" getOutputForAttr: mix %zu: inspecting mix criteria %zu of %zu",
+ mixIndex, j, mix->mCriteria.size());
- // consistency checks: for each "dimension" of rules (usage, uid...), we can
- // only have MATCH rules, or EXCLUDE rules in each dimension, not a combination
- if (hasUsageMatchRules && hasUsageExcludeRules) {
- ALOGE("getOutputForAttr: invalid combination of RULE_MATCH_ATTRIBUTE_USAGE"
- " and RULE_EXCLUDE_ATTRIBUTE_USAGE in mix %zu", i);
- return BAD_VALUE;
- }
- if (hasUidMatchRules && hasUidExcludeRules) {
- ALOGE("getOutputForAttr: invalid combination of RULE_MATCH_UID"
- " and RULE_EXCLUDE_UID in mix %zu", i);
- return BAD_VALUE;
- }
-
- if ((hasUsageExcludeRules && usageExclusionFound)
- || (hasUidExcludeRules && uidExclusionFound)) {
- break; // stop iterating on criteria because an exclusion was found (will fail)
- }
-
- }//iterate on mix criteria
-
- // determine if exiting on success (or implicit failure as desc is 0)
- if (hasAddrMatch ||
- !((hasUsageExcludeRules && usageExclusionFound) ||
- (hasUsageMatchRules && !usageMatchFound) ||
- (hasUidExcludeRules && uidExclusionFound) ||
- (hasUidMatchRules && !uidMatchFound))) {
- ALOGV("\tgetOutputForAttr will use mix %zu", i);
- desc = policyMix->getOutput();
- }
-
- } else if (mix->mMixType == MIX_TYPE_RECORDERS) {
- if (attributes.usage == AUDIO_USAGE_VIRTUAL_SOURCE &&
- strncmp(attributes.tags, "addr=", strlen("addr=")) == 0 &&
+ // if there is an address match, prioritize that match
+ if (strncmp(attributes.tags, "addr=", strlen("addr=")) == 0 &&
strncmp(attributes.tags + strlen("addr="),
mix->mDeviceAddress.string(),
AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - strlen("addr=") - 1) == 0) {
- desc = policyMix->getOutput();
+ hasAddrMatch = true;
+ break;
}
+
+ switch (mix->mCriteria[j].mRule) {
+ case RULE_MATCH_ATTRIBUTE_USAGE:
+ ALOGV("\tmix has RULE_MATCH_ATTRIBUTE_USAGE for usage %d",
+ mix->mCriteria[j].mValue.mUsage);
+ hasUsageMatchRules = true;
+ if (mix->mCriteria[j].mValue.mUsage == attributes.usage) {
+ // found one match against all allowed usages
+ usageMatchFound = true;
+ }
+ break;
+ case RULE_EXCLUDE_ATTRIBUTE_USAGE:
+ ALOGV("\tmix has RULE_EXCLUDE_ATTRIBUTE_USAGE for usage %d",
+ mix->mCriteria[j].mValue.mUsage);
+ hasUsageExcludeRules = true;
+ if (mix->mCriteria[j].mValue.mUsage == attributes.usage) {
+ // found this usage is to be excluded
+ usageExclusionFound = true;
+ }
+ break;
+ case RULE_MATCH_UID:
+ ALOGV("\tmix has RULE_MATCH_UID for uid %d", mix->mCriteria[j].mValue.mUid);
+ hasUidMatchRules = true;
+ if (mix->mCriteria[j].mValue.mUid == uid) {
+ // found one UID match against all allowed UIDs
+ uidMatchFound = true;
+ }
+ break;
+ case RULE_EXCLUDE_UID:
+ ALOGV("\tmix has RULE_EXCLUDE_UID for uid %d", mix->mCriteria[j].mValue.mUid);
+ hasUidExcludeRules = true;
+ if (mix->mCriteria[j].mValue.mUid == uid) {
+ // found this UID is to be excluded
+ uidExclusionFound = true;
+ }
+ break;
+ default:
+ break;
+ }
+
+ // consistency checks: for each "dimension" of rules (usage, uid...), we can
+ // only have MATCH rules, or EXCLUDE rules in each dimension, not a combination
+ if (hasUsageMatchRules && hasUsageExcludeRules) {
+ ALOGE("getOutputForAttr: invalid combination of RULE_MATCH_ATTRIBUTE_USAGE"
+ " and RULE_EXCLUDE_ATTRIBUTE_USAGE in mix %zu", mixIndex);
+ return MixMatchStatus::INVALID_MIX;
+ }
+ if (hasUidMatchRules && hasUidExcludeRules) {
+ ALOGE("getOutputForAttr: invalid combination of RULE_MATCH_UID"
+ " and RULE_EXCLUDE_UID in mix %zu", mixIndex);
+ return MixMatchStatus::INVALID_MIX;
+ }
+
+ if ((hasUsageExcludeRules && usageExclusionFound)
+ || (hasUidExcludeRules && uidExclusionFound)) {
+ break; // stop iterating on criteria because an exclusion was found (will fail)
+ }
+
+ }//iterate on mix criteria
+
+ // determine if exiting on success (or implicit failure as desc is 0)
+ if (hasAddrMatch ||
+ !((hasUsageExcludeRules && usageExclusionFound) ||
+ (hasUsageMatchRules && !usageMatchFound) ||
+ (hasUidExcludeRules && uidExclusionFound) ||
+ (hasUidMatchRules && !uidMatchFound))) {
+ ALOGV("\tgetOutputForAttr will use mix %zu", mixIndex);
+ return MixMatchStatus::MATCH;
}
- if (desc != 0) {
- desc->mPolicyMix = mix;
- return NO_ERROR;
+
+ } else if (mix->mMixType == MIX_TYPE_RECORDERS) {
+ if (attributes.usage == AUDIO_USAGE_VIRTUAL_SOURCE &&
+ strncmp(attributes.tags, "addr=", strlen("addr=")) == 0 &&
+ strncmp(attributes.tags + strlen("addr="),
+ mix->mDeviceAddress.string(),
+ AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - strlen("addr=") - 1) == 0) {
+ return MixMatchStatus::MATCH;
}
}
- return BAD_VALUE;
+ return MixMatchStatus::NO_MATCH;
}
sp<DeviceDescriptor> AudioPolicyMixCollection::getDeviceAndMixForOutput(