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