APM: make AudioPolicyMixCollection inherit from Vector

  Modify AudioPolicyMixCollection to inherit from Vector instead
of KeyedVector so all so the collection of mixes stays in the same
order as the mixes were added.
  Also make the mix selection take the deviceType into consideration,
not just the address to enable the same address to be associated to
different devices.

Bug: 131090322
Test: see bug for multi bus scenario
Test: atest AudioPlaybackCaptureTest

Change-Id: I4dc7f23bef19a7d47afc2998102da07dde41fbca
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
index 12b5e7d..094f506 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
@@ -19,7 +19,7 @@
 #include "DeviceDescriptor.h"
 #include <utils/RefBase.h>
 #include <media/AudioPolicy.h>
-#include <utils/KeyedVector.h>
+#include <utils/Vector.h>
 #include <system/audio.h>
 #include <utils/String8.h>
 
@@ -48,14 +48,15 @@
 };
 
 
-class AudioPolicyMixCollection : public DefaultKeyedVector<String8, sp<AudioPolicyMix> >
+class AudioPolicyMixCollection : public Vector<sp<AudioPolicyMix>>
 {
 public:
-    status_t getAudioPolicyMix(const String8& address, sp<AudioPolicyMix> &policyMix) const;
+    status_t getAudioPolicyMix(audio_devices_t deviceType,
+            const String8& address, sp<AudioPolicyMix> &policyMix) const;
 
-    status_t registerMix(const String8& address, AudioMix mix, sp<SwAudioOutputDescriptor> desc);
+    status_t registerMix(AudioMix mix, sp<SwAudioOutputDescriptor> desc);
 
-    status_t unregisterMix(const String8& address);
+    status_t unregisterMix(const AudioMix& mix);
 
     void closeOutput(sp<SwAudioOutputDescriptor> &desc);
 
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
index 98a7800..dca84c0 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
@@ -73,16 +73,21 @@
     }
 }
 
