xref: /aosp_15_r20/hardware/interfaces/audio/aidl/vts/ModuleConfig.cpp (revision 4d7e907c777eeecc4c5bd7cf640a754fac206ff7)
1*4d7e907cSAndroid Build Coastguard Worker /*
2*4d7e907cSAndroid Build Coastguard Worker  * Copyright (C) 2022 The Android Open Source Project
3*4d7e907cSAndroid Build Coastguard Worker  *
4*4d7e907cSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*4d7e907cSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*4d7e907cSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*4d7e907cSAndroid Build Coastguard Worker  *
8*4d7e907cSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*4d7e907cSAndroid Build Coastguard Worker  *
10*4d7e907cSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*4d7e907cSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*4d7e907cSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*4d7e907cSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*4d7e907cSAndroid Build Coastguard Worker  * limitations under the License.
15*4d7e907cSAndroid Build Coastguard Worker  */
16*4d7e907cSAndroid Build Coastguard Worker 
17*4d7e907cSAndroid Build Coastguard Worker #include <algorithm>
18*4d7e907cSAndroid Build Coastguard Worker #include <chrono>
19*4d7e907cSAndroid Build Coastguard Worker 
20*4d7e907cSAndroid Build Coastguard Worker #define LOG_TAG "VtsHalAudio.ModuleConfig"
21*4d7e907cSAndroid Build Coastguard Worker #include <android-base/logging.h>
22*4d7e907cSAndroid Build Coastguard Worker 
23*4d7e907cSAndroid Build Coastguard Worker #include <Utils.h>
24*4d7e907cSAndroid Build Coastguard Worker #include <aidl/android/media/audio/common/AudioInputFlags.h>
25*4d7e907cSAndroid Build Coastguard Worker #include <aidl/android/media/audio/common/AudioIoFlags.h>
26*4d7e907cSAndroid Build Coastguard Worker #include <aidl/android/media/audio/common/AudioOutputFlags.h>
27*4d7e907cSAndroid Build Coastguard Worker #include <error/expected_utils.h>
28*4d7e907cSAndroid Build Coastguard Worker 
29*4d7e907cSAndroid Build Coastguard Worker #include "ModuleConfig.h"
30*4d7e907cSAndroid Build Coastguard Worker 
31*4d7e907cSAndroid Build Coastguard Worker using namespace android;
32*4d7e907cSAndroid Build Coastguard Worker using namespace std::chrono_literals;
33*4d7e907cSAndroid Build Coastguard Worker 
34*4d7e907cSAndroid Build Coastguard Worker using aidl::android::hardware::audio::common::isBitPositionFlagSet;
35*4d7e907cSAndroid Build Coastguard Worker using aidl::android::hardware::audio::core::IModule;
36*4d7e907cSAndroid Build Coastguard Worker using aidl::android::media::audio::common::AudioChannelLayout;
37*4d7e907cSAndroid Build Coastguard Worker using aidl::android::media::audio::common::AudioDeviceDescription;
38*4d7e907cSAndroid Build Coastguard Worker using aidl::android::media::audio::common::AudioDeviceType;
39*4d7e907cSAndroid Build Coastguard Worker using aidl::android::media::audio::common::AudioEncapsulationMode;
40*4d7e907cSAndroid Build Coastguard Worker using aidl::android::media::audio::common::AudioFormatDescription;
41*4d7e907cSAndroid Build Coastguard Worker using aidl::android::media::audio::common::AudioFormatType;
42*4d7e907cSAndroid Build Coastguard Worker using aidl::android::media::audio::common::AudioInputFlags;
43*4d7e907cSAndroid Build Coastguard Worker using aidl::android::media::audio::common::AudioIoFlags;
44*4d7e907cSAndroid Build Coastguard Worker using aidl::android::media::audio::common::AudioOffloadInfo;
45*4d7e907cSAndroid Build Coastguard Worker using aidl::android::media::audio::common::AudioOutputFlags;
46*4d7e907cSAndroid Build Coastguard Worker using aidl::android::media::audio::common::AudioPort;
47*4d7e907cSAndroid Build Coastguard Worker using aidl::android::media::audio::common::AudioPortConfig;
48*4d7e907cSAndroid Build Coastguard Worker using aidl::android::media::audio::common::AudioPortExt;
49*4d7e907cSAndroid Build Coastguard Worker using aidl::android::media::audio::common::AudioProfile;
50*4d7e907cSAndroid Build Coastguard Worker using aidl::android::media::audio::common::AudioUsage;
51*4d7e907cSAndroid Build Coastguard Worker using aidl::android::media::audio::common::Int;
52*4d7e907cSAndroid Build Coastguard Worker 
53*4d7e907cSAndroid Build Coastguard Worker // static
generateOffloadInfoIfNeeded(const AudioPortConfig & portConfig)54*4d7e907cSAndroid Build Coastguard Worker std::optional<AudioOffloadInfo> ModuleConfig::generateOffloadInfoIfNeeded(
55*4d7e907cSAndroid Build Coastguard Worker         const AudioPortConfig& portConfig) {
56*4d7e907cSAndroid Build Coastguard Worker     if (portConfig.flags.has_value() &&
57*4d7e907cSAndroid Build Coastguard Worker         portConfig.flags.value().getTag() == AudioIoFlags::Tag::output &&
58*4d7e907cSAndroid Build Coastguard Worker         isBitPositionFlagSet(portConfig.flags.value().get<AudioIoFlags::Tag::output>(),
59*4d7e907cSAndroid Build Coastguard Worker                              AudioOutputFlags::COMPRESS_OFFLOAD)) {
60*4d7e907cSAndroid Build Coastguard Worker         AudioOffloadInfo offloadInfo;
61*4d7e907cSAndroid Build Coastguard Worker         offloadInfo.base.sampleRate = portConfig.sampleRate.value().value;
62*4d7e907cSAndroid Build Coastguard Worker         offloadInfo.base.channelMask = portConfig.channelMask.value();
63*4d7e907cSAndroid Build Coastguard Worker         offloadInfo.base.format = portConfig.format.value();
64*4d7e907cSAndroid Build Coastguard Worker         offloadInfo.bitRatePerSecond = 256000;                             // Arbitrary value.
65*4d7e907cSAndroid Build Coastguard Worker         offloadInfo.durationUs = std::chrono::microseconds(1min).count();  // Arbitrary value.
66*4d7e907cSAndroid Build Coastguard Worker         offloadInfo.usage = AudioUsage::MEDIA;
67*4d7e907cSAndroid Build Coastguard Worker         offloadInfo.encapsulationMode = AudioEncapsulationMode::NONE;
68*4d7e907cSAndroid Build Coastguard Worker         return offloadInfo;
69*4d7e907cSAndroid Build Coastguard Worker     }
70*4d7e907cSAndroid Build Coastguard Worker     return {};
71*4d7e907cSAndroid Build Coastguard Worker }
72*4d7e907cSAndroid Build Coastguard Worker 
73*4d7e907cSAndroid Build Coastguard Worker // static
74*4d7e907cSAndroid Build Coastguard Worker std::vector<aidl::android::media::audio::common::AudioPort>
getAudioPortsForDeviceTypes(const std::vector<aidl::android::media::audio::common::AudioPort> & ports,const std::vector<AudioDeviceType> & deviceTypes,const std::string & connection)75*4d7e907cSAndroid Build Coastguard Worker ModuleConfig::getAudioPortsForDeviceTypes(
76*4d7e907cSAndroid Build Coastguard Worker         const std::vector<aidl::android::media::audio::common::AudioPort>& ports,
77*4d7e907cSAndroid Build Coastguard Worker         const std::vector<AudioDeviceType>& deviceTypes, const std::string& connection) {
78*4d7e907cSAndroid Build Coastguard Worker     std::vector<AudioPort> result;
79*4d7e907cSAndroid Build Coastguard Worker     for (const auto& port : ports) {
80*4d7e907cSAndroid Build Coastguard Worker         if (port.ext.getTag() != AudioPortExt::Tag::device) continue;
81*4d7e907cSAndroid Build Coastguard Worker         const auto type = port.ext.get<AudioPortExt::Tag::device>().device.type;
82*4d7e907cSAndroid Build Coastguard Worker         if (type.connection == connection) {
83*4d7e907cSAndroid Build Coastguard Worker             for (auto deviceType : deviceTypes) {
84*4d7e907cSAndroid Build Coastguard Worker                 if (type.type == deviceType) {
85*4d7e907cSAndroid Build Coastguard Worker                     result.push_back(port);
86*4d7e907cSAndroid Build Coastguard Worker                 }
87*4d7e907cSAndroid Build Coastguard Worker             }
88*4d7e907cSAndroid Build Coastguard Worker         }
89*4d7e907cSAndroid Build Coastguard Worker     }
90*4d7e907cSAndroid Build Coastguard Worker     return result;
91*4d7e907cSAndroid Build Coastguard Worker }
92*4d7e907cSAndroid Build Coastguard Worker 
93*4d7e907cSAndroid Build Coastguard Worker // static
getBuiltInMicPorts(const std::vector<aidl::android::media::audio::common::AudioPort> & ports)94*4d7e907cSAndroid Build Coastguard Worker std::vector<aidl::android::media::audio::common::AudioPort> ModuleConfig::getBuiltInMicPorts(
95*4d7e907cSAndroid Build Coastguard Worker         const std::vector<aidl::android::media::audio::common::AudioPort>& ports) {
96*4d7e907cSAndroid Build Coastguard Worker     return getAudioPortsForDeviceTypes(
97*4d7e907cSAndroid Build Coastguard Worker             ports, std::vector<AudioDeviceType>{AudioDeviceType::IN_MICROPHONE,
98*4d7e907cSAndroid Build Coastguard Worker                                                 AudioDeviceType::IN_MICROPHONE_BACK});
99*4d7e907cSAndroid Build Coastguard Worker }
100*4d7e907cSAndroid Build Coastguard Worker 
101*4d7e907cSAndroid Build Coastguard Worker template <typename T>
findById(const std::vector<T> & v,int32_t id)102*4d7e907cSAndroid Build Coastguard Worker auto findById(const std::vector<T>& v, int32_t id) {
103*4d7e907cSAndroid Build Coastguard Worker     return std::find_if(v.begin(), v.end(), [&](const auto& p) { return p.id == id; });
104*4d7e907cSAndroid Build Coastguard Worker }
105*4d7e907cSAndroid Build Coastguard Worker 
ModuleConfig(IModule * module)106*4d7e907cSAndroid Build Coastguard Worker ModuleConfig::ModuleConfig(IModule* module) {
107*4d7e907cSAndroid Build Coastguard Worker     mStatus = module->getAudioPorts(&mPorts);
108*4d7e907cSAndroid Build Coastguard Worker     if (!mStatus.isOk()) return;
109*4d7e907cSAndroid Build Coastguard Worker     for (const auto& port : mPorts) {
110*4d7e907cSAndroid Build Coastguard Worker         if (port.ext.getTag() != AudioPortExt::Tag::device) continue;
111*4d7e907cSAndroid Build Coastguard Worker         const auto& devicePort = port.ext.get<AudioPortExt::Tag::device>();
112*4d7e907cSAndroid Build Coastguard Worker         if (devicePort.device.type.connection.empty()) {
113*4d7e907cSAndroid Build Coastguard Worker             const bool isInput = port.flags.getTag() == AudioIoFlags::Tag::input;
114*4d7e907cSAndroid Build Coastguard Worker             // Permanently attached device.
115*4d7e907cSAndroid Build Coastguard Worker             if (isInput) {
116*4d7e907cSAndroid Build Coastguard Worker                 mAttachedSourceDevicePorts.insert(port.id);
117*4d7e907cSAndroid Build Coastguard Worker             } else {
118*4d7e907cSAndroid Build Coastguard Worker                 mAttachedSinkDevicePorts.insert(port.id);
119*4d7e907cSAndroid Build Coastguard Worker             }
120*4d7e907cSAndroid Build Coastguard Worker         } else {
121*4d7e907cSAndroid Build Coastguard Worker             mExternalDevicePorts.insert(port.id);
122*4d7e907cSAndroid Build Coastguard Worker         }
123*4d7e907cSAndroid Build Coastguard Worker     }
124*4d7e907cSAndroid Build Coastguard Worker     if (!mStatus.isOk()) return;
125*4d7e907cSAndroid Build Coastguard Worker     mStatus = module->getAudioRoutes(&mRoutes);
126*4d7e907cSAndroid Build Coastguard Worker     if (!mStatus.isOk()) return;
127*4d7e907cSAndroid Build Coastguard Worker     mStatus = module->getAudioPortConfigs(&mInitialConfigs);
128*4d7e907cSAndroid Build Coastguard Worker }
129*4d7e907cSAndroid Build Coastguard Worker 
getAttachedDevicePorts() const130*4d7e907cSAndroid Build Coastguard Worker std::vector<AudioPort> ModuleConfig::getAttachedDevicePorts() const {
131*4d7e907cSAndroid Build Coastguard Worker     std::vector<AudioPort> result;
132*4d7e907cSAndroid Build Coastguard Worker     std::copy_if(mPorts.begin(), mPorts.end(), std::back_inserter(result), [&](const auto& port) {
133*4d7e907cSAndroid Build Coastguard Worker         return mAttachedSinkDevicePorts.count(port.id) != 0 ||
134*4d7e907cSAndroid Build Coastguard Worker                mAttachedSourceDevicePorts.count(port.id) != 0;
135*4d7e907cSAndroid Build Coastguard Worker     });
136*4d7e907cSAndroid Build Coastguard Worker     return result;
137*4d7e907cSAndroid Build Coastguard Worker }
138*4d7e907cSAndroid Build Coastguard Worker 
139*4d7e907cSAndroid Build Coastguard Worker std::vector<aidl::android::media::audio::common::AudioPort>
getAudioPortsForDeviceTypes(const std::vector<AudioDeviceType> & deviceTypes,const std::string & connection) const140*4d7e907cSAndroid Build Coastguard Worker ModuleConfig::getAudioPortsForDeviceTypes(const std::vector<AudioDeviceType>& deviceTypes,
141*4d7e907cSAndroid Build Coastguard Worker                                           const std::string& connection) const {
142*4d7e907cSAndroid Build Coastguard Worker     return getAudioPortsForDeviceTypes(mPorts, deviceTypes, connection);
143*4d7e907cSAndroid Build Coastguard Worker }
144*4d7e907cSAndroid Build Coastguard Worker 
getConnectedExternalDevicePorts() const145*4d7e907cSAndroid Build Coastguard Worker std::vector<AudioPort> ModuleConfig::getConnectedExternalDevicePorts() const {
146*4d7e907cSAndroid Build Coastguard Worker     std::vector<AudioPort> result;
147*4d7e907cSAndroid Build Coastguard Worker     std::copy_if(mPorts.begin(), mPorts.end(), std::back_inserter(result), [&](const auto& port) {
148*4d7e907cSAndroid Build Coastguard Worker         return mConnectedExternalSinkDevicePorts.count(port.id) != 0 ||
149*4d7e907cSAndroid Build Coastguard Worker                mConnectedExternalSourceDevicePorts.count(port.id) != 0;
150*4d7e907cSAndroid Build Coastguard Worker     });
151*4d7e907cSAndroid Build Coastguard Worker     return result;
152*4d7e907cSAndroid Build Coastguard Worker }
153*4d7e907cSAndroid Build Coastguard Worker 
getConnectedSinkDevicePorts() const154*4d7e907cSAndroid Build Coastguard Worker std::set<int32_t> ModuleConfig::getConnectedSinkDevicePorts() const {
155*4d7e907cSAndroid Build Coastguard Worker     std::set<int32_t> result;
156*4d7e907cSAndroid Build Coastguard Worker     result.insert(mAttachedSinkDevicePorts.begin(), mAttachedSinkDevicePorts.end());
157*4d7e907cSAndroid Build Coastguard Worker     result.insert(mConnectedExternalSinkDevicePorts.begin(),
158*4d7e907cSAndroid Build Coastguard Worker                   mConnectedExternalSinkDevicePorts.end());
159*4d7e907cSAndroid Build Coastguard Worker     return result;
160*4d7e907cSAndroid Build Coastguard Worker }
161*4d7e907cSAndroid Build Coastguard Worker 
getConnectedSourceDevicePorts() const162*4d7e907cSAndroid Build Coastguard Worker std::set<int32_t> ModuleConfig::getConnectedSourceDevicePorts() const {
163*4d7e907cSAndroid Build Coastguard Worker     std::set<int32_t> result;
164*4d7e907cSAndroid Build Coastguard Worker     result.insert(mAttachedSourceDevicePorts.begin(), mAttachedSourceDevicePorts.end());
165*4d7e907cSAndroid Build Coastguard Worker     result.insert(mConnectedExternalSourceDevicePorts.begin(),
166*4d7e907cSAndroid Build Coastguard Worker                   mConnectedExternalSourceDevicePorts.end());
167*4d7e907cSAndroid Build Coastguard Worker     return result;
168*4d7e907cSAndroid Build Coastguard Worker }
169*4d7e907cSAndroid Build Coastguard Worker 
getExternalDevicePorts() const170*4d7e907cSAndroid Build Coastguard Worker std::vector<AudioPort> ModuleConfig::getExternalDevicePorts() const {
171*4d7e907cSAndroid Build Coastguard Worker     std::vector<AudioPort> result;
172*4d7e907cSAndroid Build Coastguard Worker     std::copy_if(mPorts.begin(), mPorts.end(), std::back_inserter(result),
173*4d7e907cSAndroid Build Coastguard Worker                  [&](const auto& port) { return mExternalDevicePorts.count(port.id) != 0; });
174*4d7e907cSAndroid Build Coastguard Worker     return result;
175*4d7e907cSAndroid Build Coastguard Worker }
176*4d7e907cSAndroid Build Coastguard Worker 
getInputMixPorts(bool connectedOnly) const177*4d7e907cSAndroid Build Coastguard Worker std::vector<AudioPort> ModuleConfig::getInputMixPorts(bool connectedOnly) const {
178*4d7e907cSAndroid Build Coastguard Worker     std::vector<AudioPort> result;
179*4d7e907cSAndroid Build Coastguard Worker     std::copy_if(mPorts.begin(), mPorts.end(), std::back_inserter(result), [&](const auto& port) {
180*4d7e907cSAndroid Build Coastguard Worker         return port.ext.getTag() == AudioPortExt::Tag::mix &&
181*4d7e907cSAndroid Build Coastguard Worker                port.flags.getTag() == AudioIoFlags::Tag::input &&
182*4d7e907cSAndroid Build Coastguard Worker                (!connectedOnly || !getConnectedSourceDevicesPortsForMixPort(port).empty());
183*4d7e907cSAndroid Build Coastguard Worker     });
184*4d7e907cSAndroid Build Coastguard Worker     return result;
185*4d7e907cSAndroid Build Coastguard Worker }
186*4d7e907cSAndroid Build Coastguard Worker 
getOutputMixPorts(bool connectedOnly) const187*4d7e907cSAndroid Build Coastguard Worker std::vector<AudioPort> ModuleConfig::getOutputMixPorts(bool connectedOnly) const {
188*4d7e907cSAndroid Build Coastguard Worker     std::vector<AudioPort> result;
189*4d7e907cSAndroid Build Coastguard Worker     std::copy_if(mPorts.begin(), mPorts.end(), std::back_inserter(result), [&](const auto& port) {
190*4d7e907cSAndroid Build Coastguard Worker         return port.ext.getTag() == AudioPortExt::Tag::mix &&
191*4d7e907cSAndroid Build Coastguard Worker                port.flags.getTag() == AudioIoFlags::Tag::output &&
192*4d7e907cSAndroid Build Coastguard Worker                (!connectedOnly || !getConnectedSinkDevicesPortsForMixPort(port).empty());
193*4d7e907cSAndroid Build Coastguard Worker     });
194*4d7e907cSAndroid Build Coastguard Worker     return result;
195*4d7e907cSAndroid Build Coastguard Worker }
196*4d7e907cSAndroid Build Coastguard Worker 
getNonBlockingMixPorts(bool connectedOnly,bool singlePort) const197*4d7e907cSAndroid Build Coastguard Worker std::vector<AudioPort> ModuleConfig::getNonBlockingMixPorts(bool connectedOnly,
198*4d7e907cSAndroid Build Coastguard Worker                                                             bool singlePort) const {
199*4d7e907cSAndroid Build Coastguard Worker     return findMixPorts(false /*isInput*/, connectedOnly, singlePort, [&](const AudioPort& port) {
200*4d7e907cSAndroid Build Coastguard Worker         return isBitPositionFlagSet(port.flags.get<AudioIoFlags::Tag::output>(),
201*4d7e907cSAndroid Build Coastguard Worker                                     AudioOutputFlags::NON_BLOCKING);
202*4d7e907cSAndroid Build Coastguard Worker     });
203*4d7e907cSAndroid Build Coastguard Worker }
204*4d7e907cSAndroid Build Coastguard Worker 
getOffloadMixPorts(bool connectedOnly,bool singlePort) const205*4d7e907cSAndroid Build Coastguard Worker std::vector<AudioPort> ModuleConfig::getOffloadMixPorts(bool connectedOnly, bool singlePort) const {
206*4d7e907cSAndroid Build Coastguard Worker     return findMixPorts(false /*isInput*/, connectedOnly, singlePort, [&](const AudioPort& port) {
207*4d7e907cSAndroid Build Coastguard Worker         return isBitPositionFlagSet(port.flags.get<AudioIoFlags::Tag::output>(),
208*4d7e907cSAndroid Build Coastguard Worker                                     AudioOutputFlags::COMPRESS_OFFLOAD);
209*4d7e907cSAndroid Build Coastguard Worker     });
210*4d7e907cSAndroid Build Coastguard Worker }
211*4d7e907cSAndroid Build Coastguard Worker 
getPrimaryMixPorts(bool connectedOnly,bool singlePort) const212*4d7e907cSAndroid Build Coastguard Worker std::vector<AudioPort> ModuleConfig::getPrimaryMixPorts(bool connectedOnly, bool singlePort) const {
213*4d7e907cSAndroid Build Coastguard Worker     return findMixPorts(false /*isInput*/, connectedOnly, singlePort, [&](const AudioPort& port) {
214*4d7e907cSAndroid Build Coastguard Worker         return isBitPositionFlagSet(port.flags.get<AudioIoFlags::Tag::output>(),
215*4d7e907cSAndroid Build Coastguard Worker                                     AudioOutputFlags::PRIMARY);
216*4d7e907cSAndroid Build Coastguard Worker     });
217*4d7e907cSAndroid Build Coastguard Worker }
218*4d7e907cSAndroid Build Coastguard Worker 
getMmapOutMixPorts(bool connectedOnly,bool singlePort) const219*4d7e907cSAndroid Build Coastguard Worker std::vector<AudioPort> ModuleConfig::getMmapOutMixPorts(bool connectedOnly, bool singlePort) const {
220*4d7e907cSAndroid Build Coastguard Worker     return findMixPorts(false /*isInput*/, connectedOnly, singlePort, [&](const AudioPort& port) {
221*4d7e907cSAndroid Build Coastguard Worker         return isBitPositionFlagSet(port.flags.get<AudioIoFlags::Tag::output>(),
222*4d7e907cSAndroid Build Coastguard Worker                                     AudioOutputFlags::MMAP_NOIRQ);
223*4d7e907cSAndroid Build Coastguard Worker     });
224*4d7e907cSAndroid Build Coastguard Worker }
225*4d7e907cSAndroid Build Coastguard Worker 
getMmapInMixPorts(bool connectedOnly,bool singlePort) const226*4d7e907cSAndroid Build Coastguard Worker std::vector<AudioPort> ModuleConfig::getMmapInMixPorts(bool connectedOnly, bool singlePort) const {
227*4d7e907cSAndroid Build Coastguard Worker     return findMixPorts(true /*isInput*/, connectedOnly, singlePort, [&](const AudioPort& port) {
228*4d7e907cSAndroid Build Coastguard Worker         return isBitPositionFlagSet(port.flags.get<AudioIoFlags::Tag::input>(),
229*4d7e907cSAndroid Build Coastguard Worker                                     AudioInputFlags::MMAP_NOIRQ);
230*4d7e907cSAndroid Build Coastguard Worker     });
231*4d7e907cSAndroid Build Coastguard Worker }
232*4d7e907cSAndroid Build Coastguard Worker 
getRemoteSubmixPorts(bool isInput,bool singlePort) const233*4d7e907cSAndroid Build Coastguard Worker std::vector<AudioPort> ModuleConfig::getRemoteSubmixPorts(bool isInput, bool singlePort) const {
234*4d7e907cSAndroid Build Coastguard Worker     AudioDeviceType deviceType = isInput ? AudioDeviceType::IN_SUBMIX : AudioDeviceType::OUT_SUBMIX;
235*4d7e907cSAndroid Build Coastguard Worker     auto ports = getAudioPortsForDeviceTypes(std::vector<AudioDeviceType>{deviceType},
236*4d7e907cSAndroid Build Coastguard Worker                                              AudioDeviceDescription::CONNECTION_VIRTUAL);
237*4d7e907cSAndroid Build Coastguard Worker     if (singlePort) {
238*4d7e907cSAndroid Build Coastguard Worker         if (!ports.empty()) ports.resize(1);
239*4d7e907cSAndroid Build Coastguard Worker     }
240*4d7e907cSAndroid Build Coastguard Worker     return ports;
241*4d7e907cSAndroid Build Coastguard Worker }
242*4d7e907cSAndroid Build Coastguard Worker 
getConnectedDevicesPortsForMixPort(bool isInput,const AudioPortConfig & mixPortConfig) const243*4d7e907cSAndroid Build Coastguard Worker std::vector<AudioPort> ModuleConfig::getConnectedDevicesPortsForMixPort(
244*4d7e907cSAndroid Build Coastguard Worker         bool isInput, const AudioPortConfig& mixPortConfig) const {
245*4d7e907cSAndroid Build Coastguard Worker     const auto mixPortIt = findById<AudioPort>(mPorts, mixPortConfig.portId);
246*4d7e907cSAndroid Build Coastguard Worker     if (mixPortIt != mPorts.end()) {
247*4d7e907cSAndroid Build Coastguard Worker         return getConnectedDevicesPortsForMixPort(isInput, *mixPortIt);
248*4d7e907cSAndroid Build Coastguard Worker     }
249*4d7e907cSAndroid Build Coastguard Worker     return {};
250*4d7e907cSAndroid Build Coastguard Worker }
251*4d7e907cSAndroid Build Coastguard Worker 
getConnectedSinkDevicesPortsForMixPort(const AudioPort & mixPort) const252*4d7e907cSAndroid Build Coastguard Worker std::vector<AudioPort> ModuleConfig::getConnectedSinkDevicesPortsForMixPort(
253*4d7e907cSAndroid Build Coastguard Worker         const AudioPort& mixPort) const {
254*4d7e907cSAndroid Build Coastguard Worker     std::vector<AudioPort> result;
255*4d7e907cSAndroid Build Coastguard Worker     std::set<int32_t> connectedSinkDevicePorts = getConnectedSinkDevicePorts();
256*4d7e907cSAndroid Build Coastguard Worker     for (const auto& route : mRoutes) {
257*4d7e907cSAndroid Build Coastguard Worker         if ((connectedSinkDevicePorts.count(route.sinkPortId) != 0) &&
258*4d7e907cSAndroid Build Coastguard Worker             std::find(route.sourcePortIds.begin(), route.sourcePortIds.end(), mixPort.id) !=
259*4d7e907cSAndroid Build Coastguard Worker                     route.sourcePortIds.end()) {
260*4d7e907cSAndroid Build Coastguard Worker             const auto devicePortIt = findById<AudioPort>(mPorts, route.sinkPortId);
261*4d7e907cSAndroid Build Coastguard Worker             if (devicePortIt != mPorts.end()) result.push_back(*devicePortIt);
262*4d7e907cSAndroid Build Coastguard Worker         }
263*4d7e907cSAndroid Build Coastguard Worker     }
264*4d7e907cSAndroid Build Coastguard Worker     return result;
265*4d7e907cSAndroid Build Coastguard Worker }
266*4d7e907cSAndroid Build Coastguard Worker 
getConnectedSourceDevicesPortsForMixPort(const AudioPort & mixPort) const267*4d7e907cSAndroid Build Coastguard Worker std::vector<AudioPort> ModuleConfig::getConnectedSourceDevicesPortsForMixPort(
268*4d7e907cSAndroid Build Coastguard Worker         const AudioPort& mixPort) const {
269*4d7e907cSAndroid Build Coastguard Worker     std::vector<AudioPort> result;
270*4d7e907cSAndroid Build Coastguard Worker     std::set<int32_t> connectedSourceDevicePorts = getConnectedSourceDevicePorts();
271*4d7e907cSAndroid Build Coastguard Worker     for (const auto& route : mRoutes) {
272*4d7e907cSAndroid Build Coastguard Worker         if (route.sinkPortId == mixPort.id) {
273*4d7e907cSAndroid Build Coastguard Worker             for (const auto srcId : route.sourcePortIds) {
274*4d7e907cSAndroid Build Coastguard Worker                 if (connectedSourceDevicePorts.count(srcId) != 0) {
275*4d7e907cSAndroid Build Coastguard Worker                     const auto devicePortIt = findById<AudioPort>(mPorts, srcId);
276*4d7e907cSAndroid Build Coastguard Worker                     if (devicePortIt != mPorts.end()) result.push_back(*devicePortIt);
277*4d7e907cSAndroid Build Coastguard Worker                 }
278*4d7e907cSAndroid Build Coastguard Worker             }
279*4d7e907cSAndroid Build Coastguard Worker         }
280*4d7e907cSAndroid Build Coastguard Worker     }
281*4d7e907cSAndroid Build Coastguard Worker     return result;
282*4d7e907cSAndroid Build Coastguard Worker }
283*4d7e907cSAndroid Build Coastguard Worker 
getSourceMixPortForConnectedDevice() const284*4d7e907cSAndroid Build Coastguard Worker std::optional<AudioPort> ModuleConfig::getSourceMixPortForConnectedDevice() const {
285*4d7e907cSAndroid Build Coastguard Worker     std::set<int32_t> connectedSinkDevicePorts = getConnectedSinkDevicePorts();
286*4d7e907cSAndroid Build Coastguard Worker     for (const auto& route : mRoutes) {
287*4d7e907cSAndroid Build Coastguard Worker         if (connectedSinkDevicePorts.count(route.sinkPortId) != 0) {
288*4d7e907cSAndroid Build Coastguard Worker             const auto mixPortIt = findById<AudioPort>(mPorts, route.sourcePortIds[0]);
289*4d7e907cSAndroid Build Coastguard Worker             if (mixPortIt != mPorts.end()) return *mixPortIt;
290*4d7e907cSAndroid Build Coastguard Worker         }
291*4d7e907cSAndroid Build Coastguard Worker     }
292*4d7e907cSAndroid Build Coastguard Worker     return {};
293*4d7e907cSAndroid Build Coastguard Worker }
294*4d7e907cSAndroid Build Coastguard Worker 
getRoutableDevicePortsForMixPort(const AudioPort & port,bool connectedOnly) const295*4d7e907cSAndroid Build Coastguard Worker std::vector<AudioPort> ModuleConfig::getRoutableDevicePortsForMixPort(const AudioPort& port,
296*4d7e907cSAndroid Build Coastguard Worker                                                                       bool connectedOnly) const {
297*4d7e907cSAndroid Build Coastguard Worker     std::set<int32_t> portIds = findRoutablePortIds(port.id);
298*4d7e907cSAndroid Build Coastguard Worker     const bool isInput = port.flags.getTag() == AudioIoFlags::input;
299*4d7e907cSAndroid Build Coastguard Worker     std::set<int32_t> devicePortIds;
300*4d7e907cSAndroid Build Coastguard Worker     if (connectedOnly) {
301*4d7e907cSAndroid Build Coastguard Worker         devicePortIds = isInput ? getConnectedSourceDevicePorts() : getConnectedSinkDevicePorts();
302*4d7e907cSAndroid Build Coastguard Worker     } else {
303*4d7e907cSAndroid Build Coastguard Worker         devicePortIds = portIds;
304*4d7e907cSAndroid Build Coastguard Worker     }
305*4d7e907cSAndroid Build Coastguard Worker     std::vector<AudioPort> result;
306*4d7e907cSAndroid Build Coastguard Worker     std::copy_if(mPorts.begin(), mPorts.end(), std::back_inserter(result), [&](const auto& port) {
307*4d7e907cSAndroid Build Coastguard Worker         return port.ext.getTag() == AudioPortExt::Tag::device && portIds.count(port.id) > 0 &&
308*4d7e907cSAndroid Build Coastguard Worker                devicePortIds.count(port.id) > 0;
309*4d7e907cSAndroid Build Coastguard Worker     });
310*4d7e907cSAndroid Build Coastguard Worker     return result;
311*4d7e907cSAndroid Build Coastguard Worker }
312*4d7e907cSAndroid Build Coastguard Worker 
getRoutableMixPortsForDevicePort(const AudioPort & port,bool connectedOnly) const313*4d7e907cSAndroid Build Coastguard Worker std::vector<AudioPort> ModuleConfig::getRoutableMixPortsForDevicePort(const AudioPort& port,
314*4d7e907cSAndroid Build Coastguard Worker                                                                       bool connectedOnly) const {
315*4d7e907cSAndroid Build Coastguard Worker     std::set<int32_t> portIds = findRoutablePortIds(port.id);
316*4d7e907cSAndroid Build Coastguard Worker     const bool isInput = port.flags.getTag() == AudioIoFlags::input;
317*4d7e907cSAndroid Build Coastguard Worker     return findMixPorts(isInput, connectedOnly, false /*singlePort*/,
318*4d7e907cSAndroid Build Coastguard Worker                         [&portIds](const AudioPort& p) { return portIds.count(p.id) > 0; });
319*4d7e907cSAndroid Build Coastguard Worker }
320*4d7e907cSAndroid Build Coastguard Worker 
getNonRoutableSrcSinkPair(bool isInput) const321*4d7e907cSAndroid Build Coastguard Worker std::optional<ModuleConfig::SrcSinkPair> ModuleConfig::getNonRoutableSrcSinkPair(
322*4d7e907cSAndroid Build Coastguard Worker         bool isInput) const {
323*4d7e907cSAndroid Build Coastguard Worker     const auto mixPorts = getMixPorts(isInput, false /*connectedOnly*/);
324*4d7e907cSAndroid Build Coastguard Worker     std::set<std::pair<int32_t, int32_t>> allowedRoutes;
325*4d7e907cSAndroid Build Coastguard Worker     for (const auto& route : mRoutes) {
326*4d7e907cSAndroid Build Coastguard Worker         for (const auto srcPortId : route.sourcePortIds) {
327*4d7e907cSAndroid Build Coastguard Worker             allowedRoutes.emplace(std::make_pair(srcPortId, route.sinkPortId));
328*4d7e907cSAndroid Build Coastguard Worker         }
329*4d7e907cSAndroid Build Coastguard Worker     }
330*4d7e907cSAndroid Build Coastguard Worker     auto make_pair = [isInput](auto& device, auto& mix) {
331*4d7e907cSAndroid Build Coastguard Worker         return isInput ? std::make_pair(device, mix) : std::make_pair(mix, device);
332*4d7e907cSAndroid Build Coastguard Worker     };
333*4d7e907cSAndroid Build Coastguard Worker     for (const auto portId :
334*4d7e907cSAndroid Build Coastguard Worker          isInput ? getConnectedSourceDevicePorts() : getConnectedSinkDevicePorts()) {
335*4d7e907cSAndroid Build Coastguard Worker         const auto devicePortIt = findById<AudioPort>(mPorts, portId);
336*4d7e907cSAndroid Build Coastguard Worker         if (devicePortIt == mPorts.end()) continue;
337*4d7e907cSAndroid Build Coastguard Worker         auto devicePortConfig = getSingleConfigForDevicePort(*devicePortIt);
338*4d7e907cSAndroid Build Coastguard Worker         for (const auto& mixPort : mixPorts) {
339*4d7e907cSAndroid Build Coastguard Worker             if (std::find(allowedRoutes.begin(), allowedRoutes.end(),
340*4d7e907cSAndroid Build Coastguard Worker                           make_pair(portId, mixPort.id)) == allowedRoutes.end()) {
341*4d7e907cSAndroid Build Coastguard Worker                 auto mixPortConfig = getSingleConfigForMixPort(isInput, mixPort);
342*4d7e907cSAndroid Build Coastguard Worker                 if (mixPortConfig.has_value()) {
343*4d7e907cSAndroid Build Coastguard Worker                     return make_pair(devicePortConfig, mixPortConfig.value());
344*4d7e907cSAndroid Build Coastguard Worker                 }
345*4d7e907cSAndroid Build Coastguard Worker             }
346*4d7e907cSAndroid Build Coastguard Worker         }
347*4d7e907cSAndroid Build Coastguard Worker     }
348*4d7e907cSAndroid Build Coastguard Worker     return {};
349*4d7e907cSAndroid Build Coastguard Worker }
350*4d7e907cSAndroid Build Coastguard Worker 
getRoutableSrcSinkPair(bool isInput) const351*4d7e907cSAndroid Build Coastguard Worker std::optional<ModuleConfig::SrcSinkPair> ModuleConfig::getRoutableSrcSinkPair(bool isInput) const {
352*4d7e907cSAndroid Build Coastguard Worker     if (isInput) {
353*4d7e907cSAndroid Build Coastguard Worker         std::set<int32_t> connectedSourceDevicePorts = getConnectedSourceDevicePorts();
354*4d7e907cSAndroid Build Coastguard Worker         for (const auto& route : mRoutes) {
355*4d7e907cSAndroid Build Coastguard Worker             auto srcPortIdIt = std::find_if(
356*4d7e907cSAndroid Build Coastguard Worker                     route.sourcePortIds.begin(), route.sourcePortIds.end(),
357*4d7e907cSAndroid Build Coastguard Worker                     [&](const auto& portId) { return connectedSourceDevicePorts.count(portId); });
358*4d7e907cSAndroid Build Coastguard Worker             if (srcPortIdIt == route.sourcePortIds.end()) continue;
359*4d7e907cSAndroid Build Coastguard Worker             const auto devicePortIt = findById<AudioPort>(mPorts, *srcPortIdIt);
360*4d7e907cSAndroid Build Coastguard Worker             const auto mixPortIt = findById<AudioPort>(mPorts, route.sinkPortId);
361*4d7e907cSAndroid Build Coastguard Worker             if (devicePortIt == mPorts.end() || mixPortIt == mPorts.end()) continue;
362*4d7e907cSAndroid Build Coastguard Worker             auto devicePortConfig = getSingleConfigForDevicePort(*devicePortIt);
363*4d7e907cSAndroid Build Coastguard Worker             auto mixPortConfig = getSingleConfigForMixPort(isInput, *mixPortIt);
364*4d7e907cSAndroid Build Coastguard Worker             if (!mixPortConfig.has_value()) continue;
365*4d7e907cSAndroid Build Coastguard Worker             return std::make_pair(devicePortConfig, mixPortConfig.value());
366*4d7e907cSAndroid Build Coastguard Worker         }
367*4d7e907cSAndroid Build Coastguard Worker     } else {
368*4d7e907cSAndroid Build Coastguard Worker         std::set<int32_t> connectedSinkDevicePorts = getConnectedSinkDevicePorts();
369*4d7e907cSAndroid Build Coastguard Worker         for (const auto& route : mRoutes) {
370*4d7e907cSAndroid Build Coastguard Worker             if (connectedSinkDevicePorts.count(route.sinkPortId) == 0) continue;
371*4d7e907cSAndroid Build Coastguard Worker             const auto mixPortIt = findById<AudioPort>(mPorts, route.sourcePortIds[0]);
372*4d7e907cSAndroid Build Coastguard Worker             const auto devicePortIt = findById<AudioPort>(mPorts, route.sinkPortId);
373*4d7e907cSAndroid Build Coastguard Worker             if (devicePortIt == mPorts.end() || mixPortIt == mPorts.end()) continue;
374*4d7e907cSAndroid Build Coastguard Worker             auto mixPortConfig = getSingleConfigForMixPort(isInput, *mixPortIt);
375*4d7e907cSAndroid Build Coastguard Worker             auto devicePortConfig = getSingleConfigForDevicePort(*devicePortIt);
376*4d7e907cSAndroid Build Coastguard Worker             if (!mixPortConfig.has_value()) continue;
377*4d7e907cSAndroid Build Coastguard Worker             return std::make_pair(mixPortConfig.value(), devicePortConfig);
378*4d7e907cSAndroid Build Coastguard Worker         }
379*4d7e907cSAndroid Build Coastguard Worker     }
380*4d7e907cSAndroid Build Coastguard Worker     return {};
381*4d7e907cSAndroid Build Coastguard Worker }
382*4d7e907cSAndroid Build Coastguard Worker 
getRoutableSrcSinkGroups(bool isInput) const383*4d7e907cSAndroid Build Coastguard Worker std::vector<ModuleConfig::SrcSinkGroup> ModuleConfig::getRoutableSrcSinkGroups(bool isInput) const {
384*4d7e907cSAndroid Build Coastguard Worker     std::vector<SrcSinkGroup> result;
385*4d7e907cSAndroid Build Coastguard Worker     if (isInput) {
386*4d7e907cSAndroid Build Coastguard Worker         std::set<int32_t> connectedSourceDevicePorts = getConnectedSourceDevicePorts();
387*4d7e907cSAndroid Build Coastguard Worker         for (const auto& route : mRoutes) {
388*4d7e907cSAndroid Build Coastguard Worker             std::vector<int32_t> srcPortIds;
389*4d7e907cSAndroid Build Coastguard Worker             std::copy_if(route.sourcePortIds.begin(), route.sourcePortIds.end(),
390*4d7e907cSAndroid Build Coastguard Worker                          std::back_inserter(srcPortIds), [&](const auto& portId) {
391*4d7e907cSAndroid Build Coastguard Worker                              return connectedSourceDevicePorts.count(portId);
392*4d7e907cSAndroid Build Coastguard Worker                          });
393*4d7e907cSAndroid Build Coastguard Worker             if (srcPortIds.empty()) continue;
394*4d7e907cSAndroid Build Coastguard Worker             const auto mixPortIt = findById<AudioPort>(mPorts, route.sinkPortId);
395*4d7e907cSAndroid Build Coastguard Worker             if (mixPortIt == mPorts.end()) continue;
396*4d7e907cSAndroid Build Coastguard Worker             auto mixPortConfig = getSingleConfigForMixPort(isInput, *mixPortIt);
397*4d7e907cSAndroid Build Coastguard Worker             if (!mixPortConfig.has_value()) continue;
398*4d7e907cSAndroid Build Coastguard Worker             std::vector<SrcSinkPair> pairs;
399*4d7e907cSAndroid Build Coastguard Worker             for (const auto srcPortId : srcPortIds) {
400*4d7e907cSAndroid Build Coastguard Worker                 const auto devicePortIt = findById<AudioPort>(mPorts, srcPortId);
401*4d7e907cSAndroid Build Coastguard Worker                 if (devicePortIt == mPorts.end()) continue;
402*4d7e907cSAndroid Build Coastguard Worker                 // Using all configs for every source would be too much.
403*4d7e907cSAndroid Build Coastguard Worker                 auto devicePortConfig = getSingleConfigForDevicePort(*devicePortIt);
404*4d7e907cSAndroid Build Coastguard Worker                 pairs.emplace_back(devicePortConfig, mixPortConfig.value());
405*4d7e907cSAndroid Build Coastguard Worker             }
406*4d7e907cSAndroid Build Coastguard Worker             if (!pairs.empty()) {
407*4d7e907cSAndroid Build Coastguard Worker                 result.emplace_back(route, std::move(pairs));
408*4d7e907cSAndroid Build Coastguard Worker             }
409*4d7e907cSAndroid Build Coastguard Worker         }
410*4d7e907cSAndroid Build Coastguard Worker     } else {
411*4d7e907cSAndroid Build Coastguard Worker         std::set<int32_t> connectedSinkDevicePorts = getConnectedSinkDevicePorts();
412*4d7e907cSAndroid Build Coastguard Worker         for (const auto& route : mRoutes) {
413*4d7e907cSAndroid Build Coastguard Worker             if (connectedSinkDevicePorts.count(route.sinkPortId) == 0) continue;
414*4d7e907cSAndroid Build Coastguard Worker             const auto devicePortIt = findById<AudioPort>(mPorts, route.sinkPortId);
415*4d7e907cSAndroid Build Coastguard Worker             if (devicePortIt == mPorts.end()) continue;
416*4d7e907cSAndroid Build Coastguard Worker             auto devicePortConfig = getSingleConfigForDevicePort(*devicePortIt);
417*4d7e907cSAndroid Build Coastguard Worker             std::vector<SrcSinkPair> pairs;
418*4d7e907cSAndroid Build Coastguard Worker             for (const auto srcPortId : route.sourcePortIds) {
419*4d7e907cSAndroid Build Coastguard Worker                 const auto mixPortIt = findById<AudioPort>(mPorts, srcPortId);
420*4d7e907cSAndroid Build Coastguard Worker                 if (mixPortIt == mPorts.end()) continue;
421*4d7e907cSAndroid Build Coastguard Worker                 // Using all configs for every source would be too much.
422*4d7e907cSAndroid Build Coastguard Worker                 auto mixPortConfig = getSingleConfigForMixPort(isInput, *mixPortIt);
423*4d7e907cSAndroid Build Coastguard Worker                 if (mixPortConfig.has_value()) {
424*4d7e907cSAndroid Build Coastguard Worker                     pairs.emplace_back(mixPortConfig.value(), devicePortConfig);
425*4d7e907cSAndroid Build Coastguard Worker                 }
426*4d7e907cSAndroid Build Coastguard Worker             }
427*4d7e907cSAndroid Build Coastguard Worker             if (!pairs.empty()) {
428*4d7e907cSAndroid Build Coastguard Worker                 result.emplace_back(route, std::move(pairs));
429*4d7e907cSAndroid Build Coastguard Worker             }
430*4d7e907cSAndroid Build Coastguard Worker         }
431*4d7e907cSAndroid Build Coastguard Worker     }
432*4d7e907cSAndroid Build Coastguard Worker     return result;
433*4d7e907cSAndroid Build Coastguard Worker }
434*4d7e907cSAndroid Build Coastguard Worker 
toString() const435*4d7e907cSAndroid Build Coastguard Worker std::string ModuleConfig::toString() const {
436*4d7e907cSAndroid Build Coastguard Worker     std::string result;
437*4d7e907cSAndroid Build Coastguard Worker     result.append("Ports: ");
438*4d7e907cSAndroid Build Coastguard Worker     result.append(android::internal::ToString(mPorts));
439*4d7e907cSAndroid Build Coastguard Worker     result.append("\nInitial configs: ");
440*4d7e907cSAndroid Build Coastguard Worker     result.append(android::internal::ToString(mInitialConfigs));
441*4d7e907cSAndroid Build Coastguard Worker     result.append("\nAttached sink device ports: ");
442*4d7e907cSAndroid Build Coastguard Worker     result.append(android::internal::ToString(mAttachedSinkDevicePorts));
443*4d7e907cSAndroid Build Coastguard Worker     result.append("\nAttached source device ports: ");
444*4d7e907cSAndroid Build Coastguard Worker     result.append(android::internal::ToString(mAttachedSourceDevicePorts));
445*4d7e907cSAndroid Build Coastguard Worker     result.append("\nExternal device ports: ");
446*4d7e907cSAndroid Build Coastguard Worker     result.append(android::internal::ToString(mExternalDevicePorts));
447*4d7e907cSAndroid Build Coastguard Worker     result.append("\nConnected external device ports: ");
448*4d7e907cSAndroid Build Coastguard Worker     result.append(android::internal::ToString(getConnectedExternalDevicePorts()));
449*4d7e907cSAndroid Build Coastguard Worker     result.append("\nRoutes: ");
450*4d7e907cSAndroid Build Coastguard Worker     result.append(android::internal::ToString(mRoutes));
451*4d7e907cSAndroid Build Coastguard Worker     return result;
452*4d7e907cSAndroid Build Coastguard Worker }
453*4d7e907cSAndroid Build Coastguard Worker 
combineAudioConfigs(const AudioPort & port,const AudioProfile & profile,std::vector<AudioPortConfig> * result)454*4d7e907cSAndroid Build Coastguard Worker static size_t combineAudioConfigs(const AudioPort& port, const AudioProfile& profile,
455*4d7e907cSAndroid Build Coastguard Worker                                   std::vector<AudioPortConfig>* result) {
456*4d7e907cSAndroid Build Coastguard Worker     const size_t newConfigCount = profile.channelMasks.size() * profile.sampleRates.size();
457*4d7e907cSAndroid Build Coastguard Worker     result->reserve(result->capacity() + newConfigCount);
458*4d7e907cSAndroid Build Coastguard Worker     for (auto channelMask : profile.channelMasks) {
459*4d7e907cSAndroid Build Coastguard Worker         for (auto sampleRate : profile.sampleRates) {
460*4d7e907cSAndroid Build Coastguard Worker             AudioPortConfig config{};
461*4d7e907cSAndroid Build Coastguard Worker             config.portId = port.id;
462*4d7e907cSAndroid Build Coastguard Worker             Int sr;
463*4d7e907cSAndroid Build Coastguard Worker             sr.value = sampleRate;
464*4d7e907cSAndroid Build Coastguard Worker             config.sampleRate = sr;
465*4d7e907cSAndroid Build Coastguard Worker             config.channelMask = channelMask;
466*4d7e907cSAndroid Build Coastguard Worker             config.format = profile.format;
467*4d7e907cSAndroid Build Coastguard Worker             config.flags = port.flags;
468*4d7e907cSAndroid Build Coastguard Worker             config.ext = port.ext;
469*4d7e907cSAndroid Build Coastguard Worker             result->push_back(std::move(config));
470*4d7e907cSAndroid Build Coastguard Worker         }
471*4d7e907cSAndroid Build Coastguard Worker     }
472*4d7e907cSAndroid Build Coastguard Worker     return newConfigCount;
473*4d7e907cSAndroid Build Coastguard Worker }
474*4d7e907cSAndroid Build Coastguard Worker 
isDynamicProfile(const AudioProfile & profile)475*4d7e907cSAndroid Build Coastguard Worker static bool isDynamicProfile(const AudioProfile& profile) {
476*4d7e907cSAndroid Build Coastguard Worker     return (profile.format.type == AudioFormatType::DEFAULT && profile.format.encoding.empty()) ||
477*4d7e907cSAndroid Build Coastguard Worker            profile.sampleRates.empty() || profile.channelMasks.empty();
478*4d7e907cSAndroid Build Coastguard Worker }
479*4d7e907cSAndroid Build Coastguard Worker 
findMixPorts(bool isInput,bool connectedOnly,bool singlePort,const std::function<bool (const AudioPort &)> & pred) const480*4d7e907cSAndroid Build Coastguard Worker std::vector<AudioPort> ModuleConfig::findMixPorts(
481*4d7e907cSAndroid Build Coastguard Worker         bool isInput, bool connectedOnly, bool singlePort,
482*4d7e907cSAndroid Build Coastguard Worker         const std::function<bool(const AudioPort&)>& pred) const {
483*4d7e907cSAndroid Build Coastguard Worker     std::vector<AudioPort> result;
484*4d7e907cSAndroid Build Coastguard Worker     const auto mixPorts = getMixPorts(isInput, connectedOnly);
485*4d7e907cSAndroid Build Coastguard Worker     for (auto mixPortIt = mixPorts.begin(); mixPortIt != mixPorts.end();) {
486*4d7e907cSAndroid Build Coastguard Worker         mixPortIt = std::find_if(mixPortIt, mixPorts.end(), pred);
487*4d7e907cSAndroid Build Coastguard Worker         if (mixPortIt == mixPorts.end()) break;
488*4d7e907cSAndroid Build Coastguard Worker         result.push_back(*mixPortIt++);
489*4d7e907cSAndroid Build Coastguard Worker         if (singlePort) break;
490*4d7e907cSAndroid Build Coastguard Worker     }
491*4d7e907cSAndroid Build Coastguard Worker     return result;
492*4d7e907cSAndroid Build Coastguard Worker }
493*4d7e907cSAndroid Build Coastguard Worker 
findRoutablePortIds(int32_t portId) const494*4d7e907cSAndroid Build Coastguard Worker std::set<int32_t> ModuleConfig::findRoutablePortIds(int32_t portId) const {
495*4d7e907cSAndroid Build Coastguard Worker     std::set<int32_t> portIds;
496*4d7e907cSAndroid Build Coastguard Worker     for (const auto& route : mRoutes) {
497*4d7e907cSAndroid Build Coastguard Worker         if (portId == route.sinkPortId) {
498*4d7e907cSAndroid Build Coastguard Worker             portIds.insert(route.sourcePortIds.begin(), route.sourcePortIds.end());
499*4d7e907cSAndroid Build Coastguard Worker         } else if (auto it = std::find(route.sourcePortIds.begin(), route.sourcePortIds.end(),
500*4d7e907cSAndroid Build Coastguard Worker                                        portId);
501*4d7e907cSAndroid Build Coastguard Worker                    it != route.sourcePortIds.end()) {
502*4d7e907cSAndroid Build Coastguard Worker             portIds.insert(route.sinkPortId);
503*4d7e907cSAndroid Build Coastguard Worker         }
504*4d7e907cSAndroid Build Coastguard Worker     }
505*4d7e907cSAndroid Build Coastguard Worker     return portIds;
506*4d7e907cSAndroid Build Coastguard Worker }
507*4d7e907cSAndroid Build Coastguard Worker 
generateAudioMixPortConfigs(const std::vector<AudioPort> & ports,bool isInput,bool singleProfile) const508*4d7e907cSAndroid Build Coastguard Worker std::vector<AudioPortConfig> ModuleConfig::generateAudioMixPortConfigs(
509*4d7e907cSAndroid Build Coastguard Worker         const std::vector<AudioPort>& ports, bool isInput, bool singleProfile) const {
510*4d7e907cSAndroid Build Coastguard Worker     std::vector<AudioPortConfig> result;
511*4d7e907cSAndroid Build Coastguard Worker     for (const auto& mixPort : ports) {
512*4d7e907cSAndroid Build Coastguard Worker         if (getConnectedDevicesPortsForMixPort(isInput, mixPort).empty()) {
513*4d7e907cSAndroid Build Coastguard Worker             continue;
514*4d7e907cSAndroid Build Coastguard Worker         }
515*4d7e907cSAndroid Build Coastguard Worker         for (const auto& profile : mixPort.profiles) {
516*4d7e907cSAndroid Build Coastguard Worker             if (isDynamicProfile(profile)) continue;
517*4d7e907cSAndroid Build Coastguard Worker             combineAudioConfigs(mixPort, profile, &result);
518*4d7e907cSAndroid Build Coastguard Worker             if (singleProfile && !result.empty()) {
519*4d7e907cSAndroid Build Coastguard Worker                 result.resize(1);
520*4d7e907cSAndroid Build Coastguard Worker                 return result;
521*4d7e907cSAndroid Build Coastguard Worker             }
522*4d7e907cSAndroid Build Coastguard Worker         }
523*4d7e907cSAndroid Build Coastguard Worker     }
524*4d7e907cSAndroid Build Coastguard Worker     return result;
525*4d7e907cSAndroid Build Coastguard Worker }
526*4d7e907cSAndroid Build Coastguard Worker 
generateAudioDevicePortConfigs(const std::vector<AudioPort> & ports,bool singleProfile) const527*4d7e907cSAndroid Build Coastguard Worker std::vector<AudioPortConfig> ModuleConfig::generateAudioDevicePortConfigs(
528*4d7e907cSAndroid Build Coastguard Worker         const std::vector<AudioPort>& ports, bool singleProfile) const {
529*4d7e907cSAndroid Build Coastguard Worker     std::vector<AudioPortConfig> result;
530*4d7e907cSAndroid Build Coastguard Worker     for (const auto& devicePort : ports) {
531*4d7e907cSAndroid Build Coastguard Worker         const size_t resultSizeBefore = result.size();
532*4d7e907cSAndroid Build Coastguard Worker         for (const auto& profile : devicePort.profiles) {
533*4d7e907cSAndroid Build Coastguard Worker             combineAudioConfigs(devicePort, profile, &result);
534*4d7e907cSAndroid Build Coastguard Worker             if (singleProfile && !result.empty()) {
535*4d7e907cSAndroid Build Coastguard Worker                 result.resize(1);
536*4d7e907cSAndroid Build Coastguard Worker                 return result;
537*4d7e907cSAndroid Build Coastguard Worker             }
538*4d7e907cSAndroid Build Coastguard Worker         }
539*4d7e907cSAndroid Build Coastguard Worker         if (resultSizeBefore == result.size()) {
540*4d7e907cSAndroid Build Coastguard Worker             std::copy_if(mInitialConfigs.begin(), mInitialConfigs.end(), std::back_inserter(result),
541*4d7e907cSAndroid Build Coastguard Worker                          [&](const auto& config) { return config.portId == devicePort.id; });
542*4d7e907cSAndroid Build Coastguard Worker             if (resultSizeBefore == result.size()) {
543*4d7e907cSAndroid Build Coastguard Worker                 AudioPortConfig empty;
544*4d7e907cSAndroid Build Coastguard Worker                 empty.portId = devicePort.id;
545*4d7e907cSAndroid Build Coastguard Worker                 empty.ext = devicePort.ext;
546*4d7e907cSAndroid Build Coastguard Worker                 result.push_back(empty);
547*4d7e907cSAndroid Build Coastguard Worker             }
548*4d7e907cSAndroid Build Coastguard Worker         }
549*4d7e907cSAndroid Build Coastguard Worker         if (singleProfile) return result;
550*4d7e907cSAndroid Build Coastguard Worker     }
551*4d7e907cSAndroid Build Coastguard Worker     return result;
552*4d7e907cSAndroid Build Coastguard Worker }
553*4d7e907cSAndroid Build Coastguard Worker 
getPort(int32_t portId)554*4d7e907cSAndroid Build Coastguard Worker std::optional<AudioPort> ModuleConfig::getPort(int32_t portId) {
555*4d7e907cSAndroid Build Coastguard Worker     auto portsIt = findById(mPorts, portId);
556*4d7e907cSAndroid Build Coastguard Worker     return portsIt != mPorts.end() ? std::optional<AudioPort>(*portsIt) : std::nullopt;
557*4d7e907cSAndroid Build Coastguard Worker }
558*4d7e907cSAndroid Build Coastguard Worker 
onExternalDeviceConnected(IModule * module,const AudioPort & port)559*4d7e907cSAndroid Build Coastguard Worker ndk::ScopedAStatus ModuleConfig::onExternalDeviceConnected(IModule* module, const AudioPort& port) {
560*4d7e907cSAndroid Build Coastguard Worker     RETURN_STATUS_IF_ERROR(module->getAudioPorts(&mPorts));
561*4d7e907cSAndroid Build Coastguard Worker     RETURN_STATUS_IF_ERROR(module->getAudioRoutes(&mRoutes));
562*4d7e907cSAndroid Build Coastguard Worker 
563*4d7e907cSAndroid Build Coastguard Worker     // Validate port is present in module
564*4d7e907cSAndroid Build Coastguard Worker     if (std::find(mPorts.begin(), mPorts.end(), port) == mPorts.end()) {
565*4d7e907cSAndroid Build Coastguard Worker         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
566*4d7e907cSAndroid Build Coastguard Worker     }
567*4d7e907cSAndroid Build Coastguard Worker 
568*4d7e907cSAndroid Build Coastguard Worker     if (port.flags.getTag() == aidl::android::media::audio::common::AudioIoFlags::Tag::input) {
569*4d7e907cSAndroid Build Coastguard Worker         mConnectedExternalSourceDevicePorts.insert(port.id);
570*4d7e907cSAndroid Build Coastguard Worker     } else {
571*4d7e907cSAndroid Build Coastguard Worker         mConnectedExternalSinkDevicePorts.insert(port.id);
572*4d7e907cSAndroid Build Coastguard Worker     }
573*4d7e907cSAndroid Build Coastguard Worker     return ndk::ScopedAStatus::ok();
574*4d7e907cSAndroid Build Coastguard Worker }
575*4d7e907cSAndroid Build Coastguard Worker 
onExternalDeviceDisconnected(IModule * module,const AudioPort & port)576*4d7e907cSAndroid Build Coastguard Worker ndk::ScopedAStatus ModuleConfig::onExternalDeviceDisconnected(IModule* module,
577*4d7e907cSAndroid Build Coastguard Worker                                                               const AudioPort& port) {
578*4d7e907cSAndroid Build Coastguard Worker     RETURN_STATUS_IF_ERROR(module->getAudioPorts(&mPorts));
579*4d7e907cSAndroid Build Coastguard Worker     RETURN_STATUS_IF_ERROR(module->getAudioRoutes(&mRoutes));
580*4d7e907cSAndroid Build Coastguard Worker 
581*4d7e907cSAndroid Build Coastguard Worker     if (port.flags.getTag() == aidl::android::media::audio::common::AudioIoFlags::Tag::input) {
582*4d7e907cSAndroid Build Coastguard Worker         mConnectedExternalSourceDevicePorts.erase(port.id);
583*4d7e907cSAndroid Build Coastguard Worker     } else {
584*4d7e907cSAndroid Build Coastguard Worker         mConnectedExternalSinkDevicePorts.erase(port.id);
585*4d7e907cSAndroid Build Coastguard Worker     }
586*4d7e907cSAndroid Build Coastguard Worker     return ndk::ScopedAStatus::ok();
587*4d7e907cSAndroid Build Coastguard Worker }
588*4d7e907cSAndroid Build Coastguard Worker 
isMmapSupported() const589*4d7e907cSAndroid Build Coastguard Worker bool ModuleConfig::isMmapSupported() const {
590*4d7e907cSAndroid Build Coastguard Worker     const std::vector<AudioPort> mmapOutMixPorts =
591*4d7e907cSAndroid Build Coastguard Worker             getMmapOutMixPorts(false /*connectedOnly*/, false /*singlePort*/);
592*4d7e907cSAndroid Build Coastguard Worker     const std::vector<AudioPort> mmapInMixPorts =
593*4d7e907cSAndroid Build Coastguard Worker             getMmapInMixPorts(false /*connectedOnly*/, false /*singlePort*/);
594*4d7e907cSAndroid Build Coastguard Worker     return !mmapOutMixPorts.empty() || !mmapInMixPorts.empty();
595*4d7e907cSAndroid Build Coastguard Worker }
596