blob: 280814f8a71917246b7c6cf4f72a1aad8416f564 [file] [log] [blame]
Mikhail Naganovdf5adfd2021-11-11 22:09:22 +00001/*
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
Mikhail Naganova2c5ddf2022-09-12 22:57:14 +000017#include <Utils.h>
Mikhail Naganovdf5adfd2021-11-11 22:09:22 +000018#include <aidl/android/media/audio/common/AudioChannelLayout.h>
19#include <aidl/android/media/audio/common/AudioDeviceType.h>
Mikhail Naganov00603d12022-05-02 22:52:13 +000020#include <aidl/android/media/audio/common/AudioFormatDescription.h>
Mikhail Naganovdf5adfd2021-11-11 22:09:22 +000021#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>
Mikhail Naganov111e0ce2022-06-17 21:41:19 +000024#include <media/stagefright/foundation/MediaDefs.h>
Mikhail Naganovdf5adfd2021-11-11 22:09:22 +000025
Mikhail Naganovdf5adfd2021-11-11 22:09:22 +000026#include "core-impl/Configuration.h"
27
28using aidl::android::media::audio::common::AudioChannelLayout;
Mikhail Naganov00603d12022-05-02 22:52:13 +000029using aidl::android::media::audio::common::AudioDeviceDescription;
Mikhail Naganovdf5adfd2021-11-11 22:09:22 +000030using aidl::android::media::audio::common::AudioDeviceType;
31using aidl::android::media::audio::common::AudioFormatDescription;
32using aidl::android::media::audio::common::AudioFormatType;
33using aidl::android::media::audio::common::AudioGainConfig;
34using aidl::android::media::audio::common::AudioIoFlags;
35using aidl::android::media::audio::common::AudioOutputFlags;
36using aidl::android::media::audio::common::AudioPort;
37using aidl::android::media::audio::common::AudioPortConfig;
38using aidl::android::media::audio::common::AudioPortDeviceExt;
39using aidl::android::media::audio::common::AudioPortExt;
40using aidl::android::media::audio::common::AudioPortMixExt;
41using aidl::android::media::audio::common::AudioProfile;
42using aidl::android::media::audio::common::Int;
43using aidl::android::media::audio::common::PcmType;
Mikhail Naganova2c5ddf2022-09-12 22:57:14 +000044using android::hardware::audio::common::makeBitPositionFlagMask;
Mikhail Naganovdf5adfd2021-11-11 22:09:22 +000045
46namespace aidl::android::hardware::audio::core::internal {
47
Mikhail Naganov111e0ce2022-06-17 21:41:19 +000048static void fillProfile(AudioProfile* profile, const std::vector<int32_t>& channelLayouts,
49 const std::vector<int32_t>& sampleRates) {
50 for (auto layout : channelLayouts) {
51 profile->channelMasks.push_back(
52 AudioChannelLayout::make<AudioChannelLayout::layoutMask>(layout));
53 }
54 profile->sampleRates.insert(profile->sampleRates.end(), sampleRates.begin(), sampleRates.end());
55}
56
Mikhail Naganovdf5adfd2021-11-11 22:09:22 +000057static AudioProfile createProfile(PcmType pcmType, const std::vector<int32_t>& channelLayouts,
58 const std::vector<int32_t>& sampleRates) {
59 AudioProfile profile;
60 profile.format.type = AudioFormatType::PCM;
61 profile.format.pcm = pcmType;
Mikhail Naganov111e0ce2022-06-17 21:41:19 +000062 fillProfile(&profile, channelLayouts, sampleRates);
63 return profile;
64}
65
66static AudioProfile createProfile(const std::string& encodingType,
67 const std::vector<int32_t>& channelLayouts,
68 const std::vector<int32_t>& sampleRates) {
69 AudioProfile profile;
70 profile.format.encoding = encodingType;
71 fillProfile(&profile, channelLayouts, sampleRates);
Mikhail Naganovdf5adfd2021-11-11 22:09:22 +000072 return profile;
73}
74
Mikhail Naganov00603d12022-05-02 22:52:13 +000075static AudioPortExt createDeviceExt(AudioDeviceType devType, int32_t flags,
76 std::string connection = "") {
Mikhail Naganovdf5adfd2021-11-11 22:09:22 +000077 AudioPortDeviceExt deviceExt;
78 deviceExt.device.type.type = devType;
Mikhail Naganov00603d12022-05-02 22:52:13 +000079 deviceExt.device.type.connection = std::move(connection);
Mikhail Naganovdf5adfd2021-11-11 22:09:22 +000080 deviceExt.flags = flags;
81 return AudioPortExt::make<AudioPortExt::Tag::device>(deviceExt);
82}
83
84static AudioPortExt createPortMixExt(int32_t maxOpenStreamCount, int32_t maxActiveStreamCount) {
85 AudioPortMixExt mixExt;
86 mixExt.maxOpenStreamCount = maxOpenStreamCount;
87 mixExt.maxActiveStreamCount = maxActiveStreamCount;
88 return AudioPortExt::make<AudioPortExt::Tag::mix>(mixExt);
89}
90
91static AudioPort createPort(int32_t id, const std::string& name, int32_t flags, bool isInput,
92 const AudioPortExt& ext) {
93 AudioPort port;
94 port.id = id;
95 port.name = name;
96 port.flags = isInput ? AudioIoFlags::make<AudioIoFlags::Tag::input>(flags)
97 : AudioIoFlags::make<AudioIoFlags::Tag::output>(flags);
98 port.ext = ext;
99 return port;
100}
101
102static AudioPortConfig createPortConfig(int32_t id, int32_t portId, PcmType pcmType, int32_t layout,
103 int32_t sampleRate, int32_t flags, bool isInput,
104 const AudioPortExt& ext) {
105 AudioPortConfig config;
106 config.id = id;
107 config.portId = portId;
108 config.sampleRate = Int{.value = sampleRate};
109 config.channelMask = AudioChannelLayout::make<AudioChannelLayout::layoutMask>(layout);
110 config.format = AudioFormatDescription{.type = AudioFormatType::PCM, .pcm = pcmType};
111 config.gain = AudioGainConfig();
112 config.flags = isInput ? AudioIoFlags::make<AudioIoFlags::Tag::input>(flags)
113 : AudioIoFlags::make<AudioIoFlags::Tag::output>(flags);
114 config.ext = ext;
115 return config;
116}
117
118static AudioRoute createRoute(const std::vector<int32_t>& sources, int32_t sink) {
119 AudioRoute route;
120 route.sinkPortId = sink;
121 route.sourcePortIds.insert(route.sourcePortIds.end(), sources.begin(), sources.end());
122 return route;
123}
124
Mikhail Naganov00603d12022-05-02 22:52:13 +0000125// Configuration:
126//
127// Device ports:
128// * "Null", OUT_SPEAKER, default
129// - no profiles specified
130// * "Loopback Out", OUT_SUBMIX
131// - profile PCM 24-bit; STEREO; 48000
132// * "USB Out", OUT_DEVICE, CONNECTION_USB
133// - no profiles specified
134// * "Zero", IN_MICROPHONE, default
135// - no profiles specified
136// * "Loopback In", IN_SUBMIX
137// - profile PCM 24-bit; STEREO; 48000
138// * "USB In", IN_DEVICE, CONNECTION_USB
139// - no profiles specified
140//
141// Mix ports:
142// * "primary output", PRIMARY, 1 max open, 1 max active stream
143// - profile PCM 16-bit; MONO, STEREO; 44100, 48000
144// - profile PCM 24-bit; MONO, STEREO; 44100, 48000
Mikhail Naganov111e0ce2022-06-17 21:41:19 +0000145// * "compressed offload", DIRECT|COMPRESS_OFFLOAD|NON_BLOCKING, 1 max open, 1 max active stream
146// - profile MP3; MONO, STEREO; 44100, 48000
Mikhail Naganov00603d12022-05-02 22:52:13 +0000147// * "loopback output", stream count unlimited
148// - profile PCM 24-bit; STEREO; 48000
149// * "primary input", 2 max open, 2 max active streams
150// - profile PCM 16-bit; MONO, STEREO, FRONT_BACK;
151// 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000
152// - profile PCM 24-bit; MONO, STEREO, FRONT_BACK;
153// 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000
154// * "loopback input", stream count unlimited
155// - profile PCM 24-bit; STEREO; 48000
156//
157// Routes:
Mikhail Naganov111e0ce2022-06-17 21:41:19 +0000158// "primary out", "compressed offload" -> "Null"
159// "primary out", "compressed offload" -> "USB Out"
Mikhail Naganov00603d12022-05-02 22:52:13 +0000160// "loopback out" -> "Loopback Out"
161// "Zero", "USB In" -> "primary input"
162// "Loopback In" -> "loopback input"
163//
164// Initial port configs:
165// * "Null" device port: PCM 24-bit; STEREO; 48000
166// * "Zero" device port: PCM 24-bit; MONO; 48000
167//
168// Profiles for device port connected state:
169// * USB Out":
170// - profile PCM 16-bit; MONO, STEREO; 44100, 48000
171// - profile PCM 24-bit; MONO, STEREO; 44100, 48000
172// * USB In":
173// - profile PCM 16-bit; MONO, STEREO; 44100, 48000
174// - profile PCM 24-bit; MONO, STEREO; 44100, 48000
175//
Mikhail Naganovdf5adfd2021-11-11 22:09:22 +0000176Configuration& getNullPrimaryConfiguration() {
177 static Configuration configuration = []() {
Mikhail Naganov00603d12022-05-02 22:52:13 +0000178 const std::vector<AudioProfile> standardPcmAudioProfiles = {
179 createProfile(PcmType::INT_16_BIT,
180 {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO},
181 {44100, 48000}),
182 createProfile(PcmType::INT_24_BIT,
183 {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO},
184 {44100, 48000})};
Mikhail Naganovdf5adfd2021-11-11 22:09:22 +0000185 Configuration c;
186
187 AudioPort nullOutDevice =
188 createPort(c.nextPortId++, "Null", 0, false,
189 createDeviceExt(AudioDeviceType::OUT_SPEAKER,
190 1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE));
191 c.ports.push_back(nullOutDevice);
Mikhail Naganovdf5adfd2021-11-11 22:09:22 +0000192 c.initialConfigs.push_back(
193 createPortConfig(nullOutDevice.id, nullOutDevice.id, PcmType::INT_24_BIT,
194 AudioChannelLayout::LAYOUT_STEREO, 48000, 0, false,
195 createDeviceExt(AudioDeviceType::OUT_SPEAKER, 0)));
196
Mikhail Naganov00603d12022-05-02 22:52:13 +0000197 AudioPort primaryOutMix = createPort(c.nextPortId++, "primary output",
Mikhail Naganova2c5ddf2022-09-12 22:57:14 +0000198 makeBitPositionFlagMask(AudioOutputFlags::PRIMARY),
Mikhail Naganov00603d12022-05-02 22:52:13 +0000199 false, createPortMixExt(1, 1));
200 primaryOutMix.profiles.insert(primaryOutMix.profiles.begin(),
201 standardPcmAudioProfiles.begin(),
202 standardPcmAudioProfiles.end());
203 c.ports.push_back(primaryOutMix);
204
Mikhail Naganov111e0ce2022-06-17 21:41:19 +0000205 AudioPort compressedOffloadOutMix =
206 createPort(c.nextPortId++, "compressed offload",
Mikhail Naganova2c5ddf2022-09-12 22:57:14 +0000207 makeBitPositionFlagMask({AudioOutputFlags::DIRECT,
208 AudioOutputFlags::COMPRESS_OFFLOAD,
209 AudioOutputFlags::NON_BLOCKING}),
Mikhail Naganov111e0ce2022-06-17 21:41:19 +0000210 false, createPortMixExt(1, 1));
211 compressedOffloadOutMix.profiles.push_back(
212 createProfile(::android::MEDIA_MIMETYPE_AUDIO_MPEG,
213 {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO},
214 {44100, 48000}));
215 c.ports.push_back(compressedOffloadOutMix);
216
Mikhail Naganovdf5adfd2021-11-11 22:09:22 +0000217 AudioPort loopOutDevice = createPort(c.nextPortId++, "Loopback Out", 0, false,
218 createDeviceExt(AudioDeviceType::OUT_SUBMIX, 0));
219 loopOutDevice.profiles.push_back(
220 createProfile(PcmType::INT_24_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {48000}));
221 c.ports.push_back(loopOutDevice);
222
223 AudioPort loopOutMix =
224 createPort(c.nextPortId++, "loopback output", 0, false, createPortMixExt(0, 0));
225 loopOutMix.profiles.push_back(
226 createProfile(PcmType::INT_24_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {48000}));
227 c.ports.push_back(loopOutMix);
228
Mikhail Naganov00603d12022-05-02 22:52:13 +0000229 AudioPort usbOutDevice =
230 createPort(c.nextPortId++, "USB Out", 0, false,
231 createDeviceExt(AudioDeviceType::OUT_DEVICE, 0,
232 AudioDeviceDescription::CONNECTION_USB));
233 c.ports.push_back(usbOutDevice);
234 c.connectedProfiles[usbOutDevice.id] = standardPcmAudioProfiles;
Mikhail Naganovdf5adfd2021-11-11 22:09:22 +0000235
236 AudioPort zeroInDevice =
237 createPort(c.nextPortId++, "Zero", 0, true,
238 createDeviceExt(AudioDeviceType::IN_MICROPHONE,
239 1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE));
240 c.ports.push_back(zeroInDevice);
Mikhail Naganov00603d12022-05-02 22:52:13 +0000241 c.initialConfigs.push_back(
242 createPortConfig(zeroInDevice.id, zeroInDevice.id, PcmType::INT_24_BIT,
243 AudioChannelLayout::LAYOUT_MONO, 48000, 0, true,
244 createDeviceExt(AudioDeviceType::IN_MICROPHONE, 0)));
Mikhail Naganovdf5adfd2021-11-11 22:09:22 +0000245
Mikhail Naganovef6bc742022-10-06 00:14:19 +0000246 MicrophoneInfo mic;
247 mic.id = "zero";
248 mic.device = zeroInDevice.ext.get<AudioPortExt::Tag::device>().device;
249 mic.group = 0;
250 mic.indexInTheGroup = 0;
251 c.microphones = std::vector<MicrophoneInfo>{mic};
252
Mikhail Naganovdf5adfd2021-11-11 22:09:22 +0000253 AudioPort primaryInMix =
254 createPort(c.nextPortId++, "primary input", 0, true, createPortMixExt(2, 2));
255 primaryInMix.profiles.push_back(
256 createProfile(PcmType::INT_16_BIT,
257 {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO,
258 AudioChannelLayout::LAYOUT_FRONT_BACK},
259 {8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000}));
260 primaryInMix.profiles.push_back(
261 createProfile(PcmType::INT_24_BIT,
262 {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO,
263 AudioChannelLayout::LAYOUT_FRONT_BACK},
264 {8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000}));
265 c.ports.push_back(primaryInMix);
266
Mikhail Naganovdf5adfd2021-11-11 22:09:22 +0000267 AudioPort loopInDevice = createPort(c.nextPortId++, "Loopback In", 0, true,
268 createDeviceExt(AudioDeviceType::IN_SUBMIX, 0));
269 loopInDevice.profiles.push_back(
270 createProfile(PcmType::INT_24_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {48000}));
271 c.ports.push_back(loopInDevice);
272
273 AudioPort loopInMix =
274 createPort(c.nextPortId++, "loopback input", 0, true, createPortMixExt(0, 0));
275 loopInMix.profiles.push_back(
276 createProfile(PcmType::INT_24_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {48000}));
277 c.ports.push_back(loopInMix);
278
Mikhail Naganov00603d12022-05-02 22:52:13 +0000279 AudioPort usbInDevice = createPort(c.nextPortId++, "USB In", 0, true,
280 createDeviceExt(AudioDeviceType::IN_DEVICE, 0,
281 AudioDeviceDescription::CONNECTION_USB));
282 c.ports.push_back(usbInDevice);
283 c.connectedProfiles[usbInDevice.id] = standardPcmAudioProfiles;
284
Mikhail Naganov111e0ce2022-06-17 21:41:19 +0000285 c.routes.push_back(
286 createRoute({primaryOutMix.id, compressedOffloadOutMix.id}, nullOutDevice.id));
287 c.routes.push_back(
288 createRoute({primaryOutMix.id, compressedOffloadOutMix.id}, usbOutDevice.id));
Mikhail Naganov00603d12022-05-02 22:52:13 +0000289 c.routes.push_back(createRoute({loopOutMix.id}, loopOutDevice.id));
290 c.routes.push_back(createRoute({zeroInDevice.id, usbInDevice.id}, primaryInMix.id));
Mikhail Naganovdf5adfd2021-11-11 22:09:22 +0000291 c.routes.push_back(createRoute({loopInDevice.id}, loopInMix.id));
292
293 c.portConfigs.insert(c.portConfigs.end(), c.initialConfigs.begin(), c.initialConfigs.end());
294 return c;
295 }();
296 return configuration;
297}
298
299} // namespace aidl::android::hardware::audio::core::internal