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 {"AUDIO_DEVICE_IN_BLE_HEADSET", 1LL << 29},
80 {"AUDIO_DEVICE_IN_HDMI_EARC", 1LL << 30},
81 };
82 return map;
83 }
84
85 // A map in case we need to return a flag for output devices.
86 // This is 64 bits (and hence not the same as audio_device_t) because we need extra
87 // bits to represent new devices.
88 // NOT USED FOR R. We do not use int64 flags.
89 // This can be out of date for now, as it is unused even for string validation
90 // (instead TypeConverter<OutputDeviceTraits> is used).
getAudioDeviceOutMap()91 const std::unordered_map<std::string, int64_t>& getAudioDeviceOutMap() {
92 // DO NOT MODIFY VALUES (OK to add new ones). This does NOT match audio_device_t.
93 static std::unordered_map<std::string, int64_t> map{
94 {"AUDIO_DEVICE_OUT_EARPIECE", 1LL << 0},
95 {"AUDIO_DEVICE_OUT_SPEAKER", 1LL << 1},
96 {"AUDIO_DEVICE_OUT_WIRED_HEADSET", 1LL << 2},
97 {"AUDIO_DEVICE_OUT_WIRED_HEADPHONE", 1LL << 3},
98 {"AUDIO_DEVICE_OUT_BLUETOOTH_SCO", 1LL << 4},
99 {"AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET", 1LL << 5},
100 {"AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT", 1LL << 6},
101 {"AUDIO_DEVICE_OUT_BLUETOOTH_A2DP", 1LL << 7},
102 {"AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES", 1LL << 8},
103 {"AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER", 1LL << 9},
104 {"AUDIO_DEVICE_OUT_AUX_DIGITAL", 1LL << 10},
105 {"AUDIO_DEVICE_OUT_HDMI", 1LL << 10}, // HDMI == AUX_DIGITAL (11 reserved)
106 {"AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET", 1LL << 12},
107 {"AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET", 1LL << 13},
108 {"AUDIO_DEVICE_OUT_USB_ACCESSORY", 1LL << 14},
109 {"AUDIO_DEVICE_OUT_USB_DEVICE", 1LL << 15},
110 {"AUDIO_DEVICE_OUT_REMOTE_SUBMIX", 1LL << 16},
111 {"AUDIO_DEVICE_OUT_TELEPHONY_TX", 1LL << 17},
112 {"AUDIO_DEVICE_OUT_LINE", 1LL << 18},
113 {"AUDIO_DEVICE_OUT_HDMI_ARC", 1LL << 19},
114 {"AUDIO_DEVICE_OUT_SPDIF", 1LL << 20},
115 {"AUDIO_DEVICE_OUT_FM", 1LL << 21},
116 {"AUDIO_DEVICE_OUT_AUX_LINE", 1LL << 22},
117 {"AUDIO_DEVICE_OUT_SPEAKER_SAFE", 1LL << 23},
118 {"AUDIO_DEVICE_OUT_IP", 1LL << 24},
119 {"AUDIO_DEVICE_OUT_BUS", 1LL << 25},
120 {"AUDIO_DEVICE_OUT_PROXY", 1LL << 26},
121 {"AUDIO_DEVICE_OUT_USB_HEADSET", 1LL << 27},
122 {"AUDIO_DEVICE_OUT_HEARING_AID", 1LL << 28},
123 {"AUDIO_DEVICE_OUT_ECHO_CANCELLER", 1LL << 29},
124 {"AUDIO_DEVICE_OUT_DEFAULT", 1LL << 30},
125 // R values above.
126 {"AUDIO_DEVICE_OUT_BLE_HEADSET", 1LL << 31},
127 {"AUDIO_DEVICE_OUT_BLE_SPEAKER", 1LL << 32},
128 {"AUDIO_DEVICE_OUT_HDMI_EARC", 1LL << 33},
129 };
130 return map;
131 }
132
getAudioThreadTypeMap()133 const std::unordered_map<std::string, int32_t>& getAudioThreadTypeMap() {
134 // DO NOT MODIFY VALUES (OK to add new ones).
135 // This may be found in frameworks/av/services/audioflinger/Threads.h
136 static std::unordered_map<std::string, int32_t> map{
137 // UNKNOWN is -1
138 {"MIXER", 0}, // Thread class is MixerThread
139 {"DIRECT", 1}, // Thread class is DirectOutputThread
140 {"DUPLICATING", 2}, // Thread class is DuplicatingThread
141 {"RECORD", 3}, // Thread class is RecordThread
142 {"OFFLOAD", 4}, // Thread class is OffloadThread
143 {"MMAP_PLAYBACK", 5}, // Thread class for MMAP playback stream
144 {"MMAP_CAPTURE", 6}, // Thread class for MMAP capture stream
145 // R values above.
146 };
147 return map;
148 }
149
getAudioTrackTraitsMap()150 const std::unordered_map<std::string, int32_t>& getAudioTrackTraitsMap() {
151 // DO NOT MODIFY VALUES (OK to add new ones).
152 static std::unordered_map<std::string, int32_t> map{
153 {"static", (1 << 0)}, // A static track
154 // R values above.
155 };
156 return map;
157 }
158
getAAudioDirection()159 const std::unordered_map<std::string, int32_t>& getAAudioDirection() {
160 // DO NOT MODIFY VALUES(OK to add new ones).
161 // This may be found in frameworks/av/media/libaaudio/include/aaudio/AAudio.h
162 static std::unordered_map<std::string, int32_t> map {
163 // UNKNOWN is 0
164 {"AAUDIO_DIRECTION_OUTPUT", 1 /* AAUDIO_DIRECTION_OUTPUT + 1 */},
165 {"AAUDIO_DIRECTION_INPUT", 2 /* AAUDIO_DIRECTION_INPUT + 1*/},
166 };
167 return map;
168 }
169
getAAudioPerformanceMode()170 const std::unordered_map<std::string, int32_t>& getAAudioPerformanceMode() {
171 // DO NOT MODIFY VALUES(OK to add new ones).
172 // This may be found in frameworks/av/media/libaaudio/include/aaudio/AAudio.h
173 static std::unordered_map<std::string, int32_t> map {
174 // UNKNOWN is 0
175 {"AAUDIO_PERFORMANCE_MODE_NONE", 10},
176 {"AAUDIO_PERFORMANCE_MODE_POWER_SAVING", 11},
177 {"AAUDIO_PERFORMANCE_MODE_LOW_LATENCY", 12},
178 };
179 return map;
180 }
181
getAAudioSharingMode()182 const std::unordered_map<std::string, int32_t>& getAAudioSharingMode() {
183 // DO NOT MODIFY VALUES(OK to add new ones).
184 // This may be found in frameworks/av/media/libaaudio/include/aaudio/AAudio.h
185 static std::unordered_map<std::string, int32_t> map {
186 // UNKNOWN is 0
187 {"AAUDIO_SHARING_MODE_EXCLUSIVE", 1 /* AAUDIO_SHARING_MODE_EXCLUSIVE + 1 */},
188 {"AAUDIO_SHARING_MODE_SHARED", 2 /* AAUDIO_SHARING_MODE_SHARED + 1 */},
189 };
190 return map;
191 }
192
193 // Helper: Create the corresponding int32 from string flags split with '|'.
194 template <typename Traits>
int32FromFlags(const std::string & flags)195 int32_t int32FromFlags(const std::string &flags)
196 {
197 const auto result = stringutils::split(flags, "|");
198 int32_t intFlags = 0;
199 for (const auto& flag : result) {
200 typename Traits::Type value;
201 if (!TypeConverter<Traits>::fromString(flag, value)) {
202 break;
203 }
204 intFlags |= value;
205 }
206 return intFlags;
207 }
208
209 template <typename Traits>
stringFromFlags(const std::string & flags,size_t len)210 std::string stringFromFlags(const std::string &flags, size_t len)
211 {
212 const auto result = stringutils::split(flags, "|");
213 std::string sFlags;
214 for (const auto& flag : result) {
215 typename Traits::Type value;
216 if (!TypeConverter<Traits>::fromString(flag, value)) {
217 break;
218 }
219 if (len >= flag.size()) continue;
220 if (!sFlags.empty()) sFlags += "|";
221 sFlags += flag.c_str() + len;
222 }
223 return sFlags;
224 }
225
226 template <typename M>
validateStringFromMap(const std::string & str,const M & map)227 std::string validateStringFromMap(const std::string &str, const M& map)
228 {
229 if (str.empty()) return {};
230
231 const auto result = stringutils::split(str, "|");
232 std::stringstream ss;
233 for (const auto &s : result) {
234 if (map.count(s) > 0) {
235 if (ss.tellp() > 0) ss << "|";
236 ss << s;
237 }
238 }
239 return ss.str();
240 }
241
242 template <typename M>
flagsFromMap(const std::string & str,const M & map)243 typename M::mapped_type flagsFromMap(const std::string &str, const M& map)
244 {
245 if (str.empty()) return {};
246
247 const auto result = stringutils::split(str, "|");
248 typename M::mapped_type value{};
249 for (const auto &s : result) {
250 auto it = map.find(s);
251 if (it == map.end()) continue;
252 value |= it->second;
253 }
254 return value;
255 }
256
257 template <>
lookup(const std::string & contentType)258 int32_t lookup<CONTENT_TYPE>(const std::string &contentType)
259 {
260 AudioContentTraits::Type value;
261 if (!TypeConverter<AudioContentTraits>::fromString(contentType, value)) {
262 value = AUDIO_CONTENT_TYPE_UNKNOWN;
263 }
264 return (int32_t)value;
265 }
266
267 template <>
lookup(const std::string & contentType)268 std::string lookup<CONTENT_TYPE>(const std::string &contentType)
269 {
270 AudioContentTraits::Type value;
271 if (!TypeConverter<AudioContentTraits>::fromString(contentType, value)) {
272 return "";
273 }
274 return contentType.c_str() + sizeof("AUDIO_CONTENT_TYPE");
275 }
276
277 template <>
lookup(const std::string & encoding)278 int32_t lookup<ENCODING>(const std::string &encoding)
279 {
280 FormatTraits::Type value;
281 if (!TypeConverter<FormatTraits>::fromString(encoding, value)) {
282 value = AUDIO_FORMAT_INVALID;
283 }
284 return (int32_t)value;
285 }
286
287 template <>
lookup(const std::string & encoding)288 std::string lookup<ENCODING>(const std::string &encoding)
289 {
290 FormatTraits::Type value;
291 if (!TypeConverter<FormatTraits>::fromString(encoding, value)) {
292 return "";
293 }
294 return encoding.c_str() + sizeof("AUDIO_FORMAT");
295 }
296
297 template <>
lookup(const std::string & inputFlag)298 int32_t lookup<INPUT_FLAG>(const std::string &inputFlag)
299 {
300 return int32FromFlags<InputFlagTraits>(inputFlag);
301 }
302
303 template <>
lookup(const std::string & inputFlag)304 std::string lookup<INPUT_FLAG>(const std::string &inputFlag)
305 {
306 return stringFromFlags<InputFlagTraits>(inputFlag, sizeof("AUDIO_INPUT_FLAG"));
307 }
308
309 template <>
lookup(const std::string & outputFlag)310 int32_t lookup<OUTPUT_FLAG>(const std::string &outputFlag)
311 {
312 return int32FromFlags<OutputFlagTraits>(outputFlag);
313 }
314
315 template <>
lookup(const std::string & outputFlag)316 std::string lookup<OUTPUT_FLAG>(const std::string &outputFlag)
317 {
318 return stringFromFlags<OutputFlagTraits>(outputFlag, sizeof("AUDIO_OUTPUT_FLAG"));
319 }
320
321 template <>
lookup(const std::string & sourceType)322 int32_t lookup<SOURCE_TYPE>(const std::string &sourceType)
323 {
324 SourceTraits::Type value;
325 if (!TypeConverter<SourceTraits>::fromString(sourceType, value)) {
326 value = AUDIO_SOURCE_DEFAULT;
327 }
328 return (int32_t)value;
329 }
330
331 template <>
lookup(const std::string & sourceType)332 std::string lookup<SOURCE_TYPE>(const std::string &sourceType)
333 {
334 SourceTraits::Type value;
335 if (!TypeConverter<SourceTraits>::fromString(sourceType, value)) {
336 return "";
337 }
338 return sourceType.c_str() + sizeof("AUDIO_SOURCE");
339 }
340
341 template <>
lookup(const std::string & streamType)342 int32_t lookup<STREAM_TYPE>(const std::string &streamType)
343 {
344 StreamTraits::Type value;
345 if (!TypeConverter<StreamTraits>::fromString(streamType, value)) {
346 value = AUDIO_STREAM_DEFAULT;
347 }
348 return (int32_t)value;
349 }
350
351 template <>
lookup(const std::string & streamType)352 std::string lookup<STREAM_TYPE>(const std::string &streamType)
353 {
354 StreamTraits::Type value;
355 if (!TypeConverter<StreamTraits>::fromString(streamType, value)) {
356 return "";
357 }
358 return streamType.c_str() + sizeof("AUDIO_STREAM");
359 }
360
361 template <>
lookup(const std::string & usage)362 int32_t lookup<USAGE>(const std::string &usage)
363 {
364 UsageTraits::Type value;
365 if (!TypeConverter<UsageTraits>::fromString(usage, value)) {
366 value = AUDIO_USAGE_UNKNOWN;
367 }
368 return (int32_t)value;
369 }
370
371 template <>
lookup(const std::string & usage)372 std::string lookup<USAGE>(const std::string &usage)
373 {
374 UsageTraits::Type value;
375 if (!TypeConverter<UsageTraits>::fromString(usage, value)) {
376 return "";
377 }
378 return usage.c_str() + sizeof("AUDIO_USAGE");
379 }
380
381 template <>
lookup(const std::string & inputDevice)382 int64_t lookup<INPUT_DEVICE>(const std::string &inputDevice)
383 {
384 // NOT USED FOR R.
385 // Returns a set of bits, each one representing a device in inputDevice.
386 // This is a 64 bit integer, not the same as audio_device_t.
387 return flagsFromMap(inputDevice, getAudioDeviceInMap());
388 }
389
390 template <>
lookup(const std::string & inputDevice)391 std::string lookup<INPUT_DEVICE>(const std::string &inputDevice)
392 {
393 return stringFromFlags<InputDeviceTraits>(inputDevice, sizeof("AUDIO_DEVICE_IN"));
394 }
395
396 template <>
lookup(const std::string & outputDevice)397 int64_t lookup<OUTPUT_DEVICE>(const std::string &outputDevice)
398 {
399 // NOT USED FOR R.
400 // Returns a set of bits, each one representing a device in outputDevice.
401 // This is a 64 bit integer, not the same as audio_device_t.
402 return flagsFromMap(outputDevice, getAudioDeviceOutMap());
403 }
404
405 template <>
lookup(const std::string & outputDevice)406 std::string lookup<OUTPUT_DEVICE>(const std::string &outputDevice)
407 {
408 return stringFromFlags<OutputDeviceTraits>(outputDevice, sizeof("AUDIO_DEVICE_OUT"));
409 }
410
411 template <>
lookup(const std::string & callerName)412 int32_t lookup<CALLER_NAME>(const std::string &callerName)
413 {
414 auto& map = getAudioCallerNameMap();
415 auto it = map.find(callerName);
416 if (it == map.end()) {
417 return 0; // return unknown
418 }
419 return it->second;
420 }
421
422 template <>
lookup(const std::string & callerName)423 std::string lookup<CALLER_NAME>(const std::string &callerName)
424 {
425 auto& map = getAudioCallerNameMap();
426 auto it = map.find(callerName);
427 if (it == map.end()) {
428 return "";
429 }
430 return callerName;
431 }
432
433 template <>
lookup(const std::string & threadType)434 int32_t lookup<THREAD_TYPE>(const std::string &threadType)
435 {
436 auto& map = getAudioThreadTypeMap();
437 auto it = map.find(threadType);
438 if (it == map.end()) {
439 return -1; // note this as an illegal thread value as we don't have unknown here.
440 }
441 return it->second;
442 }
443
444 template <>
lookup(const std::string & threadType)445 std::string lookup<THREAD_TYPE>(const std::string &threadType)
446 {
447 auto& map = getAudioThreadTypeMap();
448 auto it = map.find(threadType);
449 if (it == map.end()) {
450 return "";
451 }
452 return threadType;
453 }
454
isInputThreadType(const std::string & threadType)455 bool isInputThreadType(const std::string &threadType)
456 {
457 return threadType == "RECORD" || threadType == "MMAP_CAPTURE";
458 }
459
460 template <>
lookup(const std::string & traits)461 std::string lookup<TRACK_TRAITS>(const std::string &traits)
462 {
463 return validateStringFromMap(traits, getAudioTrackTraitsMap());
464 }
465
466 template <>
lookup(const std::string & traits)467 int32_t lookup<TRACK_TRAITS>(const std::string &traits)
468 {
469 return flagsFromMap(traits, getAudioTrackTraitsMap());
470 }
471
472 template <>
lookup(const std::string & direction)473 std::string lookup<AAUDIO_DIRECTION>(const std::string &direction)
474 {
475 auto& map = getAAudioDirection();
476 auto it = map.find(direction);
477 if (it == map.end()) {
478 return "";
479 }
480 return direction;
481 }
482
483 template <>
lookup(const std::string & direction)484 int32_t lookup<AAUDIO_DIRECTION>(const std::string &direction)
485 {
486 auto& map = getAAudioDirection();
487 auto it = map.find(direction);
488 if (it == map.end()) {
489 return 0; // return unknown
490 }
491 return it->second;
492 }
493
494 template <>
lookup(const std::string & performanceMode)495 std::string lookup<AAUDIO_PERFORMANCE_MODE>(const std::string &performanceMode)
496 {
497 auto& map = getAAudioPerformanceMode();
498 auto it = map.find(performanceMode);
499 if (it == map.end()) {
500 return "";
501 }
502 return performanceMode;
503 }
504
505 template <>
lookup(const std::string & performanceMode)506 int32_t lookup<AAUDIO_PERFORMANCE_MODE>(const std::string &performanceMode)
507 {
508 auto& map = getAAudioPerformanceMode();
509 auto it = map.find(performanceMode);
510 if (it == map.end()) {
511 return 0; // return unknown
512 }
513 return it->second;
514 }
515
516 template <>
lookup(const std::string & sharingMode)517 std::string lookup<AAUDIO_SHARING_MODE>(const std::string &sharingMode)
518 {
519 auto& map = getAAudioSharingMode();
520 auto it = map.find(sharingMode);
521 if (it == map.end()) {
522 return "";
523 }
524 return sharingMode;
525 }
526
527 template <>
lookup(const std::string & sharingMode)528 int32_t lookup<AAUDIO_SHARING_MODE>(const std::string &sharingMode)
529 {
530 auto& map = getAAudioSharingMode();
531 auto it = map.find(sharingMode);
532 if (it == map.end()) {
533 return 0; // return unknown
534 }
535 return it->second;
536 }
537
538 } // namespace android::mediametrics::types
539