• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2022 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 "le_audio_utils.h"
18 
19 #include "bta/le_audio/content_control_id_keeper.h"
20 #include "gd/common/strings.h"
21 #include "le_audio_types.h"
22 #include "osi/include/log.h"
23 
24 using bluetooth::common::ToString;
25 using le_audio::types::AudioContexts;
26 using le_audio::types::LeAudioContextType;
27 
28 namespace le_audio {
29 namespace utils {
30 
31 /* The returned LeAudioContextType should have its entry in the
32  * AudioSetConfigurationProvider's ContextTypeToScenario mapping table.
33  * Otherwise the AudioSetConfigurationProvider will fall back
34  * to default scenario.
35  */
AudioContentToLeAudioContext(audio_content_type_t content_type,audio_usage_t usage)36 LeAudioContextType AudioContentToLeAudioContext(
37     audio_content_type_t content_type, audio_usage_t usage) {
38   /* Check audio attribute usage of stream */
39   switch (usage) {
40     case AUDIO_USAGE_MEDIA:
41       return LeAudioContextType::MEDIA;
42     case AUDIO_USAGE_ASSISTANT:
43       return LeAudioContextType::VOICEASSISTANTS;
44     case AUDIO_USAGE_VOICE_COMMUNICATION:
45     case AUDIO_USAGE_CALL_ASSISTANT:
46       return LeAudioContextType::CONVERSATIONAL;
47     case AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING:
48       if (content_type == AUDIO_CONTENT_TYPE_SPEECH)
49         return LeAudioContextType::CONVERSATIONAL;
50       else
51         return LeAudioContextType::MEDIA;
52     case AUDIO_USAGE_GAME:
53       return LeAudioContextType::GAME;
54     case AUDIO_USAGE_NOTIFICATION:
55       return LeAudioContextType::NOTIFICATIONS;
56     case AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE:
57       return LeAudioContextType::RINGTONE;
58     case AUDIO_USAGE_ALARM:
59       return LeAudioContextType::ALERTS;
60     case AUDIO_USAGE_EMERGENCY:
61       return LeAudioContextType::EMERGENCYALARM;
62     case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
63       return LeAudioContextType::INSTRUCTIONAL;
64     case AUDIO_USAGE_ASSISTANCE_SONIFICATION:
65       return LeAudioContextType::SOUNDEFFECTS;
66     default:
67       break;
68   }
69 
70   return LeAudioContextType::MEDIA;
71 }
72 
usageToString(audio_usage_t usage)73 static std::string usageToString(audio_usage_t usage) {
74   switch (usage) {
75     case AUDIO_USAGE_UNKNOWN:
76       return "USAGE_UNKNOWN";
77     case AUDIO_USAGE_MEDIA:
78       return "USAGE_MEDIA";
79     case AUDIO_USAGE_VOICE_COMMUNICATION:
80       return "USAGE_VOICE_COMMUNICATION";
81     case AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING:
82       return "USAGE_VOICE_COMMUNICATION_SIGNALLING";
83     case AUDIO_USAGE_ALARM:
84       return "USAGE_ALARM";
85     case AUDIO_USAGE_NOTIFICATION:
86       return "USAGE_NOTIFICATION";
87     case AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE:
88       return "USAGE_NOTIFICATION_TELEPHONY_RINGTONE";
89     case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
90       return "USAGE_NOTIFICATION_COMMUNICATION_REQUEST";
91     case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
92       return "USAGE_NOTIFICATION_COMMUNICATION_INSTANT";
93     case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
94       return "USAGE_NOTIFICATION_COMMUNICATION_DELAYED";
95     case AUDIO_USAGE_NOTIFICATION_EVENT:
96       return "USAGE_NOTIFICATION_EVENT";
97     case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY:
98       return "USAGE_ASSISTANCE_ACCESSIBILITY";
99     case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
100       return "USAGE_ASSISTANCE_NAVIGATION_GUIDANCE";
101     case AUDIO_USAGE_ASSISTANCE_SONIFICATION:
102       return "USAGE_ASSISTANCE_SONIFICATION";
103     case AUDIO_USAGE_GAME:
104       return "USAGE_GAME";
105     case AUDIO_USAGE_ASSISTANT:
106       return "USAGE_ASSISTANT";
107     case AUDIO_USAGE_CALL_ASSISTANT:
108       return "USAGE_CALL_ASSISTANT";
109     case AUDIO_USAGE_EMERGENCY:
110       return "USAGE_EMERGENCY";
111     case AUDIO_USAGE_SAFETY:
112       return "USAGE_SAFETY";
113     case AUDIO_USAGE_VEHICLE_STATUS:
114       return "USAGE_VEHICLE_STATUS";
115     case AUDIO_USAGE_ANNOUNCEMENT:
116       return "USAGE_ANNOUNCEMENT";
117     default:
118       return "unknown usage ";
119   }
120 }
121 
contentTypeToString(audio_content_type_t content_type)122 static std::string contentTypeToString(audio_content_type_t content_type) {
123   switch (content_type) {
124     case AUDIO_CONTENT_TYPE_UNKNOWN:
125       return "CONTENT_TYPE_UNKNOWN";
126     case AUDIO_CONTENT_TYPE_SPEECH:
127       return "CONTENT_TYPE_SPEECH";
128     case AUDIO_CONTENT_TYPE_MUSIC:
129       return "CONTENT_TYPE_MUSIC";
130     case AUDIO_CONTENT_TYPE_MOVIE:
131       return "CONTENT_TYPE_MOVIE";
132     case AUDIO_CONTENT_TYPE_SONIFICATION:
133       return "CONTENT_TYPE_SONIFICATION";
134     default:
135       return "unknown content type ";
136   }
137 }
138 
audioSourceToStr(audio_source_t source)139 static const char* audioSourceToStr(audio_source_t source) {
140   const char* strArr[] = {
141       "AUDIO_SOURCE_DEFAULT",           "AUDIO_SOURCE_MIC",
142       "AUDIO_SOURCE_VOICE_UPLINK",      "AUDIO_SOURCE_VOICE_DOWNLINK",
143       "AUDIO_SOURCE_VOICE_CALL",        "AUDIO_SOURCE_CAMCORDER",
144       "AUDIO_SOURCE_VOICE_RECOGNITION", "AUDIO_SOURCE_VOICE_COMMUNICATION",
145       "AUDIO_SOURCE_REMOTE_SUBMIX",     "AUDIO_SOURCE_UNPROCESSED",
146       "AUDIO_SOURCE_VOICE_PERFORMANCE"};
147 
148   if (static_cast<uint32_t>(source) < (sizeof(strArr) / sizeof(strArr[0])))
149     return strArr[source];
150   return "UNKNOWN";
151 }
152 
GetAllowedAudioContextsFromSourceMetadata(const std::vector<struct playback_track_metadata> & source_metadata,AudioContexts allowed_contexts)153 AudioContexts GetAllowedAudioContextsFromSourceMetadata(
154     const std::vector<struct playback_track_metadata>& source_metadata,
155     AudioContexts allowed_contexts) {
156   AudioContexts track_contexts;
157   for (auto& track : source_metadata) {
158     if (track.content_type == 0 && track.usage == 0) continue;
159 
160     LOG_INFO("%s: usage=%s(%d), content_type=%s(%d), gain=%f", __func__,
161              usageToString(track.usage).c_str(), track.usage,
162              contentTypeToString(track.content_type).c_str(),
163              track.content_type, track.gain);
164 
165     track_contexts.set(
166         AudioContentToLeAudioContext(track.content_type, track.usage));
167   }
168   track_contexts &= allowed_contexts;
169   LOG_INFO("%s: allowed context= %s", __func__,
170            track_contexts.to_string().c_str());
171 
172   return track_contexts;
173 }
174 
GetAllowedAudioContextsFromSinkMetadata(const std::vector<struct record_track_metadata> & sink_metadata,AudioContexts allowed_contexts)175 AudioContexts GetAllowedAudioContextsFromSinkMetadata(
176     const std::vector<struct record_track_metadata>& sink_metadata,
177     AudioContexts allowed_contexts) {
178   AudioContexts all_track_contexts;
179 
180   for (auto& track : sink_metadata) {
181     if (track.source == AUDIO_SOURCE_INVALID) continue;
182     LeAudioContextType track_context;
183 
184     LOG_DEBUG(
185         "source=%s(0x%02x), gain=%f, destination device=0x%08x, destination "
186         "device address=%.32s, allowed_contexts=%s",
187         audioSourceToStr(track.source), track.source, track.gain,
188         track.dest_device, track.dest_device_address,
189         bluetooth::common::ToString(allowed_contexts).c_str());
190 
191     if ((track.source == AUDIO_SOURCE_MIC) &&
192         (allowed_contexts.test(LeAudioContextType::LIVE))) {
193       track_context = LeAudioContextType::LIVE;
194 
195     } else if ((track.source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
196                (allowed_contexts.test(LeAudioContextType::CONVERSATIONAL))) {
197       track_context = LeAudioContextType::CONVERSATIONAL;
198 
199     } else if (allowed_contexts.test(LeAudioContextType::VOICEASSISTANTS)) {
200       /* Fallback to voice assistant
201        * This will handle also a case when the device is
202        * AUDIO_SOURCE_VOICE_RECOGNITION
203        */
204       track_context = LeAudioContextType::VOICEASSISTANTS;
205       LOG_WARN(
206           "Could not match the recording track type to group available "
207           "context. Using context %s.",
208           ToString(track_context).c_str());
209     }
210 
211     all_track_contexts.set(track_context);
212   }
213 
214   if (all_track_contexts.none()) {
215     all_track_contexts = AudioContexts(
216         static_cast<std::underlying_type<LeAudioContextType>::type>(
217             LeAudioContextType::UNSPECIFIED));
218     LOG_DEBUG(
219         "Unable to find supported audio source context for the remote audio "
220         "sink device. This may result in voice back channel malfunction.");
221   }
222 
223   LOG_DEBUG("Allowed contexts from sink metadata: %s (0x%08hx)",
224             bluetooth::common::ToString(all_track_contexts).c_str(),
225             all_track_contexts.value());
226   return all_track_contexts;
227 }
228 
GetAllCcids(const AudioContexts & contexts)229 std::vector<uint8_t> GetAllCcids(const AudioContexts& contexts) {
230   auto ccid_keeper = ContentControlIdKeeper::GetInstance();
231   std::vector<uint8_t> ccid_vec;
232 
233   for (LeAudioContextType context : types::kLeAudioContextAllTypesArray) {
234     if (!contexts.test(context)) continue;
235     using T = std::underlying_type<LeAudioContextType>::type;
236     auto ccid = ccid_keeper->GetCcid(static_cast<T>(context));
237     if (ccid != -1) {
238       ccid_vec.push_back(static_cast<uint8_t>(ccid));
239     }
240   }
241 
242   return ccid_vec;
243 }
244 
245 }  // namespace utils
246 }  // namespace le_audio
247