1 /*
2 * Copyright (C) 2021 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 #if MAJOR_VERSION >= 7
18 #include PATH(APM_XSD_ENUMS_H_FILENAME)
19 #endif
20 #include <HidlUtils.h>
21 #include <log/log.h>
22
23 #include "util/CoreUtils.h"
24
25 using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::implementation::HidlUtils;
26 #if MAJOR_VERSION >= 7
27 namespace xsd {
28 using namespace ::android::audio::policy::configuration::CPP_VERSION;
29 }
30 #endif
31
32 namespace android {
33 namespace hardware {
34 namespace audio {
35 namespace CORE_TYPES_CPP_VERSION {
36 namespace implementation {
37
38 #define CONVERT_CHECKED(expr, result) \
39 if (status_t status = (expr); status != NO_ERROR) { \
40 result = status; \
41 }
42
deviceAddressToHal(const DeviceAddress & device,audio_devices_t * halDeviceType,char * halDeviceAddress)43 status_t CoreUtils::deviceAddressToHal(const DeviceAddress& device, audio_devices_t* halDeviceType,
44 char* halDeviceAddress) {
45 #if MAJOR_VERSION >= 5
46 return HidlUtils::deviceAddressToHal(device, halDeviceType, halDeviceAddress);
47 #else
48 return HidlUtils::deviceAddressToHalImpl(device, halDeviceType, halDeviceAddress);
49 #endif
50 }
51
deviceAddressFromHal(audio_devices_t halDeviceType,const char * halDeviceAddress,DeviceAddress * device)52 status_t CoreUtils::deviceAddressFromHal(audio_devices_t halDeviceType,
53 const char* halDeviceAddress, DeviceAddress* device) {
54 #if MAJOR_VERSION >= 5
55 return HidlUtils::deviceAddressFromHal(halDeviceType, halDeviceAddress, device);
56 #else
57 return HidlUtils::deviceAddressFromHalImpl(halDeviceType, halDeviceAddress, device);
58 #endif
59 }
60
61 #if MAJOR_VERSION >= 4
microphoneInfoFromHal(const struct audio_microphone_characteristic_t & halMicInfo,MicrophoneInfo * micInfo)62 status_t CoreUtils::microphoneInfoFromHal(
63 const struct audio_microphone_characteristic_t& halMicInfo, MicrophoneInfo* micInfo) {
64 status_t result = NO_ERROR;
65 micInfo->deviceId = halMicInfo.device_id;
66 CONVERT_CHECKED(
67 deviceAddressFromHal(halMicInfo.device, halMicInfo.address, &micInfo->deviceAddress),
68 result);
69 int chCount;
70 for (chCount = AUDIO_CHANNEL_COUNT_MAX - 1; chCount >= 0; --chCount) {
71 if (halMicInfo.channel_mapping[chCount] != AUDIO_MICROPHONE_CHANNEL_MAPPING_UNUSED) {
72 break;
73 }
74 }
75 micInfo->channelMapping.resize(chCount + 1);
76 for (size_t ch = 0; ch < micInfo->channelMapping.size(); ch++) {
77 micInfo->channelMapping[ch] = AudioMicrophoneChannelMapping(halMicInfo.channel_mapping[ch]);
78 }
79 micInfo->location = AudioMicrophoneLocation(halMicInfo.location);
80 micInfo->group = AudioMicrophoneGroup(halMicInfo.group);
81 micInfo->indexInTheGroup = static_cast<uint32_t>(halMicInfo.index_in_the_group);
82 micInfo->sensitivity = halMicInfo.sensitivity;
83 micInfo->maxSpl = halMicInfo.max_spl;
84 micInfo->minSpl = halMicInfo.min_spl;
85 micInfo->directionality = AudioMicrophoneDirectionality(halMicInfo.directionality);
86 micInfo->frequencyResponse.resize(halMicInfo.num_frequency_responses);
87 for (size_t k = 0; k < halMicInfo.num_frequency_responses; k++) {
88 micInfo->frequencyResponse[k].frequency = halMicInfo.frequency_responses[0][k];
89 micInfo->frequencyResponse[k].level = halMicInfo.frequency_responses[1][k];
90 }
91 micInfo->position.x = halMicInfo.geometric_location.x;
92 micInfo->position.y = halMicInfo.geometric_location.y;
93 micInfo->position.z = halMicInfo.geometric_location.z;
94 micInfo->orientation.x = halMicInfo.orientation.x;
95 micInfo->orientation.y = halMicInfo.orientation.y;
96 micInfo->orientation.z = halMicInfo.orientation.z;
97 return result;
98 }
99
microphoneInfoToHal(const MicrophoneInfo & micInfo,audio_microphone_characteristic_t * halMicInfo)100 status_t CoreUtils::microphoneInfoToHal(const MicrophoneInfo& micInfo,
101 audio_microphone_characteristic_t* halMicInfo) {
102 status_t result = NO_ERROR;
103 strncpy(halMicInfo->device_id, micInfo.deviceId.c_str(), AUDIO_MICROPHONE_ID_MAX_LEN);
104 halMicInfo->device_id[AUDIO_MICROPHONE_ID_MAX_LEN - 1] = '\0';
105 if (micInfo.deviceId.size() >= AUDIO_MICROPHONE_ID_MAX_LEN) {
106 ALOGE("HIDL MicrophoneInfo device ID is too long: %zu", micInfo.deviceId.size());
107 result = BAD_VALUE;
108 }
109 CONVERT_CHECKED(
110 deviceAddressToHal(micInfo.deviceAddress, &halMicInfo->device, halMicInfo->address),
111 result);
112 if (micInfo.channelMapping.size() > AUDIO_CHANNEL_COUNT_MAX) {
113 ALOGE("HIDL MicrophoneInfo has too many channelMapping elements: %zu",
114 micInfo.channelMapping.size());
115 result = BAD_VALUE;
116 }
117 size_t ch;
118 for (ch = 0; ch < micInfo.channelMapping.size() && ch < AUDIO_CHANNEL_COUNT_MAX; ch++) {
119 halMicInfo->channel_mapping[ch] =
120 static_cast<audio_microphone_channel_mapping_t>(micInfo.channelMapping[ch]);
121 }
122 for (; ch < AUDIO_CHANNEL_COUNT_MAX; ch++) {
123 halMicInfo->channel_mapping[ch] = AUDIO_MICROPHONE_CHANNEL_MAPPING_UNUSED;
124 }
125 halMicInfo->location = static_cast<audio_microphone_location_t>(micInfo.location);
126 halMicInfo->group = static_cast<audio_microphone_group_t>(micInfo.group);
127 halMicInfo->index_in_the_group = static_cast<unsigned int>(micInfo.indexInTheGroup);
128 halMicInfo->sensitivity = micInfo.sensitivity;
129 halMicInfo->max_spl = micInfo.maxSpl;
130 halMicInfo->min_spl = micInfo.minSpl;
131 halMicInfo->directionality =
132 static_cast<audio_microphone_directionality_t>(micInfo.directionality);
133 halMicInfo->num_frequency_responses =
134 static_cast<unsigned int>(micInfo.frequencyResponse.size());
135 if (halMicInfo->num_frequency_responses > AUDIO_MICROPHONE_MAX_FREQUENCY_RESPONSES) {
136 ALOGE("HIDL MicrophoneInfo has too many frequency responses: %u",
137 halMicInfo->num_frequency_responses);
138 halMicInfo->num_frequency_responses = AUDIO_MICROPHONE_MAX_FREQUENCY_RESPONSES;
139 result = BAD_VALUE;
140 }
141 for (size_t k = 0; k < halMicInfo->num_frequency_responses; k++) {
142 halMicInfo->frequency_responses[0][k] = micInfo.frequencyResponse[k].frequency;
143 halMicInfo->frequency_responses[1][k] = micInfo.frequencyResponse[k].level;
144 }
145 halMicInfo->geometric_location.x = micInfo.position.x;
146 halMicInfo->geometric_location.y = micInfo.position.y;
147 halMicInfo->geometric_location.z = micInfo.position.z;
148 halMicInfo->orientation.x = micInfo.orientation.x;
149 halMicInfo->orientation.y = micInfo.orientation.y;
150 halMicInfo->orientation.z = micInfo.orientation.z;
151 return result;
152 }
153
sinkMetadataFromHal(const std::vector<record_track_metadata_t> & halTracks,SinkMetadata * sinkMetadata)154 status_t CoreUtils::sinkMetadataFromHal(const std::vector<record_track_metadata_t>& halTracks,
155 SinkMetadata* sinkMetadata) {
156 status_t result = NO_ERROR;
157 sinkMetadata->tracks.resize(halTracks.size());
158 for (size_t i = 0; i < sinkMetadata->tracks.size(); ++i) {
159 const auto& halTrackMetadata = halTracks[i];
160 RecordTrackMetadata trackMetadata{};
161 CONVERT_CHECKED(
162 HidlUtils::audioSourceFromHal(halTrackMetadata.source, &trackMetadata.source),
163 result);
164 trackMetadata.gain = halTrackMetadata.gain;
165 #if MAJOR_VERSION >= 5
166 if (halTrackMetadata.dest_device != AUDIO_DEVICE_NONE) {
167 DeviceAddress address;
168 if (status_t status =
169 deviceAddressFromHal(halTrackMetadata.dest_device,
170 halTrackMetadata.dest_device_address, &address);
171 status == NO_ERROR) {
172 trackMetadata.destination.device(std::move(address));
173 } else {
174 result = status;
175 }
176 }
177 #if MAJOR_VERSION >= 7
178 trackMetadata.channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_NONE);
179 #endif
180 #endif // MAJOR_VERSION >= 5
181 sinkMetadata->tracks[i] = std::move(trackMetadata);
182 }
183 return result;
184 }
185
sinkMetadataFromHalV7(const std::vector<record_track_metadata_v7_t> & halTracks,bool ignoreNonVendorTags,SinkMetadata * sinkMetadata)186 status_t CoreUtils::sinkMetadataFromHalV7(const std::vector<record_track_metadata_v7_t>& halTracks,
187 bool ignoreNonVendorTags, SinkMetadata* sinkMetadata) {
188 std::vector<record_track_metadata_t> bases;
189 bases.reserve(halTracks.size());
190 std::transform(halTracks.begin(), halTracks.end(), std::back_inserter(bases),
191 [](const record_track_metadata_v7_t& src) -> record_track_metadata_t {
192 record_track_metadata_t result;
193 record_track_metadata_from_v7(&result, &src);
194 return result;
195 });
196 status_t result = sinkMetadataFromHal(bases, sinkMetadata);
197 #if MAJOR_VERSION >= 7
198 for (size_t i = 0; i < halTracks.size(); ++i) {
199 auto& trackMetadata = sinkMetadata->tracks[i];
200 const auto& halTrackMetadata = halTracks[i];
201 CONVERT_CHECKED(
202 HidlUtils::audioChannelMaskFromHal(halTrackMetadata.channel_mask, true /*isInput*/,
203 &trackMetadata.channelMask),
204 result);
205 std::vector<std::string> strTags = HidlUtils::splitAudioTags(halTrackMetadata.tags);
206 if (ignoreNonVendorTags) {
207 strTags = HidlUtils::filterOutNonVendorTags(strTags);
208 }
209 CONVERT_CHECKED(HidlUtils::audioTagsFromHal(strTags, &trackMetadata.tags), result);
210 }
211 #else
212 (void)ignoreNonVendorTags;
213 #endif
214 return result;
215 }
216
sinkMetadataToHal(const SinkMetadata & sinkMetadata,std::vector<record_track_metadata_t> * halTracks)217 status_t CoreUtils::sinkMetadataToHal(const SinkMetadata& sinkMetadata,
218 std::vector<record_track_metadata_t>* halTracks) {
219 status_t result = NO_ERROR;
220 if (halTracks != nullptr) {
221 halTracks->reserve(sinkMetadata.tracks.size());
222 }
223 for (auto& trackMetadata : sinkMetadata.tracks) {
224 record_track_metadata halTrackMetadata{.gain = trackMetadata.gain};
225 CONVERT_CHECKED(HidlUtils::audioSourceToHal(trackMetadata.source, &halTrackMetadata.source),
226 result);
227 #if MAJOR_VERSION >= 5
228 if (trackMetadata.destination.getDiscriminator() ==
229 RecordTrackMetadata::Destination::hidl_discriminator::device) {
230 CONVERT_CHECKED(deviceAddressToHal(trackMetadata.destination.device(),
231 &halTrackMetadata.dest_device,
232 halTrackMetadata.dest_device_address),
233 result);
234 }
235 #endif
236 if (halTracks != nullptr) {
237 halTracks->push_back(std::move(halTrackMetadata));
238 }
239 }
240 return result;
241 }
242
sinkMetadataToHalV7(const SinkMetadata & sinkMetadata,bool ignoreNonVendorTags,std::vector<record_track_metadata_v7_t> * halTracks)243 status_t CoreUtils::sinkMetadataToHalV7(const SinkMetadata& sinkMetadata, bool ignoreNonVendorTags,
244 std::vector<record_track_metadata_v7_t>* halTracks) {
245 std::vector<record_track_metadata> bases;
246 status_t result = sinkMetadataToHal(sinkMetadata, halTracks != nullptr ? &bases : nullptr);
247 if (halTracks != nullptr) {
248 halTracks->reserve(sinkMetadata.tracks.size());
249 }
250 for (size_t i = 0; i < sinkMetadata.tracks.size(); ++i) {
251 record_track_metadata_v7_t halTrackMetadata;
252 if (halTracks != nullptr) {
253 record_track_metadata_to_v7(&halTrackMetadata, &bases[i]);
254 }
255 #if MAJOR_VERSION >= 7
256 const auto& trackMetadata = sinkMetadata.tracks[i];
257 CONVERT_CHECKED(HidlUtils::audioChannelMaskToHal(trackMetadata.channelMask,
258 &halTrackMetadata.channel_mask),
259 result);
260 if (ignoreNonVendorTags) {
261 CONVERT_CHECKED(
262 HidlUtils::audioTagsToHal(HidlUtils::filterOutNonVendorTags(trackMetadata.tags),
263 halTrackMetadata.tags),
264 result);
265 } else {
266 CONVERT_CHECKED(HidlUtils::audioTagsToHal(trackMetadata.tags, halTrackMetadata.tags),
267 result);
268 }
269 #else
270 (void)ignoreNonVendorTags;
271 #endif
272 if (halTracks != nullptr) {
273 halTracks->push_back(std::move(halTrackMetadata));
274 }
275 }
276 return result;
277 }
278
sourceMetadataFromHal(const std::vector<playback_track_metadata_t> & halTracks,SourceMetadata * sourceMetadata)279 status_t CoreUtils::sourceMetadataFromHal(const std::vector<playback_track_metadata_t>& halTracks,
280 SourceMetadata* sourceMetadata) {
281 status_t result = NO_ERROR;
282 sourceMetadata->tracks.resize(halTracks.size());
283 for (size_t i = 0; i < sourceMetadata->tracks.size(); ++i) {
284 const auto& halTrackMetadata = halTracks[i];
285 PlaybackTrackMetadata trackMetadata{};
286 CONVERT_CHECKED(HidlUtils::audioUsageFromHal(halTrackMetadata.usage, &trackMetadata.usage),
287 result);
288 CONVERT_CHECKED(HidlUtils::audioContentTypeFromHal(halTrackMetadata.content_type,
289 &trackMetadata.contentType),
290 result);
291 trackMetadata.gain = halTrackMetadata.gain;
292 #if MAJOR_VERSION >= 7
293 trackMetadata.channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_NONE);
294 #endif
295 sourceMetadata->tracks[i] = std::move(trackMetadata);
296 }
297 return result;
298 }
299
sourceMetadataFromHalV7(const std::vector<playback_track_metadata_v7_t> & halTracks,bool ignoreNonVendorTags,SourceMetadata * sourceMetadata)300 status_t CoreUtils::sourceMetadataFromHalV7(
301 const std::vector<playback_track_metadata_v7_t>& halTracks, bool ignoreNonVendorTags,
302 SourceMetadata* sourceMetadata) {
303 std::vector<playback_track_metadata_t> bases;
304 bases.reserve(halTracks.size());
305 std::transform(halTracks.begin(), halTracks.end(), std::back_inserter(bases),
306 [](const playback_track_metadata_v7_t& src) -> playback_track_metadata_t {
307 playback_track_metadata_t result;
308 playback_track_metadata_from_v7(&result, &src);
309 return result;
310 });
311 status_t result = sourceMetadataFromHal(bases, sourceMetadata);
312 #if MAJOR_VERSION >= 7
313 for (size_t i = 0; i < halTracks.size(); ++i) {
314 auto& trackMetadata = sourceMetadata->tracks[i];
315 const auto& halTrackMetadata = halTracks[i];
316 CONVERT_CHECKED(
317 HidlUtils::audioChannelMaskFromHal(halTrackMetadata.channel_mask, false /*isInput*/,
318 &trackMetadata.channelMask),
319 result);
320 std::vector<std::string> strTags = HidlUtils::splitAudioTags(halTrackMetadata.tags);
321 if (ignoreNonVendorTags) {
322 strTags = HidlUtils::filterOutNonVendorTags(strTags);
323 }
324 CONVERT_CHECKED(HidlUtils::audioTagsFromHal(strTags, &trackMetadata.tags), result);
325 }
326 #else
327 (void)ignoreNonVendorTags;
328 #endif
329 return result;
330 }
331
sourceMetadataToHal(const SourceMetadata & sourceMetadata,std::vector<playback_track_metadata_t> * halTracks)332 status_t CoreUtils::sourceMetadataToHal(const SourceMetadata& sourceMetadata,
333 std::vector<playback_track_metadata_t>* halTracks) {
334 status_t result = NO_ERROR;
335 if (halTracks != nullptr) {
336 halTracks->reserve(sourceMetadata.tracks.size());
337 }
338 for (auto& trackMetadata : sourceMetadata.tracks) {
339 playback_track_metadata_t halTrackMetadata{.gain = trackMetadata.gain};
340 CONVERT_CHECKED(HidlUtils::audioUsageToHal(trackMetadata.usage, &halTrackMetadata.usage),
341 result);
342 CONVERT_CHECKED(HidlUtils::audioContentTypeToHal(trackMetadata.contentType,
343 &halTrackMetadata.content_type),
344 result);
345 if (halTracks != nullptr) {
346 halTracks->push_back(std::move(halTrackMetadata));
347 }
348 }
349 return result;
350 }
351
sourceMetadataToHalV7(const SourceMetadata & sourceMetadata,bool ignoreNonVendorTags,std::vector<playback_track_metadata_v7_t> * halTracks)352 status_t CoreUtils::sourceMetadataToHalV7(const SourceMetadata& sourceMetadata,
353 bool ignoreNonVendorTags,
354 std::vector<playback_track_metadata_v7_t>* halTracks) {
355 std::vector<playback_track_metadata_t> bases;
356 status_t result = sourceMetadataToHal(sourceMetadata, halTracks != nullptr ? &bases : nullptr);
357 if (halTracks != nullptr) {
358 halTracks->reserve(sourceMetadata.tracks.size());
359 }
360 for (size_t i = 0; i < sourceMetadata.tracks.size(); ++i) {
361 playback_track_metadata_v7_t halTrackMetadata;
362 if (halTracks != nullptr) {
363 playback_track_metadata_to_v7(&halTrackMetadata, &bases[i]);
364 }
365 #if MAJOR_VERSION >= 7
366 const auto& trackMetadata = sourceMetadata.tracks[i];
367 CONVERT_CHECKED(HidlUtils::audioChannelMaskToHal(trackMetadata.channelMask,
368 &halTrackMetadata.channel_mask),
369 result);
370 if (ignoreNonVendorTags) {
371 CONVERT_CHECKED(
372 HidlUtils::audioTagsToHal(HidlUtils::filterOutNonVendorTags(trackMetadata.tags),
373 halTrackMetadata.tags),
374 result);
375 } else {
376 CONVERT_CHECKED(HidlUtils::audioTagsToHal(trackMetadata.tags, halTrackMetadata.tags),
377 result);
378 }
379 #else
380 (void)ignoreNonVendorTags;
381 #endif
382 if (halTracks != nullptr) {
383 halTracks->push_back(std::move(halTrackMetadata));
384 }
385 }
386 return result;
387 }
388 #endif // MAJOR_VERSION >= 4
389
390 #if MAJOR_VERSION >= 7
391 namespace xsd {
392 using namespace ::android::audio::policy::configuration::CPP_VERSION;
393 }
394
audioInputFlagsFromHal(audio_input_flags_t halFlagMask,AudioInputFlags * flags)395 status_t CoreUtils::audioInputFlagsFromHal(audio_input_flags_t halFlagMask,
396 AudioInputFlags* flags) {
397 status_t status = NO_ERROR;
398 std::vector<AudioInOutFlag> result;
399 for (uint32_t bit = 0; halFlagMask != 0 && bit < sizeof(audio_input_flags_t) * 8; ++bit) {
400 audio_input_flags_t flag = static_cast<audio_input_flags_t>(1u << bit);
401 if ((flag & halFlagMask) == flag) {
402 AudioInOutFlag flagStr = audio_input_flag_to_string(flag);
403 if (!flagStr.empty() && !xsd::isUnknownAudioInOutFlag(flagStr)) {
404 result.push_back(flagStr);
405 } else {
406 ALOGE("Unknown audio input flag value 0x%X", flag);
407 status = BAD_VALUE;
408 }
409 halFlagMask = static_cast<audio_input_flags_t>(halFlagMask & ~flag);
410 }
411 }
412 *flags = result;
413 return status;
414 }
415
audioInputFlagsToHal(const AudioInputFlags & flags,audio_input_flags_t * halFlagMask)416 status_t CoreUtils::audioInputFlagsToHal(const AudioInputFlags& flags,
417 audio_input_flags_t* halFlagMask) {
418 status_t status = NO_ERROR;
419 *halFlagMask = {};
420 for (const auto& flag : flags) {
421 audio_input_flags_t halFlag;
422 if (!xsd::isUnknownAudioInOutFlag(flag) &&
423 audio_input_flag_from_string(flag.c_str(), &halFlag)) {
424 *halFlagMask = static_cast<audio_input_flags_t>(*halFlagMask | halFlag);
425 } else {
426 ALOGE("Unknown audio input flag \"%s\"", flag.c_str());
427 status = BAD_VALUE;
428 }
429 }
430 return status;
431 }
432
audioOutputFlagsFromHal(audio_output_flags_t halFlagMask,AudioOutputFlags * flags)433 status_t CoreUtils::audioOutputFlagsFromHal(audio_output_flags_t halFlagMask,
434 AudioOutputFlags* flags) {
435 status_t status = NO_ERROR;
436 std::vector<AudioInOutFlag> result;
437 for (uint32_t bit = 0; halFlagMask != 0 && bit < sizeof(audio_output_flags_t) * 8; ++bit) {
438 audio_output_flags_t flag = static_cast<audio_output_flags_t>(1u << bit);
439 if ((flag & halFlagMask) == flag) {
440 AudioInOutFlag flagStr = audio_output_flag_to_string(flag);
441 if (!flagStr.empty() && !xsd::isUnknownAudioInOutFlag(flagStr)) {
442 result.push_back(flagStr);
443 } else {
444 ALOGE("Unknown audio output flag value 0x%X", flag);
445 status = BAD_VALUE;
446 }
447 halFlagMask = static_cast<audio_output_flags_t>(halFlagMask & ~flag);
448 }
449 }
450 *flags = result;
451 return status;
452 }
453
audioOutputFlagsToHal(const AudioOutputFlags & flags,audio_output_flags_t * halFlagMask)454 status_t CoreUtils::audioOutputFlagsToHal(const AudioOutputFlags& flags,
455 audio_output_flags_t* halFlagMask) {
456 status_t status = NO_ERROR;
457 *halFlagMask = {};
458 for (const auto& flag : flags) {
459 audio_output_flags_t halFlag;
460 if (!xsd::isUnknownAudioInOutFlag(flag) &&
461 audio_output_flag_from_string(flag.c_str(), &halFlag)) {
462 *halFlagMask = static_cast<audio_output_flags_t>(*halFlagMask | halFlag);
463 } else {
464 ALOGE("Unknown audio output flag \"%s\"", flag.c_str());
465 status = BAD_VALUE;
466 }
467 }
468 return status;
469 }
470 #endif
471
472 } // namespace implementation
473 } // namespace CORE_TYPES_CPP_VERSION
474 } // namespace audio
475 } // namespace hardware
476 } // namespace android
477