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