APM: uid-device affinity: fix for multiple concurrent apps

Audio mix rules that contain both a match and exclude for a uid
  or usage are ignored for routing evaluation. The implementation
  of the uid-device affinity caused uid matches and exclusions to
  be added to any mixes, causing previously valid mixes to be
  discarded in the routing logic.
The fix consists in implementing the uid-device affinity by only
  applying uid exclusions on mixes that:
  a/ are compatible with the concept (mixes of players that are
     render only),
  b/ do not route to the selected devices
  c/ do not have a uid match rule (such mixes are already exclusive
     to the uid to match)
  d/ do not already have a uid exclusion for the uid
Fix removeUidDeviceAffinities() that skipped the wrong mixes.

Bug: 124319394
Bug: 131180578
Test: atest AudioHostTest#testUidDeviceAffinity
Change-Id: I813c4cfb15956e56599740948775c32562266c21
diff --git a/media/libaudioclient/AudioPolicy.cpp b/media/libaudioclient/AudioPolicy.cpp
index 65e797f..3cdf095 100644
--- a/media/libaudioclient/AudioPolicy.cpp
+++ b/media/libaudioclient/AudioPolicy.cpp
@@ -159,4 +159,29 @@
     mCriteria.add(crit);
 }
 
+bool AudioMix::hasUidRule(bool match, uid_t uid) const {
+    const uint32_t rule = match ? RULE_MATCH_UID : RULE_EXCLUDE_UID;
+    for (size_t i = 0; i < mCriteria.size(); i++) {
+        if (mCriteria[i].mRule == rule
+                && mCriteria[i].mValue.mUid == uid) {
+            return true;
+        }
+    }
+    return false;
+}
+
+bool AudioMix::hasMatchUidRule() const {
+    for (size_t i = 0; i < mCriteria.size(); i++) {
+        if (mCriteria[i].mRule == RULE_MATCH_UID) {
+            return true;
+        }
+    }
+    return false;
+}
+
+bool AudioMix::isDeviceAffinityCompatible() const {
+    return ((mMixType == MIX_TYPE_PLAYERS)
+            && (mRouteFlags == MIX_ROUTE_FLAG_RENDER));
+}
+
 } // namespace android