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