-status_t AudioPolicyMixCollection::registerMix(const String8& address, AudioMix mix,
-                                               sp<SwAudioOutputDescriptor> desc)
+status_t AudioPolicyMixCollection::registerMix(AudioMix mix, sp<SwAudioOutputDescriptor> desc)
 {
-    ssize_t index = indexOfKey(address);
-    if (index >= 0) {
-        ALOGE("registerPolicyMixes(): mix for address %s already registered", address.string());
-        return BAD_VALUE;
+    for (size_t i = 0; i < size(); i++) {
+        const sp<AudioPolicyMix>& registeredMix = itemAt(i);
+        if (mix.mDeviceType == registeredMix->mDeviceType
+                && mix.mDeviceAddress.compare(registeredMix->mDeviceAddress) == 0) {
+            ALOGE("registerMix(): mix already registered for dev=0x%x addr=%s",
+                    mix.mDeviceType, mix.mDeviceAddress.string());
+            return BAD_VALUE;
+        }
     }
     sp<AudioPolicyMix> policyMix = new AudioPolicyMix(mix);
-    add(address, policyMix);
+    add(policyMix);
+    ALOGD("registerMix(): adding mix for dev=0x%x addr=%s",
+            policyMix->mDeviceType, policyMix->mDeviceAddress.string());
 
     if (desc != 0) {
         desc->mPolicyMix = policyMix;
@@ -91,34 +96,48 @@
     return NO_ERROR;
 }
 
-status_t AudioPolicyMixCollection::unregisterMix(const String8& address)
+status_t AudioPolicyMixCollection::unregisterMix(const AudioMix& mix)
 {
-    ssize_t index = indexOfKey(address);
-    if (index < 0) {
-        ALOGE("unregisterPolicyMixes(): mix for address %s not registered", address.string());
-        return BAD_VALUE;
+    for (size_t i = 0; i < size(); i++) {
+        const sp<AudioPolicyMix>& registeredMix = itemAt(i);
+        if (mix.mDeviceType == registeredMix->mDeviceType
+                && mix.mDeviceAddress.compare(registeredMix->mDeviceAddress) == 0) {
+            ALOGD("unregisterMix(): removing mix for dev=0x%x addr=%s",
+                    mix.mDeviceType, mix.mDeviceAddress.string());
+            removeAt(i);
+            return NO_ERROR;
+        }
     }
 
-    removeItemsAt(index);
-    return NO_ERROR;
+    ALOGE("unregisterMix(): mix not registered for dev=0x%x addr=%s",
+            mix.mDeviceType, mix.mDeviceAddress.string());
+    return BAD_VALUE;
 }
 
-status_t AudioPolicyMixCollection::getAudioPolicyMix(const String8& address,
-                                                     sp<AudioPolicyMix> &policyMix) const
+status_t AudioPolicyMixCollection::getAudioPolicyMix(audio_devices_t deviceType,
+        const String8& address, sp<AudioPolicyMix> &policyMix) const
 {
-    ssize_t index = indexOfKey(address);
-    if (index < 0) {
-        ALOGE("unregisterPolicyMixes(): mix for address %s not registered", address.string());
-        return BAD_VALUE;
+
+    ALOGV("getAudioPolicyMix() for dev=0x%x addr=%s", deviceType, address.string());
+    for (ssize_t i = 0; i < size(); i++) {
+        if (itemAt(i)->mDeviceType == deviceType
+                && itemAt(i)->mDeviceAddress.compare(address) == 0) {
+            policyMix = itemAt(i);
+            ALOGV("getAudioPolicyMix: found mix %zu match (devType=0x%x addr=%s)",
+                    i, deviceType, address.string());
+            return NO_ERROR;
+        }
     }
-    policyMix = valueAt(index);
-    return NO_ERROR;
+
+    ALOGE("getAudioPolicyMix(): mix not registered for dev=0x%x addr=%s",
+            deviceType, address.string());
+    return BAD_VALUE;
 }
 
 void AudioPolicyMixCollection::closeOutput(sp<SwAudioOutputDescriptor> &desc)
 {
     for (size_t i = 0; i < size(); i++) {
-        sp<AudioPolicyMix> policyMix = valueAt(i);
+        sp<AudioPolicyMix> policyMix = itemAt(i);
         if (policyMix->getOutput() == desc) {
             policyMix->clearOutput();
         }
@@ -134,7 +153,7 @@
     ALOGV("getOutputForAttr() querying %zu mixes:", size());
     primaryDesc = 0;
     for (size_t i = 0; i < size(); i++) {
-        sp<AudioPolicyMix> policyMix = valueAt(i);
+        sp<AudioPolicyMix> policyMix = itemAt(i);
         const bool primaryOutputMix = !is_mix_loopback_render(policyMix->mRouteFlags);
         if (!primaryOutputMix && (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ)) {
             // AAudio does not support MMAP_NO_IRQ loopback render, and there is no way with
@@ -320,10 +339,10 @@
         const DeviceVector &availableOutputDevices)
 {
     for (size_t i = 0; i < size(); i++) {
-        if (valueAt(i)->getOutput() == output) {
+        if (itemAt(i)->getOutput() == output) {
             // This Desc is involved in a Mix, which has the highest prio
-            audio_devices_t deviceType = valueAt(i)->mDeviceType;
-            String8 address = valueAt(i)->mDeviceAddress;
+            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);
@@ -338,7 +357,7 @@
         sp<AudioPolicyMix> *policyMix) const
 {
     for (size_t i = 0; i < size(); i++) {
-        AudioPolicyMix *mix = valueAt(i).get();
+        AudioPolicyMix *mix = itemAt(i).get();
         if (mix->mMixType != MIX_TYPE_RECORDERS) {
             continue;
         }
@@ -374,19 +393,28 @@
     String8 address(attr.tags + strlen("addr="));
 
 #ifdef LOG_NDEBUG
-    ALOGV("getInputMixForAttr looking for address %s\n  mixes available:", address.string());
+    ALOGV("getInputMixForAttr looking for address %s for source %d\n  mixes available:",
+            address.string(), attr.source);
     for (size_t i = 0; i < size(); i++) {
-            sp<AudioPolicyMix> audioPolicyMix = valueAt(i);
-            ALOGV("\tmix %zu address=%s", i, audioPolicyMix->mDeviceAddress.string());
+        const sp<AudioPolicyMix> audioPolicyMix = itemAt(i);
+        ALOGV("\tmix %zu address=%s", i, audioPolicyMix->mDeviceAddress.string());
     }
 #endif
 
-    ssize_t index = indexOfKey(address);
-    if (index < 0) {
+    size_t index;
+    for (index = 0; index < size(); index++) {
+        const sp<AudioPolicyMix>& registeredMix = itemAt(index);
+        if (registeredMix->mDeviceAddress.compare(address) == 0) {
+            ALOGD("getInputMixForAttr found addr=%s dev=0x%x",
+                    registeredMix->mDeviceAddress.string(), registeredMix->mDeviceType);
+            break;
+        }
+    }
+    if (index == size()) {
         ALOGW("getInputMixForAttr() no policy for address %s", address.string());
         return BAD_VALUE;
     }
-    sp<AudioPolicyMix> audioPolicyMix = valueAt(index);
+    const sp<AudioPolicyMix> audioPolicyMix = itemAt(index);
 
     if (audioPolicyMix->mMixType != MIX_TYPE_PLAYERS) {
         ALOGW("getInputMixForAttr() bad policy mix type for address %s", address.string());
@@ -404,7 +432,7 @@
     //    "match uid" rule for this uid, return an error
     //    (adding a uid-device affinity would result in contradictory rules)
     for (size_t i = 0; i < size(); i++) {
-        const AudioPolicyMix* mix = valueAt(i).get();
+        const AudioPolicyMix* mix = itemAt(i).get();
         if (!mix->isDeviceAffinityCompatible()) {
             continue;
         }
@@ -421,7 +449,7 @@
     //     AND it doesn't have a "match uid" rule
     //   THEN add a rule to exclude the uid
     for (size_t i = 0; i < size(); i++) {
-        const AudioPolicyMix *mix = valueAt(i).get();
+        const AudioPolicyMix *mix = itemAt(i).get();
         if (!mix->isDeviceAffinityCompatible()) {
             continue;
         }
@@ -452,7 +480,7 @@
     // for each player mix: remove existing rules that match or exclude this uid
     for (size_t i = 0; i < size(); i++) {
         bool foundUidRule = false;
-        const AudioPolicyMix *mix = valueAt(i).get();
+        const AudioPolicyMix *mix = itemAt(i).get();
         if (!mix->isDeviceAffinityCompatible()) {
             continue;
         }
@@ -481,7 +509,7 @@
     // for each player mix: find rules that don't exclude this uid, and add the device to the list
     for (size_t i = 0; i < size(); i++) {
         bool ruleAllowsUid = true;
-        const AudioPolicyMix *mix = valueAt(i).get();
+        const AudioPolicyMix *mix = itemAt(i).get();
         if (mix->mMixType != MIX_TYPE_PLAYERS) {
             continue;
         }
@@ -504,7 +532,7 @@
 {
     dst->append("\nAudio Policy Mix:\n");
     for (size_t i = 0; i < size(); i++) {
-        valueAt(i)->dump(dst, 2, i);
+        itemAt(i)->dump(dst, 2, i);
     }
 }
 
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 9025119..3ca7591 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -2868,13 +2868,16 @@
             }
 
             String8 address = mix.mDeviceAddress;
+            audio_devices_t deviceTypeToMakeAvailable;
             if (mix.mMixType == MIX_TYPE_PLAYERS) {
-                mix.mDeviceType = AUDIO_DEVICE_IN_REMOTE_SUBMIX;
-            } else {
                 mix.mDeviceType = AUDIO_DEVICE_OUT_REMOTE_SUBMIX;
+                deviceTypeToMakeAvailable = AUDIO_DEVICE_IN_REMOTE_SUBMIX;
+            } else {
+                mix.mDeviceType = AUDIO_DEVICE_IN_REMOTE_SUBMIX;
+                deviceTypeToMakeAvailable = AUDIO_DEVICE_OUT_REMOTE_SUBMIX;
             }
 
-            if (mPolicyMixes.registerMix(address, mix, 0 /*output desc*/) != NO_ERROR) {
+            if (mPolicyMixes.registerMix(mix, 0 /*output desc*/) != NO_ERROR) {
                 ALOGE("Error registering mix %zu for address %s", i, address.string());
                 res = INVALID_OPERATION;
                 break;
@@ -2890,7 +2893,7 @@
             rSubmixModule->addInputProfile(address, &inputConfig,
                     AUDIO_DEVICE_IN_REMOTE_SUBMIX, address);
 
-            if ((res = setDeviceConnectionStateInt(mix.mDeviceType,
+            if ((res = setDeviceConnectionStateInt(deviceTypeToMakeAvailable,
                     AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
                     address.string(), "remote-submix", AUDIO_FORMAT_DEFAULT)) != NO_ERROR) {
                 ALOGE("Failed to set remote submix device available, type %u, address %s",
@@ -2916,7 +2919,7 @@
                 sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(j);
 
                 if (desc->supportedDevices().contains(device)) {
-                    if (mPolicyMixes.registerMix(address, mix, desc) != NO_ERROR) {
+                    if (mPolicyMixes.registerMix(mix, desc) != NO_ERROR) {
                         ALOGE("Could not register mix RENDER,  dev=0x%X addr=%s", type,
                               address.string());
                         res = INVALID_OPERATION;
@@ -2966,7 +2969,7 @@
 
             String8 address = mix.mDeviceAddress;
 
-            if (mPolicyMixes.unregisterMix(address) != NO_ERROR) {
+            if (mPolicyMixes.unregisterMix(mix) != NO_ERROR) {
                 res = INVALID_OPERATION;
                 continue;
             }
@@ -2987,7 +2990,7 @@
             rSubmixModule->removeInputProfile(address);
 
         } else if ((mix.mRouteFlags & MIX_ROUTE_FLAG_RENDER) == MIX_ROUTE_FLAG_RENDER) {
-            if (mPolicyMixes.unregisterMix(mix.mDeviceAddress) != NO_ERROR) {
+            if (mPolicyMixes.unregisterMix(mix) != NO_ERROR) {
                 res = INVALID_OPERATION;
                 continue;
             }
@@ -4653,7 +4656,8 @@
                     addOutput(output, desc);
                     if (device_distinguishes_on_address(deviceType) && address != "0") {
                         sp<AudioPolicyMix> policyMix;
-                        if (mPolicyMixes.getAudioPolicyMix(address, policyMix) == NO_ERROR) {
+                        if (mPolicyMixes.getAudioPolicyMix(deviceType, address, policyMix)
+                                == NO_ERROR) {
                             policyMix->setOutput(desc);
                             desc->mPolicyMix = policyMix;
                         } else {