1 /*
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 "AudioTypes.h"
18 #include "StringUtils.h"
19 #include <media/TypeConverter.h> // requires libmedia_helper to get the Audio code.
20
21 namespace android::mediametrics::types {
22
getAudioCallerNameMap()23 const std::unordered_map<std::string, int32_t>& getAudioCallerNameMap() {
24 // DO NOT MODIFY VALUES (OK to add new ones).
25 // This may be found in frameworks/av/media/libmediametrics/include/MediaMetricsConstants.h
26 static std::unordered_map<std::string, int32_t> map{
27 {"unknown", 0}, // callerName not set
28 {"aaudio", 1}, // Native AAudio
29 {"java", 2}, // Java API layer
30 {"media", 3}, // libmedia (mediaplayer)
31 {"opensles", 4}, // Open SLES
32 {"rtp", 5}, // RTP communication
33 {"soundpool", 6}, // SoundPool
34 {"tonegenerator", 7}, // dial tones
35 // R values above.
36 };
37 return map;
38 }
39
40 // A map in case we need to return a flag for input devices.
41 // This is 64 bits (and hence not the same as audio_device_t) because we need extra
42 // bits to represent new devices.
43 // NOT USED FOR R. We do not use int64 flags.
44 // This can be out of date for now, as it is unused even for string validation
45 // (instead TypeConverter<InputDeviceTraits> is used).
getAudioDeviceInMap()46 const std::unordered_map<std::string, int64_t>& getAudioDeviceInMap() {
47 // DO NOT MODIFY VALUES (OK to add new ones). This does NOT match audio_device_t.
48 static std::unordered_map<std::string, int64_t> map{
49 {"AUDIO_DEVICE_IN_COMMUNICATION", 1LL << 0},
50 {"AUDIO_DEVICE_IN_AMBIENT", 1LL << 1},
51 {"AUDIO_DEVICE_IN_BUILTIN_MIC", 1LL << 2},
52 {"AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET", 1LL << 3},
53 {"AUDIO_DEVICE_IN_WIRED_HEADSET", 1LL << 4},
54 {"AUDIO_DEVICE_IN_AUX_DIGITAL", 1LL << 5},
55 {"AUDIO_DEVICE_IN_HDMI", 1LL << 5}, // HDMI == AUX_DIGITAL (6 reserved)
56 {"AUDIO_DEVICE_IN_VOICE_CALL", 1LL << 7},
57 {"AUDIO_DEVICE_IN_TELEPHONY_RX", 1LL << 7}, // TELEPHONY_RX == VOICE_CALL (8 reserved)
58 {"AUDIO_DEVICE_IN_BACK_MIC", 1LL << 9},
59 {"AUDIO_DEVICE_IN_REMOTE_SUBMIX", 1LL << 10},
60 {"AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET", 1LL << 11},
61 {"AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET", 1LL << 12},
62 {"AUDIO_DEVICE_IN_USB_ACCESSORY", 1LL << 13},
63 {"AUDIO_DEVICE_IN_USB_DEVICE", 1LL << 14},
64 {"AUDIO_DEVICE_IN_FM_TUNER", 1LL << 15},
65 {"AUDIO_DEVICE_IN_TV_TUNER", 1LL << 16},
66 {"AUDIO_DEVICE_IN_LINE", 1LL << 17},
67 {"AUDIO_DEVICE_IN_SPDIF", 1LL << 18},
68 {"AUDIO_DEVICE_IN_BLUETOOTH_A2DP", 1LL << 19},
69 {"AUDIO_DEVICE_IN_LOOPBACK", 1LL << 20},
70 {"AUDIO_DEVICE_IN_IP", 1LL << 21},
71 {"AUDIO_DEVICE_IN_BUS", 1LL << 22},
72 {"AUDIO_DEVICE_IN_PROXY", 1LL << 23},
73 {"AUDIO_DEVICE_IN_USB_HEADSET", 1LL << 24},
74 {"AUDIO_DEVICE_IN_BLUETOOTH_BLE", 1LL << 25},
75 {"AUDIO_DEVICE_IN_HDMI_ARC", 1LL << 26},
76 {"AUDIO_DEVICE_IN_ECHO_REFERENCE", 1LL << 27},
77 {"AUDIO_DEVICE_IN_DEFAULT", 1LL << 28},
78 // R values above.
79 };
80 return map;
81 }
82
83 // A map in case we need to return a flag for output devices.
84 // This is 64 bits (and hence not the same as audio_device_t) because we need extra
85 // bits to represent new devices.
86 // NOT USED FOR R. We do not use int64 flags.
87 // This can be out of date for now, as it is unused even for string validation
88 // (instead TypeConverter<OutputDeviceTraits> is used).
getAudioDeviceOutMap()89 const std::unordered_map<std::string, int64_t>& getAudioDeviceOutMap() {
90 // DO NOT MODIFY VALUES (OK to add new ones). This does NOT match audio_device_t.
91 static std::unordered_map<std::string, int64_t> map{
92 {"AUDIO_DEVICE_OUT_EARPIECE", 1LL << 0},
93 {"AUDIO_DEVICE_OUT_SPEAKER", 1LL << 1},
94 {"AUDIO_DEVICE_OUT_WIRED_HEADSET", 1LL << 2},
95 {"AUDIO_DEVICE_OUT_WIRED_HEADPHONE", 1LL << 3},
96 {"AUDIO_DEVICE_OUT_BLUETOOTH_SCO", 1LL << 4},
97 {"AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET", 1LL << 5},
98 {"AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT", 1LL << 6},
99 {"AUDIO_DEVICE_OUT_BLUETOOTH_A2DP", 1LL << 7},
100 {"AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES", 1LL << 8},
101 {"AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER", 1LL << 9},
102 {"AUDIO_DEVICE_OUT_AUX_DIGITAL", 1LL << 10},
103 {"AUDIO_DEVICE_OUT_HDMI", 1LL << 10}, // HDMI == AUX_DIGITAL (11 reserved)
104 {"AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET", 1LL << 12},
105 {"AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET", 1LL << 13},
106 {"AUDIO_DEVICE_OUT_USB_ACCESSORY", 1LL << 14},
107 {"AUDIO_DEVICE_OUT_USB_DEVICE", 1LL << 15},
108 {"AUDIO_DEVICE_OUT_REMOTE_SUBMIX", 1LL << 16},
109 {"AUDIO_DEVICE_OUT_TELEPHONY_TX", 1LL << 17},
110 {"AUDIO_DEVICE_OUT_LINE", 1LL << 18},
111 {"AUDIO_DEVICE_OUT_HDMI_ARC", 1LL << 19},
112 {"AUDIO_DEVICE_OUT_SPDIF", 1LL << 20},
113 {"AUDIO_DEVICE_OUT_FM", 1LL << 21},
114 {"AUDIO_DEVICE_OUT_AUX_LINE", 1LL << 22},
115 {"AUDIO_DEVICE_OUT_SPEAKER_SAFE", 1LL << 23},
116 {"AUDIO_DEVICE_OUT_IP", 1LL << 24},
117 {"AUDIO_DEVICE_OUT_BUS", 1LL << 25},
118 {"AUDIO_DEVICE_OUT_PROXY", 1LL << 26},
119 {"AUDIO_DEVICE_OUT_USB_HEADSET", 1LL << 27},
120 {"AUDIO_DEVICE_OUT_HEARING_AID", 1LL << 28},
121 {"AUDIO_DEVICE_OUT_ECHO_CANCELLER", 1LL << 29},
122 {"AUDIO_DEVICE_OUT_DEFAULT", 1LL << 30},
123 // R values above.
124 };
125 return map;
126 }
127
getAudioThreadTypeMap()128 const std::unordered_map<std::string, int32_t>& getAudioThreadTypeMap() {
129 // DO NOT MODIFY VALUES (OK to add new ones).
130 // This may be found in frameworks/av/services/audioflinger/Threads.h
131 static std::unordered_map<std::string, int32_t> map{
132 // UNKNOWN is -1
133 {"MIXER", 0}, // Thread class is MixerThread
134 {"DIRECT", 1}, // Thread class is DirectOutputThread
135 {"DUPLICATING", 2}, // Thread class is DuplicatingThread
136 {"RECORD", 3}, // Thread class is RecordThread
137 {"OFFLOAD", 4}, // Thread class is OffloadThread
138 {"MMAP_PLAYBACK", 5}, // Thread class for MMAP playback stream
139 {"MMAP_CAPTURE", 6}, // Thread class for MMAP capture stream
140 // R values above.
141 };
142 return map;
143 }
144
getAudioTrackTraitsMap()145 const std::unordered_map<std::string, int32_t>& getAudioTrackTraitsMap() {
146 // DO NOT MODIFY VALUES (OK to add new ones).
147 static std::unordered_map<std::string, int32_t> map{
148 {"static", (1 << 0)}, // A static track
149 // R values above.
150 };
151 return map;
152 }
153
154 // Helper: Create the corresponding int32 from string flags split with '|'.
155 template <typename Traits>
int32FromFlags(const std::string & flags)156 int32_t int32FromFlags(const std::string &flags)
157 {
158 const auto result = stringutils::split(flags, "|");
159 int32_t intFlags = 0;
160 for (const auto& flag : result) {
161 typename Traits::Type value;
162 if (!TypeConverter<Traits>::fromString(flag, value)) {
163 break;
164 }
165 intFlags |= value;
166 }
167 return intFlags;
168 }
169
170 template <typename Traits>
stringFromFlags(const std::string & flags,size_t len)171 std::string stringFromFlags(const std::string &flags, size_t len)
172 {
173 const auto result = stringutils::split(flags, "|");
174 std::string sFlags;
175 for (const auto& flag : result) {
176 typename Traits::Type value;
177 if (!TypeConverter<Traits>::fromString(flag, value)) {
178 break;
179 }
180 if (len >= flag.size()) continue;
181 if (!sFlags.empty()) sFlags += "|";
182 sFlags += flag.c_str() + len;
183 }
184 return sFlags;
185 }
186
187 template <typename M>
validateStringFromMap(const std::string & str,const M & map)188 std::string validateStringFromMap(const std::string &str, const M& map)
189 {
190 if (str.empty()) return {};
191
192 const auto result = stringutils::split(str, "|");
193 std::stringstream ss;
194 for (const auto &s : result) {
195 if (map.count(s) > 0) {
196 if (ss.tellp() > 0) ss << "|";
197 ss << s;
198 }
199 }
200 return ss.str();
201 }
202
203 template <typename M>
flagsFromMap(const std::string & str,const M & map)204 typename M::mapped_type flagsFromMap(const std::string &str, const M& map)
205 {
206 if (str.empty()) return {};
207
208 const auto result = stringutils::split(str, "|");
209 typename M::mapped_type value{};
210 for (const auto &s : result) {
211 auto it = map.find(s);
212 if (it == map.end()) continue;
213 value |= it->second;
214 }
215 return value;
216 }
217
218 template <>
lookup(const std::string & contentType)219 int32_t lookup<CONTENT_TYPE>(const std::string &contentType)
220 {
221 AudioContentTraits::Type value;
222 if (!TypeConverter<AudioContentTraits>::fromString(contentType, value)) {
223 value = AUDIO_CONTENT_TYPE_UNKNOWN;
224 }
225 return (int32_t)value;
226 }
227
228 template <>
lookup(const std::string & contentType)229 std::string lookup<CONTENT_TYPE>(const std::string &contentType)
230 {
231 AudioContentTraits::Type value;
232 if (!TypeConverter<AudioContentTraits>::fromString(contentType, value)) {
233 return "";
234 }
235 return contentType.c_str() + sizeof("AUDIO_CONTENT_TYPE");
236 }
237
238 template <>
lookup(const std::string & encoding)239 int32_t lookup<ENCODING>(const std::string &encoding)
240 {
241 FormatTraits::Type value;
242 if (!TypeConverter<FormatTraits>::fromString(encoding, value)) {
243 value = AUDIO_FORMAT_INVALID;
244 }
245 return (int32_t)value;
246 }
247
248 template <>
lookup(const std::string & encoding)249 std::string lookup<ENCODING>(const std::string &encoding)
250 {
251 FormatTraits::Type value;
252 if (!TypeConverter<FormatTraits>::fromString(encoding, value)) {
253 return "";
254 }
255 return encoding.c_str() + sizeof("AUDIO_FORMAT");
256 }
257
258 template <>
lookup(const std::string & inputFlag)259 int32_t lookup<INPUT_FLAG>(const std::string &inputFlag)
260 {
261 return int32FromFlags<InputFlagTraits>(inputFlag);
262 }
263
264 template <>
lookup(const std::string & inputFlag)265 std::string lookup<INPUT_FLAG>(const std::string &inputFlag)
266 {
267 return stringFromFlags<InputFlagTraits>(inputFlag, sizeof("AUDIO_INPUT_FLAG"));
268 }
269
270 template <>
lookup(const std::string & outputFlag)271 int32_t lookup<OUTPUT_FLAG>(const std::string &outputFlag)
272 {
273 return int32FromFlags<OutputFlagTraits>(outputFlag);
274 }
275
276 template <>
lookup(const std::string & outputFlag)277 std::string lookup<OUTPUT_FLAG>(const std::string &outputFlag)
278 {
279 return stringFromFlags<OutputFlagTraits>(outputFlag, sizeof("AUDIO_OUTPUT_FLAG"));
280 }
281
282 template <>
lookup(const std::string & sourceType)283 int32_t lookup<SOURCE_TYPE>(const std::string &sourceType)
284 {
285 SourceTraits::Type value;
286 if (!TypeConverter<SourceTraits>::fromString(sourceType, value)) {
287 value = AUDIO_SOURCE_DEFAULT;
288 }
289 return (int32_t)value;
290 }
291
292 template <>
lookup(const std::string & sourceType)293 std::string lookup<SOURCE_TYPE>(const std::string &sourceType)
294 {
295 SourceTraits::Type value;
296 if (!TypeConverter<SourceTraits>::fromString(sourceType, value)) {
297 return "";
298 }
299 return sourceType.c_str() + sizeof("AUDIO_SOURCE");
300 }
301
302 template <>
lookup(const std::string & streamType)303 int32_t lookup<STREAM_TYPE>(const std::string &streamType)
304 {
305 StreamTraits::Type value;
306 if (!TypeConverter<StreamTraits>::fromString(streamType, value)) {
307 value = AUDIO_STREAM_DEFAULT;
308 }
309 return (int32_t)value;
310 }
311
312 template <>
lookup(const std::string & streamType)313 std::string lookup<STREAM_TYPE>(const std::string &streamType)
314 {
315 StreamTraits::Type value;
316 if (!TypeConverter<StreamTraits>::fromString(streamType, value)) {
317 return "";
318 }
319 return streamType.c_str() + sizeof("AUDIO_STREAM");
320 }
321
322 template <>
lookup(const std::string & usage)323 int32_t lookup<USAGE>(const std::string &usage)
324 {
325 UsageTraits::Type value;
326 if (!TypeConverter<UsageTraits>::fromString(usage, value)) {
327 value = AUDIO_USAGE_UNKNOWN;
328 }
329 return (int32_t)value;
330 }
331
332 template <>
lookup(const std::string & usage)333 std::string lookup<USAGE>(const std::string &usage)
334 {
335 UsageTraits::Type value;
336 if (!TypeConverter<UsageTraits>::fromString(usage, value)) {
337 return "";
338 }
339 return usage.c_str() + sizeof("AUDIO_USAGE");
340 }
341
342 template <>
lookup(const std::string & inputDevice)343 int64_t lookup<INPUT_DEVICE>(const std::string &inputDevice)
344 {
345 // NOT USED FOR R.
346 // Returns a set of bits, each one representing a device in inputDevice.
347 // This is a 64 bit integer, not the same as audio_device_t.
348 return flagsFromMap(inputDevice, getAudioDeviceInMap());
349 }
350
351 template <>
lookup(const std::string & inputDevice)352 std::string lookup<INPUT_DEVICE>(const std::string &inputDevice)
353 {
354 return stringFromFlags<InputDeviceTraits>(inputDevice, sizeof("AUDIO_DEVICE_IN"));
355 }
356
357 template <>
lookup(const std::string & outputDevice)358 int64_t lookup<OUTPUT_DEVICE>(const std::string &outputDevice)
359 {
360 // NOT USED FOR R.
361 // Returns a set of bits, each one representing a device in outputDevice.
362 // This is a 64 bit integer, not the same as audio_device_t.
363 return flagsFromMap(outputDevice, getAudioDeviceOutMap());
364 }
365
366 template <>
lookup(const std::string & outputDevice)367 std::string lookup<OUTPUT_DEVICE>(const std::string &outputDevice)
368 {
369 return stringFromFlags<OutputDeviceTraits>(outputDevice, sizeof("AUDIO_DEVICE_OUT"));
370 }
371
372 template <>
lookup(const std::string & callerName)373 int32_t lookup<CALLER_NAME>(const std::string &callerName)
374 {
375 auto& map = getAudioCallerNameMap();
376 auto it = map.find(callerName);
377 if (it == map.end()) {
378 return 0; // return unknown
379 }
380 return it->second;
381 }
382
383 template <>
lookup(const std::string & callerName)384 std::string lookup<CALLER_NAME>(const std::string &callerName)
385 {
386 auto& map = getAudioCallerNameMap();
387 auto it = map.find(callerName);
388 if (it == map.end()) {
389 return "";
390 }
391 return callerName;
392 }
393
394 template <>
lookup(const std::string & threadType)395 int32_t lookup<THREAD_TYPE>(const std::string &threadType)
396 {
397 auto& map = getAudioThreadTypeMap();
398 auto it = map.find(threadType);
399 if (it == map.end()) {
400 return -1; // note this as an illegal thread value as we don't have unknown here.
401 }
402 return it->second;
403 }
404
405 template <>
lookup(const std::string & threadType)406 std::string lookup<THREAD_TYPE>(const std::string &threadType)
407 {
408 auto& map = getAudioThreadTypeMap();
409 auto it = map.find(threadType);
410 if (it == map.end()) {
411 return "";
412 }
413 return threadType;
414 }
415
isInputThreadType(const std::string & threadType)416 bool isInputThreadType(const std::string &threadType)
417 {
418 return threadType == "RECORD" || threadType == "MMAP_CAPTURE";
419 }
420
421 template <>
lookup(const std::string & traits)422 std::string lookup<TRACK_TRAITS>(const std::string &traits)
423 {
424 return validateStringFromMap(traits, getAudioTrackTraitsMap());
425 }
426
427 template <>
lookup(const std::string & traits)428 int32_t lookup<TRACK_TRAITS>(const std::string &traits)
429 {
430 return flagsFromMap(traits, getAudioTrackTraitsMap());
431 }
432
433 } // namespace android::mediametrics::types
434