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
diff --git a/media/libaudiofoundation/include/media/AudioContainers.h b/media/libaudiofoundation/include/media/AudioContainers.h
index aa7ca69..204b365 100644
--- a/media/libaudiofoundation/include/media/AudioContainers.h
+++ b/media/libaudiofoundation/include/media/AudioContainers.h
@@ -50,6 +50,15 @@
return intersection;
}
+template<typename T>
+static std::set<T> SetIntersection(const std::set<T>& a, const std::set<T> b) {
+ std::set<T> intersection;
+ std::set_intersection(a.begin(), a.end(),
+ b.begin(), b.end(),
+ std::inserter(intersection, intersection.begin()));
+ return intersection;
+}
+
static inline ChannelMaskSet asInMask(const ChannelMaskSet& channelMasks) {
ChannelMaskSet inMaskSet;
for (const auto &channel : channelMasks) {
diff --git a/media/libaudiofoundation/include/media/AudioProfile.h b/media/libaudiofoundation/include/media/AudioProfile.h
index 57592bc..5051233 100644
--- a/media/libaudiofoundation/include/media/AudioProfile.h
+++ b/media/libaudiofoundation/include/media/AudioProfile.h
@@ -137,5 +137,7 @@
ConversionResult<std::vector<media::AudioProfile>>
legacy2aidl_AudioProfileVector(const AudioProfileVector& legacy);
+AudioProfileVector intersectAudioProfiles(const AudioProfileVector& profiles1,
+ const AudioProfileVector& profiles2);
} // namespace android