blob: 1a662825bdcd41da463a3540cc267da0a1df7ae9 [file] [log] [blame]
Mikhail Naganov1b444a52020-10-29 13:08:05 -07001/*
2 * Copyright (C) 2020 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 <stdio.h>
18#include <string.h>
19
20#define LOG_TAG "HidlUtils"
21#include <log/log.h>
22
23#include <android_audio_policy_configuration_V7_0-enums.h>
24#include <common/all-versions/VersionUtils.h>
25
26#include "HidlUtils.h"
27
28namespace android {
29namespace hardware {
30namespace audio {
31namespace common {
32namespace CPP_VERSION {
33namespace implementation {
34
35namespace xsd {
36using namespace ::android::audio::policy::configuration::V7_0;
37}
38
39#define CONVERT_CHECKED(expr, result) \
40 if (status_t status = (expr); status != NO_ERROR) { \
41 result = status; \
42 }
43
44status_t HidlUtils::audioIndexChannelMaskFromHal(audio_channel_mask_t halChannelMask,
45 AudioChannelMask* channelMask) {
46 *channelMask = audio_channel_index_mask_to_string(halChannelMask);
47 if (!channelMask->empty() && !xsd::isUnknownAudioChannelMask(*channelMask)) {
48 return NO_ERROR;
49 }
50 ALOGE("Unknown index channel mask value 0x%X", halChannelMask);
51 *channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_NONE);
52 return BAD_VALUE;
53}
54
55status_t HidlUtils::audioInputChannelMaskFromHal(audio_channel_mask_t halChannelMask,
56 AudioChannelMask* channelMask) {
57 *channelMask = audio_channel_in_mask_to_string(halChannelMask);
58 if (!channelMask->empty() && !xsd::isUnknownAudioChannelMask(*channelMask)) {
59 return NO_ERROR;
60 }
61 ALOGE("Unknown input channel mask value 0x%X", halChannelMask);
62 *channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_NONE);
63 return BAD_VALUE;
64}
65
66status_t HidlUtils::audioOutputChannelMaskFromHal(audio_channel_mask_t halChannelMask,
67 AudioChannelMask* channelMask) {
68 *channelMask = audio_channel_out_mask_to_string(halChannelMask);
69 if (!channelMask->empty() && !xsd::isUnknownAudioChannelMask(*channelMask)) {
70 return NO_ERROR;
71 }
72 ALOGE("Unknown output channel mask value 0x%X", halChannelMask);
73 *channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_NONE);
74 return BAD_VALUE;
75}
76
77status_t HidlUtils::audioChannelMaskFromHal(audio_channel_mask_t halChannelMask, bool isInput,
78 AudioChannelMask* channelMask) {
79 if (halChannelMask != AUDIO_CHANNEL_NONE) {
80 if (audio_channel_mask_is_valid(halChannelMask)) {
81 switch (audio_channel_mask_get_representation(halChannelMask)) {
82 case AUDIO_CHANNEL_REPRESENTATION_POSITION:
83 return isInput ? audioInputChannelMaskFromHal(halChannelMask, channelMask)
84 : audioOutputChannelMaskFromHal(halChannelMask, channelMask);
85 case AUDIO_CHANNEL_REPRESENTATION_INDEX:
86 // Index masks do not have direction.
87 return audioIndexChannelMaskFromHal(halChannelMask, channelMask);
88 // no default
89 }
90 }
91 *channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_NONE);
92 return BAD_VALUE;
93 }
94 *channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_NONE);
95 return NO_ERROR;
96}
97
98status_t HidlUtils::audioChannelMaskToHal(const AudioChannelMask& channelMask,
99 audio_channel_mask_t* halChannelMask) {
100 if (!xsd::isUnknownAudioChannelMask(channelMask) &&
101 audio_channel_mask_from_string(channelMask.c_str(), halChannelMask)) {
102 return NO_ERROR;
103 }
104 ALOGE("Unknown channel mask \"%s\"", channelMask.c_str());
105 *halChannelMask = AUDIO_CHANNEL_NONE;
106 return BAD_VALUE;
107}
108
109status_t HidlUtils::audioConfigBaseFromHal(const audio_config_base_t& halConfigBase, bool isInput,
110 AudioConfigBase* configBase) {
111 status_t result = NO_ERROR;
112 configBase->sampleRateHz = halConfigBase.sample_rate;
113 CONVERT_CHECKED(
114 audioChannelMaskFromHal(halConfigBase.channel_mask, isInput, &configBase->channelMask),
115 result);
116 CONVERT_CHECKED(audioFormatFromHal(halConfigBase.format, &configBase->format), result);
117 return result;
118}
119
120status_t HidlUtils::audioConfigBaseToHal(const AudioConfigBase& configBase,
121 audio_config_base_t* halConfigBase) {
122 status_t result = NO_ERROR;
123 halConfigBase->sample_rate = configBase.sampleRateHz;
124 CONVERT_CHECKED(audioChannelMaskToHal(configBase.channelMask, &halConfigBase->channel_mask),
125 result);
126 CONVERT_CHECKED(audioFormatToHal(configBase.format, &halConfigBase->format), result);
127 return result;
128}
129
130status_t HidlUtils::audioDeviceTypeFromHal(audio_devices_t halDevice, AudioDevice* device) {
131 *device = audio_device_to_string(halDevice);
132 if (!device->empty() && !xsd::isUnknownAudioDevice(*device)) {
133 return NO_ERROR;
134 }
135 ALOGE("Unknown audio device value 0x%X", halDevice);
136 *device = toString(xsd::AudioDevice::AUDIO_DEVICE_NONE);
137 return BAD_VALUE;
138}
139
140status_t HidlUtils::audioDeviceTypeToHal(const AudioDevice& device, audio_devices_t* halDevice) {
141 if (!xsd::isUnknownAudioDevice(device) && audio_device_from_string(device.c_str(), halDevice)) {
142 return NO_ERROR;
143 }
144 ALOGE("Unknown audio device \"%s\"", device.c_str());
145 *halDevice = AUDIO_DEVICE_NONE;
146 return BAD_VALUE;
147}
148
149status_t HidlUtils::audioFormatFromHal(audio_format_t halFormat, AudioFormat* format) {
150 *format = audio_format_to_string(halFormat);
151 if (!format->empty() && !xsd::isUnknownAudioFormat(*format)) {
152 return NO_ERROR;
153 }
154 ALOGE("Unknown audio format value 0x%X", halFormat);
155 return BAD_VALUE;
156}
157
158status_t HidlUtils::audioFormatToHal(const AudioFormat& format, audio_format_t* halFormat) {
159 if (!xsd::isUnknownAudioFormat(format) && audio_format_from_string(format.c_str(), halFormat)) {
160 return NO_ERROR;
161 }
162 ALOGE("Unknown audio format \"%s\"", format.c_str());
163 *halFormat = AUDIO_FORMAT_DEFAULT;
164 return BAD_VALUE;
165}
166
167status_t HidlUtils::audioGainModeMaskFromHal(audio_gain_mode_t halGainModeMask,
168 hidl_vec<AudioGainMode>* gainModeMask) {
169 status_t status = NO_ERROR;
170 std::vector<AudioGainMode> result;
171 for (uint32_t bit = 0; bit < sizeof(audio_gain_mode_t) * 8; ++bit) {
172 audio_gain_mode_t flag = static_cast<audio_gain_mode_t>(1u << bit);
173 if ((flag & halGainModeMask) == flag) {
174 AudioGainMode flagStr = audio_gain_mode_to_string(flag);
175 if (!flagStr.empty() && !xsd::isUnknownAudioGainMode(flagStr)) {
176 result.push_back(flagStr);
177 } else {
178 ALOGE("Unknown audio gain mode value 0x%X", flag);
179 status = BAD_VALUE;
180 }
181 }
182 }
183 *gainModeMask = result;
184 return status;
185}
186
187status_t HidlUtils::audioGainModeMaskToHal(const hidl_vec<AudioGainMode>& gainModeMask,
188 audio_gain_mode_t* halGainModeMask) {
189 status_t status = NO_ERROR;
190 *halGainModeMask = {};
191 for (const auto& gainMode : gainModeMask) {
192 audio_gain_mode_t halGainMode;
193 if (!xsd::isUnknownAudioGainMode(gainMode) &&
194 audio_gain_mode_from_string(gainMode.c_str(), &halGainMode)) {
195 *halGainModeMask = static_cast<audio_gain_mode_t>(*halGainModeMask | halGainMode);
196 } else {
197 ALOGE("Unknown audio gain mode \"%s\"", gainMode.c_str());
198 status = BAD_VALUE;
199 }
200 }
201 return status;
202}
203
204status_t HidlUtils::audioSourceFromHal(audio_source_t halSource, AudioSource* source) {
205 *source = audio_source_to_string(halSource);
206 if (!source->empty() && !xsd::isUnknownAudioSource(*source)) {
207 return NO_ERROR;
208 }
209 ALOGE("Unknown audio source value 0x%X", halSource);
210 *source = toString(xsd::AudioSource::AUDIO_SOURCE_DEFAULT);
211 return BAD_VALUE;
212}
213
214status_t HidlUtils::audioSourceToHal(const AudioSource& source, audio_source_t* halSource) {
215 if (!xsd::isUnknownAudioSource(source) && audio_source_from_string(source.c_str(), halSource)) {
216 return NO_ERROR;
217 }
218 ALOGE("Unknown audio source \"%s\"", source.c_str());
219 *halSource = AUDIO_SOURCE_DEFAULT;
220 return BAD_VALUE;
221}
222
223status_t HidlUtils::audioStreamTypeFromHal(audio_stream_type_t halStreamType,
224 AudioStreamType* streamType) {
225 *streamType = audio_stream_type_to_string(halStreamType);
226 if (!streamType->empty() && !xsd::isUnknownAudioStreamType(*streamType)) {
227 return NO_ERROR;
228 }
229 ALOGE("Unknown audio stream type value 0x%X", halStreamType);
230 return BAD_VALUE;
231}
232
233status_t HidlUtils::audioStreamTypeToHal(const AudioStreamType& streamType,
234 audio_stream_type_t* halStreamType) {
235 if (!xsd::isUnknownAudioStreamType(streamType) &&
236 audio_stream_type_from_string(streamType.c_str(), halStreamType)) {
237 return NO_ERROR;
238 }
239 ALOGE("Unknown audio stream type \"%s\"", streamType.c_str());
240 *halStreamType = AUDIO_STREAM_DEFAULT;
241 return BAD_VALUE;
242}
243
244status_t HidlUtils::audioConfigFromHal(const audio_config_t& halConfig, bool isInput,
245 AudioConfig* config) {
246 status_t result = NO_ERROR;
247 audio_config_base_t halConfigBase = {halConfig.sample_rate, halConfig.channel_mask,
248 halConfig.format};
249 CONVERT_CHECKED(audioConfigBaseFromHal(halConfigBase, isInput, &config->base), result);
250 CONVERT_CHECKED(audioOffloadInfoFromHal(halConfig.offload_info, &config->offloadInfo), result);
251 config->frameCount = halConfig.frame_count;
252 return result;
253}
254
255status_t HidlUtils::audioConfigToHal(const AudioConfig& config, audio_config_t* halConfig) {
256 status_t result = NO_ERROR;
257 *halConfig = AUDIO_CONFIG_INITIALIZER;
258 audio_config_base_t halConfigBase = AUDIO_CONFIG_BASE_INITIALIZER;
259 CONVERT_CHECKED(audioConfigBaseToHal(config.base, &halConfigBase), result);
260 halConfig->sample_rate = halConfigBase.sample_rate;
261 halConfig->channel_mask = halConfigBase.channel_mask;
262 halConfig->format = halConfigBase.format;
263 CONVERT_CHECKED(audioOffloadInfoToHal(config.offloadInfo, &halConfig->offload_info), result);
264 halConfig->frame_count = config.frameCount;
265 return result;
266}
267
268status_t HidlUtils::audioGainConfigFromHal(const struct audio_gain_config& halConfig, bool isInput,
269 AudioGainConfig* config) {
270 status_t result = NO_ERROR;
271 config->index = halConfig.index;
272 CONVERT_CHECKED(audioGainModeMaskFromHal(halConfig.mode, &config->mode), result);
273 CONVERT_CHECKED(audioChannelMaskFromHal(halConfig.channel_mask, isInput, &config->channelMask),
274 result);
275 if (halConfig.mode & AUDIO_GAIN_MODE_JOINT) {
276 config->values.resize(1);
277 config->values[0] = halConfig.values[0];
278 }
279 if (halConfig.mode & (AUDIO_GAIN_MODE_CHANNELS | AUDIO_GAIN_MODE_RAMP)) {
280 config->values.resize(__builtin_popcount(halConfig.channel_mask));
281 for (size_t i = 0; i < config->values.size(); ++i) {
282 config->values[i] = halConfig.values[i];
283 }
284 }
285 config->rampDurationMs = halConfig.ramp_duration_ms;
286 return result;
287}
288
289status_t HidlUtils::audioGainConfigToHal(const AudioGainConfig& config,
290 struct audio_gain_config* halConfig) {
291 status_t result = NO_ERROR;
292 halConfig->index = config.index;
293 CONVERT_CHECKED(audioGainModeMaskToHal(config.mode, &halConfig->mode), result);
294 CONVERT_CHECKED(audioChannelMaskToHal(config.channelMask, &halConfig->channel_mask), result);
295 memset(halConfig->values, 0, sizeof(halConfig->values));
296 if (halConfig->mode & AUDIO_GAIN_MODE_JOINT) {
297 if (config.values.size() > 0) {
298 halConfig->values[0] = config.values[0];
299 } else {
300 ALOGE("Empty values vector in AudioGainConfig");
301 result = BAD_VALUE;
302 }
303 }
304 if (halConfig->mode & (AUDIO_GAIN_MODE_CHANNELS | AUDIO_GAIN_MODE_RAMP)) {
305 size_t channelCount = __builtin_popcount(halConfig->channel_mask);
306 size_t valuesCount = config.values.size();
307 if (channelCount != valuesCount) {
308 ALOGE("Wrong number of values in AudioGainConfig, expected: %zu, found: %zu",
309 channelCount, valuesCount);
310 result = BAD_VALUE;
311 if (channelCount < valuesCount) {
312 valuesCount = channelCount;
313 }
314 }
315 for (size_t i = 0; i < valuesCount; ++i) {
316 halConfig->values[i] = config.values[i];
317 }
318 }
319 halConfig->ramp_duration_ms = config.rampDurationMs;
320 return result;
321}
322
323status_t HidlUtils::audioGainFromHal(const struct audio_gain& halGain, bool isInput,
324 AudioGain* gain) {
325 status_t result = NO_ERROR;
326 CONVERT_CHECKED(audioGainModeMaskFromHal(halGain.mode, &gain->mode), result);
327 CONVERT_CHECKED(audioChannelMaskFromHal(halGain.channel_mask, isInput, &gain->channelMask),
328 result);
329 gain->minValue = halGain.min_value;
330 gain->maxValue = halGain.max_value;
331 gain->defaultValue = halGain.default_value;
332 gain->stepValue = halGain.step_value;
333 gain->minRampMs = halGain.min_ramp_ms;
334 gain->maxRampMs = halGain.max_ramp_ms;
335 return result;
336}
337
338status_t HidlUtils::audioGainToHal(const AudioGain& gain, struct audio_gain* halGain) {
339 status_t result = NO_ERROR;
340 CONVERT_CHECKED(audioGainModeMaskToHal(gain.mode, &halGain->mode), result);
341 CONVERT_CHECKED(audioChannelMaskToHal(gain.channelMask, &halGain->channel_mask), result);
342 halGain->min_value = gain.minValue;
343 halGain->max_value = gain.maxValue;
344 halGain->default_value = gain.defaultValue;
345 halGain->step_value = gain.stepValue;
346 halGain->min_ramp_ms = gain.minRampMs;
347 halGain->max_ramp_ms = gain.maxRampMs;
348 return result;
349}
350
351status_t HidlUtils::audioUsageFromHal(audio_usage_t halUsage, AudioUsage* usage) {
352 if (halUsage == AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST ||
353 halUsage == AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT ||
354 halUsage == AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED ||
355 halUsage == AUDIO_USAGE_NOTIFICATION_EVENT) {
356 halUsage = AUDIO_USAGE_NOTIFICATION;
357 }
358 *usage = audio_usage_to_string(halUsage);
359 if (!usage->empty() && !xsd::isUnknownAudioUsage(*usage)) {
360 return NO_ERROR;
361 }
362 ALOGE("Unknown audio usage %d", halUsage);
363 *usage = toString(xsd::AudioUsage::AUDIO_USAGE_UNKNOWN);
364 return BAD_VALUE;
365}
366
367status_t HidlUtils::audioUsageToHal(const AudioUsage& usage, audio_usage_t* halUsage) {
368 if (!xsd::isUnknownAudioUsage(usage) && audio_usage_from_string(usage.c_str(), halUsage)) {
369 return NO_ERROR;
370 }
371 ALOGE("Unknown audio usage \"%s\"", usage.c_str());
372 *halUsage = AUDIO_USAGE_UNKNOWN;
373 return BAD_VALUE;
374}
375
376status_t HidlUtils::audioOffloadInfoFromHal(const audio_offload_info_t& halOffload,
377 AudioOffloadInfo* offload) {
378 status_t result = NO_ERROR;
379 audio_config_base_t halConfigBase = {halOffload.sample_rate, halOffload.channel_mask,
380 halOffload.format};
381 CONVERT_CHECKED(audioConfigBaseFromHal(halConfigBase, false /*isInput*/, &offload->base),
382 result);
383 CONVERT_CHECKED(audioStreamTypeFromHal(halOffload.stream_type, &offload->streamType), result);
384 offload->bitRatePerSecond = halOffload.bit_rate;
385 offload->durationMicroseconds = halOffload.duration_us;
386 offload->hasVideo = halOffload.has_video;
387 offload->isStreaming = halOffload.is_streaming;
388 offload->bitWidth = halOffload.bit_width;
389 offload->bufferSize = halOffload.offload_buffer_size;
390 CONVERT_CHECKED(audioUsageFromHal(halOffload.usage, &offload->usage), result);
391 if (halOffload.version >= AUDIO_OFFLOAD_INFO_VERSION_0_2) {
392 offload->encapsulationMode =
393 static_cast<AudioEncapsulationMode>(halOffload.encapsulation_mode);
394 offload->contentId = halOffload.content_id;
395 offload->syncId = halOffload.sync_id;
396 } else {
397 offload->encapsulationMode = AudioEncapsulationMode::NONE;
398 offload->contentId = 0;
399 offload->syncId = 0;
400 }
401 return result;
402}
403
404status_t HidlUtils::audioOffloadInfoToHal(const AudioOffloadInfo& offload,
405 audio_offload_info_t* halOffload) {
406 status_t result = NO_ERROR;
407 *halOffload = AUDIO_INFO_INITIALIZER;
408 audio_config_base_t halConfigBase = AUDIO_CONFIG_BASE_INITIALIZER;
409 CONVERT_CHECKED(audioConfigBaseToHal(offload.base, &halConfigBase), result);
410 halOffload->sample_rate = halConfigBase.sample_rate;
411 halOffload->channel_mask = halConfigBase.channel_mask;
412 halOffload->format = halConfigBase.format;
413 CONVERT_CHECKED(audioStreamTypeToHal(offload.streamType, &halOffload->stream_type), result);
414 halOffload->bit_rate = offload.bitRatePerSecond;
415 halOffload->duration_us = offload.durationMicroseconds;
416 halOffload->has_video = offload.hasVideo;
417 halOffload->is_streaming = offload.isStreaming;
418 halOffload->bit_width = offload.bitWidth;
419 halOffload->offload_buffer_size = offload.bufferSize;
420 CONVERT_CHECKED(audioUsageToHal(offload.usage, &halOffload->usage), result);
421 halOffload->encapsulation_mode =
422 static_cast<audio_encapsulation_mode_t>(offload.encapsulationMode);
423 halOffload->content_id = offload.contentId;
424 halOffload->sync_id = offload.syncId;
425 return result;
426}
427
428status_t HidlUtils::audioPortConfigFromHal(const struct audio_port_config& halConfig,
429 AudioPortConfig* config) {
430 status_t result = NO_ERROR;
431 bool isInput = false;
432 config->id = halConfig.id;
433 CONVERT_CHECKED(audioPortExtendedInfoFromHal(halConfig.role, halConfig.type,
434 halConfig.ext.device, halConfig.ext.mix,
435 halConfig.ext.session, &config->ext, &isInput),
436 result);
437 if (audio_port_config_has_input_direction(&halConfig) != isInput) {
438 ALOGE("Inconsistent port config direction data, is input: %d (hal) != %d (converter)",
439 audio_port_config_has_input_direction(&halConfig), isInput);
440 result = BAD_VALUE;
441 }
442 if (halConfig.config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) {
443 config->base.sampleRateHz = halConfig.sample_rate;
444 } else {
445 config->base.sampleRateHz = {};
446 }
447 if (halConfig.config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) {
448 CONVERT_CHECKED(
449 audioChannelMaskFromHal(halConfig.channel_mask, isInput, &config->base.channelMask),
450 result);
451 } else {
452 config->base.channelMask = {};
453 }
454 if (halConfig.config_mask & AUDIO_PORT_CONFIG_FORMAT) {
455 CONVERT_CHECKED(audioFormatFromHal(halConfig.format, &config->base.format), result);
456 } else {
457 config->base.format = {};
458 }
459 if (halConfig.config_mask & AUDIO_PORT_CONFIG_GAIN) {
460 config->gain.config({});
461 CONVERT_CHECKED(audioGainConfigFromHal(halConfig.gain, isInput, &config->gain.config()),
462 result);
463 } else {
464 config->gain.unspecified({});
465 }
466 return result;
467}
468
469status_t HidlUtils::audioPortConfigToHal(const AudioPortConfig& config,
470 struct audio_port_config* halConfig) {
471 status_t result = NO_ERROR;
472 memset(halConfig, 0, sizeof(audio_port_config));
473 halConfig->id = config.id;
474 halConfig->config_mask = {};
475 if (config.base.sampleRateHz != 0) {
476 halConfig->config_mask |= AUDIO_PORT_CONFIG_SAMPLE_RATE;
477 halConfig->sample_rate = config.base.sampleRateHz;
478 }
479 if (!config.base.channelMask.empty()) {
480 halConfig->config_mask |= AUDIO_PORT_CONFIG_CHANNEL_MASK;
481 CONVERT_CHECKED(audioChannelMaskToHal(config.base.channelMask, &halConfig->channel_mask),
482 result);
483 }
484 if (!config.base.format.empty()) {
485 halConfig->config_mask |= AUDIO_PORT_CONFIG_FORMAT;
486 CONVERT_CHECKED(audioFormatToHal(config.base.format, &halConfig->format), result);
487 }
488 if (config.gain.getDiscriminator() ==
489 AudioPortConfig::OptionalGain::hidl_discriminator::config) {
490 halConfig->config_mask |= AUDIO_PORT_CONFIG_GAIN;
491 CONVERT_CHECKED(audioGainConfigToHal(config.gain.config(), &halConfig->gain), result);
492 }
493 CONVERT_CHECKED(audioPortExtendedInfoToHal(config.ext, &halConfig->role, &halConfig->type,
494 &halConfig->ext.device, &halConfig->ext.mix,
495 &halConfig->ext.session),
496 result);
497 return result;
498}
499
500status_t HidlUtils::audioPortExtendedInfoFromHal(
501 audio_port_role_t role, audio_port_type_t type,
502 const struct audio_port_config_device_ext& device,
503 const struct audio_port_config_mix_ext& mix,
504 const struct audio_port_config_session_ext& session, AudioPortExtendedInfo* ext,
505 bool* isInput) {
506 status_t result = NO_ERROR;
507 *isInput = false;
508 switch (type) {
509 case AUDIO_PORT_TYPE_NONE:
510 ext->unspecified({});
511 break;
512 case AUDIO_PORT_TYPE_DEVICE: {
513 *isInput = role == AUDIO_PORT_ROLE_SOURCE;
514 ext->device({});
515 CONVERT_CHECKED(deviceAddressFromHal(device.type, device.address, &ext->device()),
516 result);
517 break;
518 }
519 case AUDIO_PORT_TYPE_MIX: {
520 *isInput = role == AUDIO_PORT_ROLE_SINK;
521 ext->mix({});
522 ext->mix().ioHandle = mix.handle;
523 if (role == AUDIO_PORT_ROLE_SOURCE) {
524 ext->mix().useCase.stream({});
525 CONVERT_CHECKED(
526 audioStreamTypeFromHal(mix.usecase.stream, &ext->mix().useCase.stream()),
527 result);
528 } else if (role == AUDIO_PORT_ROLE_SINK) {
529 ext->mix().useCase.source({});
530 CONVERT_CHECKED(
531 audioSourceFromHal(mix.usecase.source, &ext->mix().useCase.source()),
532 result);
533 }
534 break;
535 }
536 case AUDIO_PORT_TYPE_SESSION: {
537 ext->session(session.session);
538 break;
539 }
540 }
541 return result;
542}
543
544status_t HidlUtils::audioPortExtendedInfoToHal(const AudioPortExtendedInfo& ext,
545 audio_port_role_t* role, audio_port_type_t* type,
546 struct audio_port_config_device_ext* device,
547 struct audio_port_config_mix_ext* mix,
548 struct audio_port_config_session_ext* session) {
549 status_t result = NO_ERROR;
550 switch (ext.getDiscriminator()) {
551 case AudioPortExtendedInfo::hidl_discriminator::unspecified:
552 *role = AUDIO_PORT_ROLE_NONE;
553 *type = AUDIO_PORT_TYPE_NONE;
554 break;
555 case AudioPortExtendedInfo::hidl_discriminator::device:
556 *role = xsd::isOutputDevice(ext.device().deviceType) ? AUDIO_PORT_ROLE_SINK
557 : AUDIO_PORT_ROLE_SOURCE;
558 *type = AUDIO_PORT_TYPE_DEVICE;
559 CONVERT_CHECKED(deviceAddressToHal(ext.device(), &device->type, device->address),
560 result);
561 break;
562 case AudioPortExtendedInfo::hidl_discriminator::mix:
563 *type = AUDIO_PORT_TYPE_MIX;
564 switch (ext.mix().useCase.getDiscriminator()) {
565 case AudioPortExtendedInfo::AudioPortMixExt::UseCase::hidl_discriminator::stream:
566 *role = AUDIO_PORT_ROLE_SOURCE;
567 CONVERT_CHECKED(
568 audioStreamTypeToHal(ext.mix().useCase.stream(), &mix->usecase.stream),
569 result);
570 break;
571 case AudioPortExtendedInfo::AudioPortMixExt::UseCase::hidl_discriminator::source:
572 *role = AUDIO_PORT_ROLE_SINK;
573 CONVERT_CHECKED(
574 audioSourceToHal(ext.mix().useCase.source(), &mix->usecase.source),
575 result);
576 break;
577 }
578 mix->handle = ext.mix().ioHandle;
579 break;
580 case AudioPortExtendedInfo::hidl_discriminator::session:
581 *role = AUDIO_PORT_ROLE_NONE;
582 *type = AUDIO_PORT_TYPE_SESSION;
583 session->session = static_cast<audio_session_t>(ext.session());
584 break;
585 }
586 return result;
587}
588
589status_t HidlUtils::audioPortFromHal(const struct audio_port& halPort, AudioPort* port) {
590 struct audio_port_v7 halPortV7 = {};
591 audio_populate_audio_port_v7(&halPort, &halPortV7);
592 return audioPortFromHal(halPortV7, port);
593}
594
595status_t HidlUtils::audioPortToHal(const AudioPort& port, struct audio_port* halPort) {
596 status_t result = NO_ERROR;
597 struct audio_port_v7 halPortV7 = {};
598 CONVERT_CHECKED(audioPortToHal(port, &halPortV7), result);
599 if (!audio_populate_audio_port(&halPortV7, halPort)) {
600 result = BAD_VALUE;
601 }
602 return result;
603}
604
605status_t HidlUtils::audioPortFromHal(const struct audio_port_v7& halPort, AudioPort* port) {
606 status_t result = NO_ERROR;
607 bool isInput = false;
608 port->id = halPort.id;
609 port->name.setToExternal(halPort.name, strlen(halPort.name));
610 // HAL uses slightly different but convertible structures for the extended info in port
611 // and port config structures.
612 struct audio_port_config_device_ext halDevice = {};
613 struct audio_port_config_mix_ext halMix = {};
614 struct audio_port_config_session_ext halSession = {};
615 switch (halPort.type) {
616 case AUDIO_PORT_TYPE_NONE:
617 break;
618 case AUDIO_PORT_TYPE_DEVICE:
619 halDevice.type = halPort.ext.device.type;
620 memcpy(halDevice.address, halPort.ext.device.address, AUDIO_DEVICE_MAX_ADDRESS_LEN);
621 break;
622 case AUDIO_PORT_TYPE_MIX:
623 halMix.handle = halPort.ext.mix.handle;
624 break;
625 case AUDIO_PORT_TYPE_SESSION:
626 halSession.session = halPort.ext.session.session;
627 break;
628 }
629 CONVERT_CHECKED(audioPortExtendedInfoFromHal(halPort.role, halPort.type, halDevice, halMix,
630 halSession, &port->ext, &isInput),
631 result);
632 port->profiles.resize(halPort.num_audio_profiles);
633 for (size_t i = 0; i < halPort.num_audio_profiles; ++i) {
634 CONVERT_CHECKED(audioProfileFromHal(halPort.audio_profiles[i], isInput, &port->profiles[i]),
635 result);
636 }
637 port->gains.resize(halPort.num_gains);
638 for (size_t i = 0; i < halPort.num_gains; ++i) {
639 CONVERT_CHECKED(audioGainFromHal(halPort.gains[i], isInput, &port->gains[i]), result);
640 }
641 CONVERT_CHECKED(audioPortConfigFromHal(halPort.active_config, &port->activeConfig), result);
642 return result;
643}
644
645status_t HidlUtils::audioPortToHal(const AudioPort& port, struct audio_port_v7* halPort) {
646 status_t result = NO_ERROR;
647 halPort->id = port.id;
648 strncpy(halPort->name, port.name.c_str(), AUDIO_PORT_MAX_NAME_LEN);
649 halPort->name[AUDIO_PORT_MAX_NAME_LEN - 1] = '\0';
650 if (port.name.size() >= AUDIO_PORT_MAX_NAME_LEN) {
651 ALOGE("HIDL Audio Port name is too long: %zu", port.name.size());
652 result = BAD_VALUE;
653 }
654 halPort->num_audio_profiles = port.profiles.size();
655 if (halPort->num_audio_profiles > AUDIO_PORT_MAX_AUDIO_PROFILES) {
656 ALOGE("HIDL Audio Port has too many profiles: %u", halPort->num_audio_profiles);
657 halPort->num_audio_profiles = AUDIO_PORT_MAX_AUDIO_PROFILES;
658 result = BAD_VALUE;
659 }
660 for (size_t i = 0; i < halPort->num_audio_profiles; ++i) {
661 CONVERT_CHECKED(audioProfileToHal(port.profiles[i], &halPort->audio_profiles[i]), result);
662 }
663 halPort->num_gains = port.gains.size();
664 if (halPort->num_gains > AUDIO_PORT_MAX_GAINS) {
665 ALOGE("HIDL Audio Port has too many gains: %u", halPort->num_gains);
666 halPort->num_gains = AUDIO_PORT_MAX_GAINS;
667 result = BAD_VALUE;
668 }
669 for (size_t i = 0; i < halPort->num_gains; ++i) {
670 CONVERT_CHECKED(audioGainToHal(port.gains[i], &halPort->gains[i]), result);
671 }
672 // HAL uses slightly different but convertible structures for the extended info in port
673 // and port config structures.
674 struct audio_port_config_device_ext halDevice = {};
675 struct audio_port_config_mix_ext halMix = {};
676 struct audio_port_config_session_ext halSession = {};
677 CONVERT_CHECKED(audioPortExtendedInfoToHal(port.ext, &halPort->role, &halPort->type, &halDevice,
678 &halMix, &halSession),
679 result);
680 switch (halPort->type) {
681 case AUDIO_PORT_TYPE_NONE:
682 break;
683 case AUDIO_PORT_TYPE_DEVICE:
684 halPort->ext.device.type = halDevice.type;
685 memcpy(halPort->ext.device.address, halDevice.address, AUDIO_DEVICE_MAX_ADDRESS_LEN);
686 break;
687 case AUDIO_PORT_TYPE_MIX:
688 halPort->ext.mix.handle = halMix.handle;
689 break;
690 case AUDIO_PORT_TYPE_SESSION:
691 halPort->ext.session.session = halSession.session;
692 break;
693 }
694 CONVERT_CHECKED(audioPortConfigToHal(port.activeConfig, &halPort->active_config), result);
695 return result;
696}
697
698status_t HidlUtils::audioProfileFromHal(const struct audio_profile& halProfile, bool isInput,
699 AudioProfile* profile) {
700 status_t result = NO_ERROR;
701 CONVERT_CHECKED(audioFormatFromHal(halProfile.format, &profile->format), result);
702 profile->sampleRates.resize(halProfile.num_sample_rates);
703 for (size_t i = 0; i < halProfile.num_sample_rates; ++i) {
704 profile->sampleRates[i] = halProfile.sample_rates[i];
705 }
706 profile->channelMasks.resize(halProfile.num_channel_masks);
707 for (size_t i = 0; i < halProfile.num_channel_masks; ++i) {
708 CONVERT_CHECKED(audioChannelMaskFromHal(halProfile.channel_masks[i], isInput,
709 &profile->channelMasks[i]),
710 result);
711 }
712 return result;
713}
714
715status_t HidlUtils::audioProfileToHal(const AudioProfile& profile,
716 struct audio_profile* halProfile) {
717 status_t result = NO_ERROR;
718 CONVERT_CHECKED(audioFormatToHal(profile.format, &halProfile->format), result);
719 memset(halProfile->sample_rates, 0, sizeof(halProfile->sample_rates));
720 halProfile->num_sample_rates = profile.sampleRates.size();
721 if (halProfile->num_sample_rates > AUDIO_PORT_MAX_SAMPLING_RATES) {
722 ALOGE("HIDL Audio profile has too many sample rates: %u", halProfile->num_sample_rates);
723 halProfile->num_sample_rates = AUDIO_PORT_MAX_SAMPLING_RATES;
724 result = BAD_VALUE;
725 }
726 for (size_t i = 0; i < halProfile->num_sample_rates; ++i) {
727 halProfile->sample_rates[i] = profile.sampleRates[i];
728 }
729 memset(halProfile->channel_masks, 0, sizeof(halProfile->channel_masks));
730 halProfile->num_channel_masks = profile.channelMasks.size();
731 if (halProfile->num_channel_masks > AUDIO_PORT_MAX_CHANNEL_MASKS) {
732 ALOGE("HIDL Audio profile has too many channel masks: %u", halProfile->num_channel_masks);
733 halProfile->num_channel_masks = AUDIO_PORT_MAX_CHANNEL_MASKS;
734 result = BAD_VALUE;
735 }
736 for (size_t i = 0; i < halProfile->num_channel_masks; ++i) {
737 CONVERT_CHECKED(
738 audioChannelMaskToHal(profile.channelMasks[i], &halProfile->channel_masks[i]),
739 status);
740 }
741 return result;
742}
743
744status_t HidlUtils::deviceAddressFromHal(audio_devices_t halDeviceType,
745 const char* halDeviceAddress, DeviceAddress* device) {
746 status_t result = NO_ERROR;
747 CONVERT_CHECKED(audioDeviceTypeFromHal(halDeviceType, &device->deviceType), result);
748 if (audio_is_a2dp_out_device(halDeviceType) || audio_is_a2dp_in_device(halDeviceType)) {
749 device->address.mac({});
750 if (halDeviceAddress != nullptr) {
751 auto& mac = device->address.mac();
752 int status = sscanf(halDeviceAddress, "%hhX:%hhX:%hhX:%hhX:%hhX:%hhX", &mac[0], &mac[1],
753 &mac[2], &mac[3], &mac[4], &mac[5]);
754 if (status != 6) {
755 ALOGE("BT A2DP device \"%s\" MAC address \"%s\" is invalid",
756 device->deviceType.c_str(), halDeviceAddress);
757 result = BAD_VALUE;
758 }
759 } else {
760 ALOGE("BT A2DP device \"%s\" does not have a MAC address", halDeviceAddress);
761 result = BAD_VALUE;
762 }
763 } else if (halDeviceType == AUDIO_DEVICE_OUT_IP || halDeviceType == AUDIO_DEVICE_IN_IP) {
764 device->address.ipv4({});
765 if (halDeviceAddress != nullptr) {
766 auto& ipv4 = device->address.ipv4();
767 int status = sscanf(halDeviceAddress, "%hhu.%hhu.%hhu.%hhu", &ipv4[0], &ipv4[1],
768 &ipv4[2], &ipv4[3]);
769 if (status != 4) {
770 ALOGE("IP device \"%s\" IPv4 address \"%s\" is invalid", device->deviceType.c_str(),
771 halDeviceAddress);
772 result = BAD_VALUE;
773 }
774 } else {
775 ALOGE("IP device \"%s\" does not have an IPv4 address", device->deviceType.c_str());
776 result = BAD_VALUE;
777 }
778 } else if (audio_is_usb_out_device(halDeviceType) || audio_is_usb_in_device(halDeviceType)) {
779 device->address.alsa({});
780 if (halDeviceAddress != nullptr) {
781 auto& alsa = device->address.alsa();
782 int status = sscanf(halDeviceAddress, "card=%d;device=%d", &alsa.card, &alsa.device);
783 if (status != 2) {
784 ALOGE("USB device \"%s\" ALSA address \"%s\" is invalid",
785 device->deviceType.c_str(), halDeviceAddress);
786 result = BAD_VALUE;
787 }
788 } else {
789 ALOGE("USB device \"%s\" does not have ALSA address", device->deviceType.c_str());
790 result = BAD_VALUE;
791 }
792 } else {
793 // Any other device type uses the 'id' field.
794 device->address.id(halDeviceAddress != nullptr ? halDeviceAddress : "");
795 }
796 return result;
797}
798
799status_t HidlUtils::deviceAddressToHal(const DeviceAddress& device, audio_devices_t* halDeviceType,
800 char* halDeviceAddress) {
801 status_t result = NO_ERROR;
802 CONVERT_CHECKED(audioDeviceTypeToHal(device.deviceType, halDeviceType), result);
803 memset(halDeviceAddress, 0, AUDIO_DEVICE_MAX_ADDRESS_LEN);
804 if (audio_is_a2dp_out_device(*halDeviceType) || audio_is_a2dp_in_device(*halDeviceType)) {
805 if (device.address.getDiscriminator() == DeviceAddress::Address::hidl_discriminator::mac) {
806 const auto& mac = device.address.mac();
807 snprintf(halDeviceAddress, AUDIO_DEVICE_MAX_ADDRESS_LEN,
808 "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4],
809 mac[5]);
810 } else {
811 ALOGE("BT A2DP device \"%s\" does not have MAC address set", device.deviceType.c_str());
812 result = BAD_VALUE;
813 }
814 } else if (*halDeviceType == AUDIO_DEVICE_OUT_IP || *halDeviceType == AUDIO_DEVICE_IN_IP) {
815 if (device.address.getDiscriminator() == DeviceAddress::Address::hidl_discriminator::ipv4) {
816 const auto& ipv4 = device.address.ipv4();
817 snprintf(halDeviceAddress, AUDIO_DEVICE_MAX_ADDRESS_LEN, "%d.%d.%d.%d", ipv4[0],
818 ipv4[1], ipv4[2], ipv4[3]);
819 } else {
820 ALOGE("IP device \"%s\" does not have IPv4 address set", device.deviceType.c_str());
821 result = BAD_VALUE;
822 }
823 } else if (audio_is_usb_out_device(*halDeviceType) || audio_is_usb_in_device(*halDeviceType)) {
824 if (device.address.getDiscriminator() == DeviceAddress::Address::hidl_discriminator::alsa) {
825 const auto& alsa = device.address.alsa();
826 snprintf(halDeviceAddress, AUDIO_DEVICE_MAX_ADDRESS_LEN, "card=%d;device=%d", alsa.card,
827 alsa.device);
828 } else {
829 ALOGE("USB device \"%s\" does not have ALSA address set", device.deviceType.c_str());
830 result = BAD_VALUE;
831 }
832 } else {
833 // Any other device type uses the 'id' field.
834 if (device.address.getDiscriminator() == DeviceAddress::Address::hidl_discriminator::id) {
835 snprintf(halDeviceAddress, AUDIO_DEVICE_MAX_ADDRESS_LEN, "%s",
836 device.address.id().c_str());
837 }
838 }
839 return result;
840}
841
842} // namespace implementation
843} // namespace CPP_VERSION
844} // namespace common
845} // namespace audio
846} // namespace hardware
847} // namespace android