blob: 9b14a5e38a3580140254618c66b74feebe1416ed [file] [log] [blame]
Shunkai Yao51202502022-12-12 06:11:46 +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 Naganovb6e57752023-03-08 18:12:47 -080017#include <sstream>
Shunkai Yao51202502022-12-12 06:11:46 +000018#include <utility>
19
Mikhail Naganovb6e57752023-03-08 18:12:47 -080020#include <system/audio.h>
Shunkai Yao51202502022-12-12 06:11:46 +000021#define LOG_TAG "AidlConversionNdk"
22//#define LOG_NDEBUG 0
23#include <utils/Log.h>
Mikhail Naganovb6e57752023-03-08 18:12:47 -080024#include <utils/Errors.h>
Shunkai Yao51202502022-12-12 06:11:46 +000025
26#include <media/AidlConversionCppNdk.h>
27#include <media/AidlConversionNdk.h>
Mikhail Naganovb6e57752023-03-08 18:12:47 -080028#include <Utils.h>
Shunkai Yao51202502022-12-12 06:11:46 +000029
30////////////////////////////////////////////////////////////////////////////////////////////////////
31// AIDL NDK backend to legacy audio data structure conversion utilities.
32
33namespace aidl {
34namespace android {
35
Mikhail Naganovb6e57752023-03-08 18:12:47 -080036using hardware::audio::common::PlaybackTrackMetadata;
37using hardware::audio::common::RecordTrackMetadata;
38using ::android::BAD_VALUE;
39using ::android::OK;
40
41namespace {
42
43::android::status_t combineString(
44 const std::vector<std::string>& v, char separator, std::string* result) {
45 std::ostringstream oss;
46 for (const auto& s : v) {
47 if (oss.tellp() > 0) {
48 oss << separator;
49 }
50 if (s.find(separator) == std::string::npos) {
51 oss << s;
52 } else {
53 ALOGE("%s: string \"%s\" contains separator character \"%c\"",
54 __func__, s.c_str(), separator);
55 return BAD_VALUE;
56 }
57 }
58 *result = oss.str();
59 return OK;
60}
61
62std::vector<std::string> splitString(const std::string& s, char separator) {
63 std::istringstream iss(s);
64 std::string t;
65 std::vector<std::string> result;
66 while (std::getline(iss, t, separator)) {
67 result.push_back(std::move(t));
68 }
69 return result;
70}
71
72std::vector<std::string> filterOutNonVendorTags(const std::vector<std::string>& tags) {
73 std::vector<std::string> result;
74 std::copy_if(tags.begin(), tags.end(), std::back_inserter(result),
Mikhail Naganov6352e822023-03-09 18:22:36 -080075 ::aidl::android::hardware::audio::common::maybeVendorExtension);
Mikhail Naganovb6e57752023-03-08 18:12:47 -080076 return result;
77}
78
79} // namespace
80
Shunkai Yao44bdbad2023-01-14 05:11:58 +000081// buffer_provider_t is not supported thus skipped
Shunkai Yao5c718342023-02-23 23:49:51 +000082ConversionResult<buffer_config_t> aidl2legacy_AudioConfig_buffer_config_t(
83 const media::audio::common::AudioConfig& aidl, bool isInput) {
Shunkai Yao51202502022-12-12 06:11:46 +000084 buffer_config_t legacy;
85
Shunkai Yao5c718342023-02-23 23:49:51 +000086 legacy.samplingRate = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.base.sampleRate));
Shunkai Yao51202502022-12-12 06:11:46 +000087 legacy.mask |= EFFECT_CONFIG_SMP_RATE;
88
89 legacy.channels = VALUE_OR_RETURN(
Shunkai Yao5c718342023-02-23 23:49:51 +000090 aidl2legacy_AudioChannelLayout_audio_channel_mask_t(aidl.base.channelMask, isInput));
Shunkai Yao51202502022-12-12 06:11:46 +000091 legacy.mask |= EFFECT_CONFIG_CHANNELS;
92
Shunkai Yao5c718342023-02-23 23:49:51 +000093 legacy.format =
94 VALUE_OR_RETURN(aidl2legacy_AudioFormatDescription_audio_format_t(aidl.base.format));
Shunkai Yao51202502022-12-12 06:11:46 +000095 legacy.mask |= EFFECT_CONFIG_FORMAT;
Shunkai Yao5c718342023-02-23 23:49:51 +000096 legacy.buffer.frameCount = aidl.frameCount;
Shunkai Yao51202502022-12-12 06:11:46 +000097
Shunkai Yao44bdbad2023-01-14 05:11:58 +000098 // TODO: add accessMode and mask
Shunkai Yao51202502022-12-12 06:11:46 +000099 return legacy;
100}
101
Shunkai Yao5c718342023-02-23 23:49:51 +0000102ConversionResult<media::audio::common::AudioConfig>
103legacy2aidl_buffer_config_t_AudioConfig(const buffer_config_t& legacy, bool isInput) {
104 media::audio::common::AudioConfig aidl;
Shunkai Yao51202502022-12-12 06:11:46 +0000105
106 if (legacy.mask & EFFECT_CONFIG_SMP_RATE) {
Shunkai Yao5c718342023-02-23 23:49:51 +0000107 aidl.base.sampleRate = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.samplingRate));
Shunkai Yao51202502022-12-12 06:11:46 +0000108 }
109 if (legacy.mask & EFFECT_CONFIG_CHANNELS) {
Shunkai Yao5c718342023-02-23 23:49:51 +0000110 aidl.base.channelMask = VALUE_OR_RETURN(legacy2aidl_audio_channel_mask_t_AudioChannelLayout(
Shunkai Yao51202502022-12-12 06:11:46 +0000111 static_cast<audio_channel_mask_t>(legacy.channels), isInput));
112 }
113 if (legacy.mask & EFFECT_CONFIG_FORMAT) {
Shunkai Yao5c718342023-02-23 23:49:51 +0000114 aidl.base.format = VALUE_OR_RETURN(legacy2aidl_audio_format_t_AudioFormatDescription(
Shunkai Yao51202502022-12-12 06:11:46 +0000115 static_cast<audio_format_t>(legacy.format)));
116 }
Shunkai Yao5c718342023-02-23 23:49:51 +0000117 aidl.frameCount = legacy.buffer.frameCount;
Shunkai Yao44bdbad2023-01-14 05:11:58 +0000118
119 // TODO: add accessMode and mask
Shunkai Yao51202502022-12-12 06:11:46 +0000120 return aidl;
121}
122
Mikhail Naganovb6e57752023-03-08 18:12:47 -0800123::android::status_t aidl2legacy_AudioAttributesTags(
124 const std::vector<std::string>& aidl, char* legacy) {
125 std::string aidlTags;
126 RETURN_STATUS_IF_ERROR(combineString(
127 filterOutNonVendorTags(aidl), AUDIO_ATTRIBUTES_TAGS_SEPARATOR, &aidlTags));
128 RETURN_STATUS_IF_ERROR(aidl2legacy_string(aidlTags, legacy, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE));
129 return OK;
130}
131
132ConversionResult<std::vector<std::string>> legacy2aidl_AudioAttributesTags(const char* legacy) {
133 std::string legacyTags = VALUE_OR_RETURN(legacy2aidl_string(
134 legacy, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE));
135 return filterOutNonVendorTags(splitString(legacyTags, AUDIO_ATTRIBUTES_TAGS_SEPARATOR));
136}
137
138ConversionResult<playback_track_metadata_v7>
139aidl2legacy_PlaybackTrackMetadata_playback_track_metadata_v7(const PlaybackTrackMetadata& aidl) {
140 playback_track_metadata_v7 legacy;
141 legacy.base.usage = VALUE_OR_RETURN(aidl2legacy_AudioUsage_audio_usage_t(aidl.usage));
142 legacy.base.content_type = VALUE_OR_RETURN(aidl2legacy_AudioContentType_audio_content_type_t(
143 aidl.contentType));
144 legacy.base.gain = aidl.gain;
145 legacy.channel_mask = VALUE_OR_RETURN(aidl2legacy_AudioChannelLayout_audio_channel_mask_t(
146 aidl.channelMask, false /*isInput*/));
147 RETURN_IF_ERROR(aidl2legacy_AudioAttributesTags(aidl.tags, legacy.tags));
148 return legacy;
149}
150
151ConversionResult<PlaybackTrackMetadata>
152legacy2aidl_playback_track_metadata_v7_PlaybackTrackMetadata(
153 const playback_track_metadata_v7& legacy) {
154 PlaybackTrackMetadata aidl;
155 aidl.usage = VALUE_OR_RETURN(legacy2aidl_audio_usage_t_AudioUsage(legacy.base.usage));
156 aidl.contentType = VALUE_OR_RETURN(legacy2aidl_audio_content_type_t_AudioContentType(
157 legacy.base.content_type));
158 aidl.gain = legacy.base.gain;
159 aidl.channelMask = VALUE_OR_RETURN(legacy2aidl_audio_channel_mask_t_AudioChannelLayout(
160 legacy.channel_mask, false /*isInput*/));
161 aidl.tags = VALUE_OR_RETURN(legacy2aidl_AudioAttributesTags(legacy.tags));
162 return aidl;
163}
164
165ConversionResult<record_track_metadata_v7>
166aidl2legacy_RecordTrackMetadata_record_track_metadata_v7(const RecordTrackMetadata& aidl) {
167 record_track_metadata_v7 legacy;
168 legacy.base.source = VALUE_OR_RETURN(aidl2legacy_AudioSource_audio_source_t(aidl.source));
169 legacy.base.gain = aidl.gain;
170 if (aidl.destinationDevice.has_value()) {
171 RETURN_IF_ERROR(aidl2legacy_AudioDevice_audio_device(aidl.destinationDevice.value(),
172 &legacy.base.dest_device, legacy.base.dest_device_address));
173 } else {
174 legacy.base.dest_device = AUDIO_DEVICE_NONE;
175 }
176 legacy.channel_mask = VALUE_OR_RETURN(aidl2legacy_AudioChannelLayout_audio_channel_mask_t(
177 aidl.channelMask, true /*isInput*/));
178 RETURN_IF_ERROR(aidl2legacy_AudioAttributesTags(aidl.tags, legacy.tags));
179 return legacy;
180}
181
182ConversionResult<RecordTrackMetadata>
183legacy2aidl_record_track_metadata_v7_RecordTrackMetadata(const record_track_metadata_v7& legacy) {
184 RecordTrackMetadata aidl;
185 aidl.source = VALUE_OR_RETURN(legacy2aidl_audio_source_t_AudioSource(legacy.base.source));
186 aidl.gain = legacy.base.gain;
187 if (legacy.base.dest_device != AUDIO_DEVICE_NONE) {
188 aidl.destinationDevice = VALUE_OR_RETURN(legacy2aidl_audio_device_AudioDevice(
189 legacy.base.dest_device, legacy.base.dest_device_address));
190 }
191 aidl.channelMask = VALUE_OR_RETURN(legacy2aidl_audio_channel_mask_t_AudioChannelLayout(
192 legacy.channel_mask, true /*isInput*/));
193 aidl.tags = VALUE_OR_RETURN(legacy2aidl_AudioAttributesTags(legacy.tags));
194 return aidl;
195}
196
Shunkai Yao51202502022-12-12 06:11:46 +0000197} // namespace android
198} // aidl