1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <Utils.h>
18 #include <aidl/android/media/audio/common/AudioChannelLayout.h>
19 #include <aidl/android/media/audio/common/AudioDeviceType.h>
20 #include <aidl/android/media/audio/common/AudioFormatDescription.h>
21 #include <aidl/android/media/audio/common/AudioFormatType.h>
22 #include <aidl/android/media/audio/common/AudioIoFlags.h>
23 #include <aidl/android/media/audio/common/AudioOutputFlags.h>
24 #include <media/stagefright/foundation/MediaDefs.h>
25 
26 #include "core-impl/Configuration.h"
27 
28 using aidl::android::hardware::audio::common::makeBitPositionFlagMask;
29 using aidl::android::media::audio::common::AudioChannelLayout;
30 using aidl::android::media::audio::common::AudioDeviceDescription;
31 using aidl::android::media::audio::common::AudioDeviceType;
32 using aidl::android::media::audio::common::AudioFormatDescription;
33 using aidl::android::media::audio::common::AudioFormatType;
34 using aidl::android::media::audio::common::AudioGainConfig;
35 using aidl::android::media::audio::common::AudioIoFlags;
36 using aidl::android::media::audio::common::AudioOutputFlags;
37 using aidl::android::media::audio::common::AudioPort;
38 using aidl::android::media::audio::common::AudioPortConfig;
39 using aidl::android::media::audio::common::AudioPortDeviceExt;
40 using aidl::android::media::audio::common::AudioPortExt;
41 using aidl::android::media::audio::common::AudioPortMixExt;
42 using aidl::android::media::audio::common::AudioProfile;
43 using aidl::android::media::audio::common::Int;
44 using aidl::android::media::audio::common::MicrophoneInfo;
45 using aidl::android::media::audio::common::PcmType;
46 
47 namespace aidl::android::hardware::audio::core::internal {
48 
fillProfile(AudioProfile * profile,const std::vector<int32_t> & channelLayouts,const std::vector<int32_t> & sampleRates)49 static void fillProfile(AudioProfile* profile, const std::vector<int32_t>& channelLayouts,
50                         const std::vector<int32_t>& sampleRates) {
51     for (auto layout : channelLayouts) {
52         profile->channelMasks.push_back(
53                 AudioChannelLayout::make<AudioChannelLayout::layoutMask>(layout));
54     }
55     profile->sampleRates.insert(profile->sampleRates.end(), sampleRates.begin(), sampleRates.end());
56 }
57 
createProfile(PcmType pcmType,const std::vector<int32_t> & channelLayouts,const std::vector<int32_t> & sampleRates)58 static AudioProfile createProfile(PcmType pcmType, const std::vector<int32_t>& channelLayouts,
59                                   const std::vector<int32_t>& sampleRates) {
60     AudioProfile profile;
61     profile.format.type = AudioFormatType::PCM;
62     profile.format.pcm = pcmType;
63     fillProfile(&profile, channelLayouts, sampleRates);
64     return profile;
65 }
66 
createProfile(const std::string & encodingType,const std::vector<int32_t> & channelLayouts,const std::vector<int32_t> & sampleRates)67 static AudioProfile createProfile(const std::string& encodingType,
68                                   const std::vector<int32_t>& channelLayouts,
69                                   const std::vector<int32_t>& sampleRates) {
70     AudioProfile profile;
71     profile.format.encoding = encodingType;
72     fillProfile(&profile, channelLayouts, sampleRates);
73     return profile;
74 }
75 
createDeviceExt(AudioDeviceType devType,int32_t flags,std::string connection="")76 static AudioPortExt createDeviceExt(AudioDeviceType devType, int32_t flags,
77                                     std::string connection = "") {
78     AudioPortDeviceExt deviceExt;
79     deviceExt.device.type.type = devType;
80     if (devType == AudioDeviceType::IN_MICROPHONE && connection.empty()) {
81         deviceExt.device.address = "bottom";
82     } else if (devType == AudioDeviceType::IN_MICROPHONE_BACK && connection.empty()) {
83         deviceExt.device.address = "back";
84     }
85     deviceExt.device.type.connection = std::move(connection);
86     deviceExt.flags = flags;
87     return AudioPortExt::make<AudioPortExt::Tag::device>(deviceExt);
88 }
89 
createPortMixExt(int32_t maxOpenStreamCount,int32_t maxActiveStreamCount)90 static AudioPortExt createPortMixExt(int32_t maxOpenStreamCount, int32_t maxActiveStreamCount) {
91     AudioPortMixExt mixExt;
92     mixExt.maxOpenStreamCount = maxOpenStreamCount;
93     mixExt.maxActiveStreamCount = maxActiveStreamCount;
94     return AudioPortExt::make<AudioPortExt::Tag::mix>(mixExt);
95 }
96 
createPort(int32_t id,const std::string & name,int32_t flags,bool isInput,const AudioPortExt & ext)97 static AudioPort createPort(int32_t id, const std::string& name, int32_t flags, bool isInput,
98                             const AudioPortExt& ext) {
99     AudioPort port;
100     port.id = id;
101     port.name = name;
102     port.flags = isInput ? AudioIoFlags::make<AudioIoFlags::Tag::input>(flags)
103                          : AudioIoFlags::make<AudioIoFlags::Tag::output>(flags);
104     port.ext = ext;
105     return port;
106 }
107 
createPortConfig(int32_t id,int32_t portId,PcmType pcmType,int32_t layout,int32_t sampleRate,int32_t flags,bool isInput,const AudioPortExt & ext)108 static AudioPortConfig createPortConfig(int32_t id, int32_t portId, PcmType pcmType, int32_t layout,
109                                         int32_t sampleRate, int32_t flags, bool isInput,
110                                         const AudioPortExt& ext) {
111     AudioPortConfig config;
112     config.id = id;
113     config.portId = portId;
114     config.sampleRate = Int{.value = sampleRate};
115     config.channelMask = AudioChannelLayout::make<AudioChannelLayout::layoutMask>(layout);
116     config.format = AudioFormatDescription{.type = AudioFormatType::PCM, .pcm = pcmType};
117     config.gain = AudioGainConfig();
118     config.flags = isInput ? AudioIoFlags::make<AudioIoFlags::Tag::input>(flags)
119                            : AudioIoFlags::make<AudioIoFlags::Tag::output>(flags);
120     config.ext = ext;
121     return config;
122 }
123 
createRoute(const std::vector<AudioPort> & sources,const AudioPort & sink)124 static AudioRoute createRoute(const std::vector<AudioPort>& sources, const AudioPort& sink) {
125     AudioRoute route;
126     route.sinkPortId = sink.id;
127     std::transform(sources.begin(), sources.end(), std::back_inserter(route.sourcePortIds),
128                    [](const auto& port) { return port.id; });
129     return route;
130 }
131 
132 // Primary (default) configuration:
133 //
134 // Device ports:
135 //  * "Speaker", OUT_SPEAKER, default
136 //    - no profiles specified
137 //  * "Built-In Mic", IN_MICROPHONE, default
138 //    - no profiles specified
139 //  * "Telephony Tx", OUT_TELEPHONY_TX
140 //    - no profiles specified
141 //  * "Telephony Rx", IN_TELEPHONY_RX
142 //    - no profiles specified
143 //  * "FM Tuner", IN_FM_TUNER
144 //    - no profiles specified
145 //
146 // Mix ports:
147 //  * "primary output", PRIMARY, 1 max open, 1 max active stream
148 //    - profile PCM 16-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
149 //  * "primary input", 1 max open, 1 max active stream
150 //    - profile PCM 16-bit; MONO, STEREO;
151 //        8000, 11025, 16000, 32000, 44100, 48000
152 //  * "telephony_tx", 1 max open, 1 max active stream
153 //    - profile PCM 16-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
154 //  * "telephony_rx", 1 max open, 1 max active stream
155 //    - profile PCM 16-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
156 //  * "fm_tuner", 1 max open, 1 max active stream
157 //    - profile PCM 16-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
158 //
159 // Routes:
160 //  "primary out" -> "Speaker"
161 //  "Built-In Mic" -> "primary input"
162 //  "Telephony Rx" -> "telephony_rx"
163 //  "telephony_tx" -> "Telephony Tx"
164 //  "FM Tuner" -> "fm_tuner"
165 //
166 // Initial port configs:
167 //  * "Speaker" device port: PCM 16-bit; STEREO; 48000
168 //  * "Built-In Mic" device port: PCM 16-bit; MONO; 48000
169 //  * "Telephony Tx" device port: PCM 16-bit; MONO; 48000
170 //  * "Telephony Rx" device port: PCM 16-bit; MONO; 48000
171 //  * "FM Tuner" device port: PCM 16-bit; STEREO; 48000
172 //
getPrimaryConfiguration()173 std::unique_ptr<Configuration> getPrimaryConfiguration() {
174     static const Configuration configuration = []() {
175         const std::vector<AudioProfile> standardPcmAudioProfiles = {
176                 createProfile(PcmType::INT_16_BIT,
177                               {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO},
178                               {8000, 11025, 16000, 32000, 44100, 48000})};
179         Configuration c;
180 
181         // Device ports
182 
183         AudioPort speakerOutDevice =
184                 createPort(c.nextPortId++, "Speaker", 0, false,
185                            createDeviceExt(AudioDeviceType::OUT_SPEAKER,
186                                            1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE));
187         c.ports.push_back(speakerOutDevice);
188         c.initialConfigs.push_back(
189                 createPortConfig(speakerOutDevice.id, speakerOutDevice.id, PcmType::INT_16_BIT,
190                                  AudioChannelLayout::LAYOUT_STEREO, 48000, 0, false,
191                                  createDeviceExt(AudioDeviceType::OUT_SPEAKER, 0)));
192 
193         AudioPort micInDevice =
194                 createPort(c.nextPortId++, "Built-In Mic", 0, true,
195                            createDeviceExt(AudioDeviceType::IN_MICROPHONE,
196                                            1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE));
197         c.ports.push_back(micInDevice);
198         c.initialConfigs.push_back(
199                 createPortConfig(micInDevice.id, micInDevice.id, PcmType::INT_16_BIT,
200                                  AudioChannelLayout::LAYOUT_MONO, 48000, 0, true,
201                                  createDeviceExt(AudioDeviceType::IN_MICROPHONE, 0)));
202 
203         AudioPort telephonyTxOutDevice =
204                 createPort(c.nextPortId++, "Telephony Tx", 0, false,
205                            createDeviceExt(AudioDeviceType::OUT_TELEPHONY_TX, 0));
206         c.ports.push_back(telephonyTxOutDevice);
207         c.initialConfigs.push_back(
208                 createPortConfig(telephonyTxOutDevice.id, telephonyTxOutDevice.id,
209                                  PcmType::INT_16_BIT, AudioChannelLayout::LAYOUT_MONO, 48000, 0,
210                                  false, createDeviceExt(AudioDeviceType::OUT_TELEPHONY_TX, 0)));
211 
212         AudioPort telephonyRxInDevice =
213                 createPort(c.nextPortId++, "Telephony Rx", 0, true,
214                            createDeviceExt(AudioDeviceType::IN_TELEPHONY_RX, 0));
215         c.ports.push_back(telephonyRxInDevice);
216         c.initialConfigs.push_back(
217                 createPortConfig(telephonyRxInDevice.id, telephonyRxInDevice.id,
218                                  PcmType::INT_16_BIT, AudioChannelLayout::LAYOUT_MONO, 48000, 0,
219                                  true, createDeviceExt(AudioDeviceType::IN_TELEPHONY_RX, 0)));
220 
221         AudioPort fmTunerInDevice = createPort(c.nextPortId++, "FM Tuner", 0, true,
222                                                createDeviceExt(AudioDeviceType::IN_FM_TUNER, 0));
223         c.ports.push_back(fmTunerInDevice);
224         c.initialConfigs.push_back(
225                 createPortConfig(fmTunerInDevice.id, fmTunerInDevice.id, PcmType::INT_16_BIT,
226                                  AudioChannelLayout::LAYOUT_STEREO, 48000, 0, true,
227                                  createDeviceExt(AudioDeviceType::IN_FM_TUNER, 0)));
228 
229         // Mix ports
230 
231         AudioPort primaryOutMix = createPort(c.nextPortId++, "primary output",
232                                              makeBitPositionFlagMask(AudioOutputFlags::PRIMARY),
233                                              false, createPortMixExt(0, 0));
234         primaryOutMix.profiles.insert(primaryOutMix.profiles.begin(),
235                                       standardPcmAudioProfiles.begin(),
236                                       standardPcmAudioProfiles.end());
237         c.ports.push_back(primaryOutMix);
238 
239         AudioPort primaryInMix =
240                 createPort(c.nextPortId++, "primary input", 0, true, createPortMixExt(0, 0));
241         primaryInMix.profiles.push_back(
242                 createProfile(PcmType::INT_16_BIT,
243                               {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO},
244                               {8000, 11025, 16000, 32000, 44100, 48000}));
245         c.ports.push_back(primaryInMix);
246 
247         AudioPort telephonyTxOutMix =
248                 createPort(c.nextPortId++, "telephony_tx", 0, false, createPortMixExt(1, 1));
249         telephonyTxOutMix.profiles.insert(telephonyTxOutMix.profiles.begin(),
250                                           standardPcmAudioProfiles.begin(),
251                                           standardPcmAudioProfiles.end());
252         c.ports.push_back(telephonyTxOutMix);
253 
254         AudioPort telephonyRxInMix =
255                 createPort(c.nextPortId++, "telephony_rx", 0, true, createPortMixExt(1, 1));
256         telephonyRxInMix.profiles.insert(telephonyRxInMix.profiles.begin(),
257                                          standardPcmAudioProfiles.begin(),
258                                          standardPcmAudioProfiles.end());
259         c.ports.push_back(telephonyRxInMix);
260 
261         AudioPort fmTunerInMix =
262                 createPort(c.nextPortId++, "fm_tuner", 0, true, createPortMixExt(1, 1));
263         fmTunerInMix.profiles.insert(fmTunerInMix.profiles.begin(),
264                                      standardPcmAudioProfiles.begin(),
265                                      standardPcmAudioProfiles.end());
266         c.ports.push_back(fmTunerInMix);
267 
268         c.routes.push_back(createRoute({primaryOutMix}, speakerOutDevice));
269         c.routes.push_back(createRoute({micInDevice}, primaryInMix));
270         c.routes.push_back(createRoute({telephonyRxInDevice}, telephonyRxInMix));
271         c.routes.push_back(createRoute({telephonyTxOutMix}, telephonyTxOutDevice));
272         c.routes.push_back(createRoute({fmTunerInDevice}, fmTunerInMix));
273 
274         c.portConfigs.insert(c.portConfigs.end(), c.initialConfigs.begin(), c.initialConfigs.end());
275 
276         MicrophoneInfo mic;
277         mic.id = "mic";
278         mic.device = micInDevice.ext.get<AudioPortExt::Tag::device>().device;
279         mic.group = 0;
280         mic.indexInTheGroup = 0;
281         c.microphones = std::vector<MicrophoneInfo>{mic};
282 
283         return c;
284     }();
285     return std::make_unique<Configuration>(configuration);
286 }
287 
288 // Remote Submix configuration:
289 //
290 // Device ports:
291 //  * "Remote Submix Out", OUT_SUBMIX
292 //    - no profiles specified
293 //  * "Remote Submix In", IN_SUBMIX
294 //    - no profiles specified
295 //
296 // Mix ports:
297 //  * "r_submix output", unlimited max open, unlimited max active stream
298 //    - profile PCM 16-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
299 //    - profile PCM 24-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
300 //    - profile PCM 32-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
301 //    - profile PCM 32-bit float; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
302 //  * "r_submix input", unlimited max open, unlimited max active stream
303 //    - profile PCM 16-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
304 //    - profile PCM 24-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
305 //    - profile PCM 32-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
306 //    - profile PCM 32-bit float; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
307 //
308 // Routes:
309 //  "r_submix output" -> "Remote Submix Out"
310 //  "Remote Submix In" -> "r_submix input"
311 //
getRSubmixConfiguration()312 std::unique_ptr<Configuration> getRSubmixConfiguration() {
313     static const Configuration configuration = []() {
314         Configuration c;
315         const std::vector<AudioProfile> standardPcmAudioProfiles{
316                 createProfile(PcmType::FLOAT_32_BIT,
317                               {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO},
318                               {8000, 11025, 16000, 32000, 44100, 48000}),
319                 createProfile(PcmType::INT_32_BIT,
320                               {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO},
321                               {8000, 11025, 16000, 32000, 44100, 48000}),
322                 createProfile(PcmType::INT_24_BIT,
323                               {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO},
324                               {8000, 11025, 16000, 32000, 44100, 48000}),
325                 createProfile(PcmType::INT_16_BIT,
326                               {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO},
327                               {8000, 11025, 16000, 32000, 44100, 48000})};
328 
329         // Device ports
330 
331         AudioPort rsubmixOutDevice =
332                 createPort(c.nextPortId++, "Remote Submix Out", 0, false,
333                            createDeviceExt(AudioDeviceType::OUT_SUBMIX, 0,
334                                            AudioDeviceDescription::CONNECTION_VIRTUAL));
335         c.ports.push_back(rsubmixOutDevice);
336         c.connectedProfiles[rsubmixOutDevice.id] = standardPcmAudioProfiles;
337 
338         AudioPort rsubmixInDevice =
339                 createPort(c.nextPortId++, "Remote Submix In", 0, true,
340                            createDeviceExt(AudioDeviceType::IN_SUBMIX, 0,
341                                            AudioDeviceDescription::CONNECTION_VIRTUAL));
342         c.ports.push_back(rsubmixInDevice);
343         c.connectedProfiles[rsubmixInDevice.id] = standardPcmAudioProfiles;
344 
345         // Mix ports
346 
347         AudioPort rsubmixOutMix =
348                 createPort(c.nextPortId++, "r_submix output", 0, false, createPortMixExt(0, 0));
349         rsubmixOutMix.profiles = standardPcmAudioProfiles;
350         c.ports.push_back(rsubmixOutMix);
351 
352         AudioPort rsubmixInMix =
353                 createPort(c.nextPortId++, "r_submix input", 0, true, createPortMixExt(0, 0));
354         rsubmixInMix.profiles = standardPcmAudioProfiles;
355         c.ports.push_back(rsubmixInMix);
356 
357         c.routes.push_back(createRoute({rsubmixOutMix}, rsubmixOutDevice));
358         c.routes.push_back(createRoute({rsubmixInDevice}, rsubmixInMix));
359 
360         return c;
361     }();
362     return std::make_unique<Configuration>(configuration);
363 }
364 
365 // Usb configuration:
366 //
367 // Device ports:
368 //  * "USB Device Out", OUT_DEVICE, CONNECTION_USB
369 //    - no profiles specified
370 //  * "USB Headset Out", OUT_HEADSET, CONNECTION_USB
371 //    - no profiles specified
372 //  * "USB Device In", IN_DEVICE, CONNECTION_USB
373 //    - no profiles specified
374 //  * "USB Headset In", IN_HEADSET, CONNECTION_USB
375 //    - no profiles specified
376 //
377 // Mix ports:
378 //  * "usb_device output", 1 max open, 1 max active stream
379 //    - no profiles specified
380 //  * "usb_device input", 1 max open, 1 max active stream
381 //    - no profiles specified
382 //
383 // Routes:
384 //  * "usb_device output" -> "USB Device Out"
385 //  * "usb_device output" -> "USB Headset Out"
386 //  * "USB Device In", "USB Headset In" -> "usb_device input"
387 //
388 // Profiles for device port connected state:
389 //  * "USB Device Out", "USB Headset Out":
390 //    - profile PCM 16-bit; MONO, STEREO, INDEX_MASK_1, INDEX_MASK_2; 44100, 48000
391 //    - profile PCM 24-bit; MONO, STEREO, INDEX_MASK_1, INDEX_MASK_2; 44100, 48000
392 //  * "USB Device In", "USB Headset In":
393 //    - profile PCM 16-bit; MONO, STEREO, INDEX_MASK_1, INDEX_MASK_2; 44100, 48000
394 //    - profile PCM 24-bit; MONO, STEREO, INDEX_MASK_1, INDEX_MASK_2; 44100, 48000
395 //
getUsbConfiguration()396 std::unique_ptr<Configuration> getUsbConfiguration() {
397     static const Configuration configuration = []() {
398         const std::vector<AudioProfile> standardPcmAudioProfiles = {
399                 createProfile(PcmType::INT_16_BIT,
400                               {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO,
401                                AudioChannelLayout::INDEX_MASK_1, AudioChannelLayout::INDEX_MASK_2},
402                               {44100, 48000}),
403                 createProfile(PcmType::INT_24_BIT,
404                               {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO,
405                                AudioChannelLayout::INDEX_MASK_1, AudioChannelLayout::INDEX_MASK_2},
406                               {44100, 48000})};
407         Configuration c;
408 
409         // Device ports
410 
411         AudioPort usbOutDevice =
412                 createPort(c.nextPortId++, "USB Device Out", 0, false,
413                            createDeviceExt(AudioDeviceType::OUT_DEVICE, 0,
414                                            AudioDeviceDescription::CONNECTION_USB));
415         c.ports.push_back(usbOutDevice);
416         c.connectedProfiles[usbOutDevice.id] = standardPcmAudioProfiles;
417 
418         AudioPort usbOutHeadset =
419                 createPort(c.nextPortId++, "USB Headset Out", 0, false,
420                            createDeviceExt(AudioDeviceType::OUT_HEADSET, 0,
421                                            AudioDeviceDescription::CONNECTION_USB));
422         c.ports.push_back(usbOutHeadset);
423         c.connectedProfiles[usbOutHeadset.id] = standardPcmAudioProfiles;
424 
425         AudioPort usbInDevice = createPort(c.nextPortId++, "USB Device In", 0, true,
426                                            createDeviceExt(AudioDeviceType::IN_DEVICE, 0,
427                                                            AudioDeviceDescription::CONNECTION_USB));
428         c.ports.push_back(usbInDevice);
429         c.connectedProfiles[usbInDevice.id] = standardPcmAudioProfiles;
430 
431         AudioPort usbInHeadset =
432                 createPort(c.nextPortId++, "USB Headset In", 0, true,
433                            createDeviceExt(AudioDeviceType::IN_HEADSET, 0,
434                                            AudioDeviceDescription::CONNECTION_USB));
435         c.ports.push_back(usbInHeadset);
436         c.connectedProfiles[usbInHeadset.id] = standardPcmAudioProfiles;
437 
438         // Mix ports
439 
440         AudioPort usbDeviceOutMix =
441                 createPort(c.nextPortId++, "usb_device output", 0, false, createPortMixExt(1, 1));
442         c.ports.push_back(usbDeviceOutMix);
443 
444         AudioPort usbDeviceInMix =
445                 createPort(c.nextPortId++, "usb_device input", 0, true, createPortMixExt(1, 1));
446         c.ports.push_back(usbDeviceInMix);
447 
448         c.routes.push_back(createRoute({usbDeviceOutMix}, usbOutDevice));
449         c.routes.push_back(createRoute({usbDeviceOutMix}, usbOutHeadset));
450         c.routes.push_back(createRoute({usbInDevice, usbInHeadset}, usbDeviceInMix));
451 
452         return c;
453     }();
454     return std::make_unique<Configuration>(configuration);
455 }
456 
457 // Stub configuration:
458 //
459 // Device ports:
460 //  * "Test Out", OUT_AFE_PROXY
461 //    - no profiles specified
462 //  * "Test In", IN_AFE_PROXY
463 //    - no profiles specified
464 //  * "Wired Headset", OUT_HEADSET
465 //    - profile PCM 24-bit; STEREO; 48000
466 //  * "Wired Headset Mic", IN_HEADSET
467 //    - profile PCM 24-bit; MONO; 48000
468 //
469 // Mix ports:
470 //  * "test output", 1 max open, 1 max active stream
471 //    - profile PCM 24-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
472 //  * "test fast output", 1 max open, 1 max active stream
473 //    - profile PCM 24-bit; STEREO; 44100, 48000
474 //  * "test compressed offload", DIRECT|COMPRESS_OFFLOAD|NON_BLOCKING, 1 max open, 1 max active
475 //  stream
476 //    - profile MP3; MONO, STEREO; 44100, 48000
477 //  * "test input", 2 max open, 2 max active streams
478 //    - profile PCM 24-bit; MONO, STEREO, FRONT_BACK;
479 //        8000, 11025, 16000, 22050, 32000, 44100, 48000
480 //
481 // Routes:
482 //  "test output", "test fast output", "test compressed offload" -> "Test Out"
483 //  "test output" -> "Wired Headset"
484 //  "Test In", "Wired Headset Mic" -> "test input"
485 //
486 // Initial port configs:
487 //  * "Test Out" device port: PCM 24-bit; STEREO; 48000
488 //  * "Test In" device port: PCM 24-bit; MONO; 48000
489 //
getStubConfiguration()490 std::unique_ptr<Configuration> getStubConfiguration() {
491     static const Configuration configuration = []() {
492         Configuration c;
493 
494         // Device ports
495 
496         AudioPort testOutDevice = createPort(c.nextPortId++, "Test Out", 0, false,
497                                              createDeviceExt(AudioDeviceType::OUT_AFE_PROXY, 0));
498         c.ports.push_back(testOutDevice);
499         c.initialConfigs.push_back(
500                 createPortConfig(testOutDevice.id, testOutDevice.id, PcmType::INT_24_BIT,
501                                  AudioChannelLayout::LAYOUT_STEREO, 48000, 0, false,
502                                  createDeviceExt(AudioDeviceType::OUT_AFE_PROXY, 0)));
503 
504         AudioPort headsetOutDevice =
505                 createPort(c.nextPortId++, "Wired Headset", 0, false,
506                            createDeviceExt(AudioDeviceType::OUT_HEADSET, 0,
507                                            AudioDeviceDescription::CONNECTION_ANALOG));
508         headsetOutDevice.profiles.push_back(
509                 createProfile(PcmType::INT_24_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {48000}));
510         c.ports.push_back(headsetOutDevice);
511 
512         AudioPort testInDevice = createPort(c.nextPortId++, "Test In", 0, true,
513                                             createDeviceExt(AudioDeviceType::IN_AFE_PROXY, 0));
514         c.ports.push_back(testInDevice);
515         c.initialConfigs.push_back(
516                 createPortConfig(testInDevice.id, testInDevice.id, PcmType::INT_24_BIT,
517                                  AudioChannelLayout::LAYOUT_MONO, 48000, 0, true,
518                                  createDeviceExt(AudioDeviceType::IN_AFE_PROXY, 0)));
519 
520         AudioPort headsetInDevice =
521                 createPort(c.nextPortId++, "Wired Headset Mic", 0, true,
522                            createDeviceExt(AudioDeviceType::IN_HEADSET, 0,
523                                            AudioDeviceDescription::CONNECTION_ANALOG));
524         headsetInDevice.profiles.push_back(
525                 createProfile(PcmType::INT_24_BIT, {AudioChannelLayout::LAYOUT_MONO}, {48000}));
526         c.ports.push_back(headsetInDevice);
527 
528         // Mix ports
529 
530         AudioPort testOutMix =
531                 createPort(c.nextPortId++, "test output", 0, false, createPortMixExt(1, 1));
532         testOutMix.profiles.push_back(
533                 createProfile(PcmType::INT_24_BIT,
534                               {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO},
535                               {8000, 11025, 16000, 32000, 44100, 48000}));
536         c.ports.push_back(testOutMix);
537 
538         AudioPort testFastOutMix = createPort(c.nextPortId++, "test fast output",
539                                               makeBitPositionFlagMask({AudioOutputFlags::FAST}),
540                                               false, createPortMixExt(1, 1));
541         testFastOutMix.profiles.push_back(createProfile(
542                 PcmType::INT_24_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {44100, 48000}));
543         c.ports.push_back(testFastOutMix);
544 
545         AudioPort compressedOffloadOutMix =
546                 createPort(c.nextPortId++, "test compressed offload",
547                            makeBitPositionFlagMask({AudioOutputFlags::DIRECT,
548                                                     AudioOutputFlags::COMPRESS_OFFLOAD,
549                                                     AudioOutputFlags::NON_BLOCKING}),
550                            false, createPortMixExt(1, 1));
551         compressedOffloadOutMix.profiles.push_back(
552                 createProfile(::android::MEDIA_MIMETYPE_AUDIO_MPEG,
553                               {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO},
554                               {44100, 48000}));
555         c.ports.push_back(compressedOffloadOutMix);
556 
557         AudioPort testInMIx =
558                 createPort(c.nextPortId++, "test input", 0, true, createPortMixExt(2, 2));
559         testInMIx.profiles.push_back(
560                 createProfile(PcmType::INT_16_BIT,
561                               {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO,
562                                AudioChannelLayout::LAYOUT_FRONT_BACK},
563                               {8000, 11025, 16000, 22050, 32000, 44100, 48000}));
564         testInMIx.profiles.push_back(
565                 createProfile(PcmType::INT_24_BIT,
566                               {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO,
567                                AudioChannelLayout::LAYOUT_FRONT_BACK},
568                               {8000, 11025, 16000, 22050, 32000, 44100, 48000}));
569         c.ports.push_back(testInMIx);
570 
571         c.routes.push_back(
572                 createRoute({testOutMix, testFastOutMix, compressedOffloadOutMix}, testOutDevice));
573         c.routes.push_back(createRoute({testOutMix}, headsetOutDevice));
574         c.routes.push_back(createRoute({testInDevice, headsetInDevice}, testInMIx));
575 
576         c.portConfigs.insert(c.portConfigs.end(), c.initialConfigs.begin(), c.initialConfigs.end());
577 
578         return c;
579     }();
580     return std::make_unique<Configuration>(configuration);
581 }
582 
583 // Bluetooth configuration:
584 //
585 // Device ports:
586 //  * "BT A2DP Out", OUT_DEVICE, CONNECTION_BT_A2DP
587 //    - profile PCM 16-bit; STEREO; 44100, 48000, 88200, 96000
588 //  * "BT A2DP Headphones", OUT_HEADPHONE, CONNECTION_BT_A2DP
589 //    - profile PCM 16-bit; STEREO; 44100, 48000, 88200, 96000
590 //  * "BT A2DP Speaker", OUT_SPEAKER, CONNECTION_BT_A2DP
591 //    - profile PCM 16-bit; STEREO; 44100, 48000, 88200, 96000
592 //  * "BT Hearing Aid Out", OUT_HEARING_AID, CONNECTION_WIRELESS
593 //    - no profiles specified
594 //
595 // Mix ports:
596 //  * "a2dp output", 1 max open, 1 max active stream
597 //    - no profiles specified
598 //  * "hearing aid output", 1 max open, 1 max active stream
599 //    - profile PCM 16-bit; STEREO; 16000, 24000
600 //
601 // Routes:
602 //  "a2dp output" -> "BT A2DP Out"
603 //  "a2dp output" -> "BT A2DP Headphones"
604 //  "a2dp output" -> "BT A2DP Speaker"
605 //  "hearing aid output" -> "BT Hearing Aid Out"
606 //
getBluetoothConfiguration()607 std::unique_ptr<Configuration> getBluetoothConfiguration() {
608     static const Configuration configuration = []() {
609         const std::vector<AudioProfile> standardPcmAudioProfiles = {
610                 createProfile(PcmType::INT_16_BIT, {AudioChannelLayout::LAYOUT_STEREO},
611                               {44100, 48000, 88200, 96000})};
612         Configuration c;
613 
614         // Device ports
615         AudioPort btOutDevice =
616                 createPort(c.nextPortId++, "BT A2DP Out", 0, false,
617                            createDeviceExt(AudioDeviceType::OUT_DEVICE, 0,
618                                            AudioDeviceDescription::CONNECTION_BT_A2DP));
619         btOutDevice.profiles.insert(btOutDevice.profiles.begin(), standardPcmAudioProfiles.begin(),
620                                     standardPcmAudioProfiles.end());
621         c.ports.push_back(btOutDevice);
622         c.connectedProfiles[btOutDevice.id] = standardPcmAudioProfiles;
623 
624         AudioPort btOutHeadphone =
625                 createPort(c.nextPortId++, "BT A2DP Headphones", 0, false,
626                            createDeviceExt(AudioDeviceType::OUT_HEADPHONE, 0,
627                                            AudioDeviceDescription::CONNECTION_BT_A2DP));
628         btOutHeadphone.profiles.insert(btOutHeadphone.profiles.begin(),
629                                        standardPcmAudioProfiles.begin(),
630                                        standardPcmAudioProfiles.end());
631         c.ports.push_back(btOutHeadphone);
632         c.connectedProfiles[btOutHeadphone.id] = standardPcmAudioProfiles;
633 
634         AudioPort btOutSpeaker =
635                 createPort(c.nextPortId++, "BT A2DP Speaker", 0, false,
636                            createDeviceExt(AudioDeviceType::OUT_SPEAKER, 0,
637                                            AudioDeviceDescription::CONNECTION_BT_A2DP));
638         btOutSpeaker.profiles.insert(btOutSpeaker.profiles.begin(),
639                                      standardPcmAudioProfiles.begin(),
640                                      standardPcmAudioProfiles.end());
641         c.ports.push_back(btOutSpeaker);
642         c.connectedProfiles[btOutSpeaker.id] = standardPcmAudioProfiles;
643 
644         AudioPort btOutHearingAid =
645                 createPort(c.nextPortId++, "BT Hearing Aid Out", 0, false,
646                            createDeviceExt(AudioDeviceType::OUT_HEARING_AID, 0,
647                                            AudioDeviceDescription::CONNECTION_WIRELESS));
648         c.ports.push_back(btOutHearingAid);
649         c.connectedProfiles[btOutHearingAid.id] = std::vector<AudioProfile>(
650                 {createProfile(PcmType::INT_16_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {16000})});
651 
652         // Mix ports
653         AudioPort btOutMix =
654                 createPort(c.nextPortId++, "a2dp output", 0, false, createPortMixExt(1, 1));
655         c.ports.push_back(btOutMix);
656 
657         AudioPort btHearingOutMix =
658                 createPort(c.nextPortId++, "hearing aid output", 0, false, createPortMixExt(1, 1));
659         btHearingOutMix.profiles.push_back(createProfile(
660                 PcmType::INT_16_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {16000, 24000}));
661         c.ports.push_back(btHearingOutMix);
662 
663         c.routes.push_back(createRoute({btOutMix}, btOutDevice));
664         c.routes.push_back(createRoute({btOutMix}, btOutHeadphone));
665         c.routes.push_back(createRoute({btOutMix}, btOutSpeaker));
666         c.routes.push_back(createRoute({btHearingOutMix}, btOutHearingAid));
667 
668         return c;
669     }();
670     return std::make_unique<Configuration>(configuration);
671 }
672 
673 }  // namespace aidl::android::hardware::audio::core::internal
674