Audio policy: uid device affinity deterministic rule

When setting a uid device affinity, make the rules deterministic
  by applying an "exclude" rule on all mixes that don't reach
  the devices (existing), but also a "match" on the mixes that
  do (new).
Bug: 111647296
Test: requires device with routing policy started by CarService

Change-Id: I3bb844156ade75e4b9576c1e18200ca90ce26cf9
diff --git a/media/libaudioclient/AudioPolicy.cpp b/media/libaudioclient/AudioPolicy.cpp
index 9601d6d..3ab38cd 100644
--- a/media/libaudioclient/AudioPolicy.cpp
+++ b/media/libaudioclient/AudioPolicy.cpp
@@ -143,11 +143,18 @@
     return NO_ERROR;
 }
 
-void AudioMix::excludeUid(uid_t uid) const {
+void AudioMix::setExcludeUid(uid_t uid) const {
     AudioMixMatchCriterion crit;
     crit.mRule = RULE_EXCLUDE_UID;
     crit.mValue.mUid = uid;
     mCriteria.add(crit);
 }
 
+void AudioMix::setMatchUid(uid_t uid) const {
+    AudioMixMatchCriterion crit;
+    crit.mRule = RULE_MATCH_UID;
+    crit.mValue.mUid = uid;
+    mCriteria.add(crit);
+}
+
 } // namespace android
diff --git a/media/libaudioclient/include/media/AudioPolicy.h b/media/libaudioclient/include/media/AudioPolicy.h
index 96e1235..786fb9a 100644
--- a/media/libaudioclient/include/media/AudioPolicy.h
+++ b/media/libaudioclient/include/media/AudioPolicy.h
@@ -100,7 +100,8 @@
     status_t readFromParcel(Parcel *parcel);
     status_t writeToParcel(Parcel *parcel) const;
 
-    void excludeUid(uid_t uid) const;
+    void setExcludeUid(uid_t uid) const;
+    void setMatchUid(uid_t uid) const;
 
     mutable Vector<AudioMixMatchCriterion> mCriteria;
     uint32_t        mMixType;
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
index 776d98f..4d0916e 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
@@ -360,10 +360,12 @@
                 break;
             }
         }
-        if (!deviceMatch) {
+        if (deviceMatch) {
+            mix->setMatchUid(uid);
+        } else {
             // this mix doesn't go to one of the listed devices for the given uid,
             // modify its rules to exclude the uid
-            mix->excludeUid(uid);
+            mix->setExcludeUid(uid);
         }
     }
 
@@ -382,7 +384,7 @@
         for (size_t j = 0; j < mix->mCriteria.size(); j++) {
             const uint32_t rule = mix->mCriteria[j].mRule;
             // is this rule affecting the uid?
-            if (rule == RULE_EXCLUDE_UID
+            if ((rule == RULE_EXCLUDE_UID || rule == RULE_MATCH_UID)
                     && uid == mix->mCriteria[j].mValue.mUid) {
                 foundUidRule = true;
                 criteriaToRemove.push_back(j);