Support connecting multiple devices to APM.

When connecting multiple devices with the same type to APM, APM will
need to support enumerating capabilities of the device. When a device is
connected/disconnected, the active devices may be updated. If an output
supports the active devices and dynamic profiles, it will be reopened to
query to dynamic profiles.

Test: atest AudioTrackTest AudioRecordTest AudioManagerTest
Test: atest AudioPlaybackCaptureTest audiopolicy_tests
Test: audio smoke test
Bug: 160352965
Change-Id: I52577ae26dd4073673025fe3286a58c047a35965
diff --git a/media/libaudiofoundation/AudioProfile.cpp b/media/libaudiofoundation/AudioProfile.cpp
index 3b47fed..65f7388 100644
--- a/media/libaudiofoundation/AudioProfile.cpp
+++ b/media/libaudiofoundation/AudioProfile.cpp
@@ -355,4 +355,31 @@
     return convertContainer<std::vector<media::AudioProfile>>(legacy, legacy2aidl_AudioProfile);
 }
 
+AudioProfileVector intersectAudioProfiles(const AudioProfileVector& profiles1,
+                                          const AudioProfileVector& profiles2)
+{
+    std::map<audio_format_t, std::pair<ChannelMaskSet, SampleRateSet>> infos2;
+    for (const auto& profile : profiles2) {
+        infos2.emplace(profile->getFormat(),
+                std::make_pair(profile->getChannels(), profile->getSampleRates()));
+    }
+    AudioProfileVector profiles;
+    for (const auto& profile : profiles1) {
+        const auto it = infos2.find(profile->getFormat());
+        if (it == infos2.end()) {
+            continue;
+        }
+        ChannelMaskSet channelMasks = SetIntersection(profile->getChannels(), it->second.first);
+        if (channelMasks.empty()) {
+            continue;
+        }
+        SampleRateSet sampleRates = SetIntersection(profile->getSampleRates(), it->second.second);
+        if (sampleRates.empty()) {
+            continue;
+        }
+        profiles.push_back(new AudioProfile(profile->getFormat(), channelMasks, sampleRates));
+    }
+    return profiles;
+}
+
 } // namespace android