1 /*
2 * Copyright (C) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "gavdp/a2dp_def.h"
17 #include "include/a2dp_codec_config.h"
18 #include "include/a2dp_codec_errors.h"
19 #include "include/a2dp_codec_factory.h"
20 #include "include/a2dp_codec_wrapper.h"
21 #include "log.h"
22
23 namespace OHOS {
24 namespace bluetooth {
OrderCodecPriority(const A2dpCodecConfig * element1,const A2dpCodecConfig * element2)25 static bool OrderCodecPriority(const A2dpCodecConfig *element1, const A2dpCodecConfig *element2)
26 {
27 if (element1->GetCodecPriority() > element2->GetCodecPriority()) {
28 return true;
29 }
30
31 if (element1->GetCodecPriority() < element2->GetCodecPriority()) {
32 return false;
33 }
34
35 return (element1->GetCodecIndex() > element2->GetCodecIndex());
36 }
37
A2dpCodecFactory(const std::map<A2dpCodecIndex,A2dpCodecPriority> & codecPriorities)38 A2dpCodecFactory::A2dpCodecFactory(const std::map<A2dpCodecIndex, A2dpCodecPriority> &codecPriorities)
39 : codecPriorities_(codecPriorities), currentCodecConfig_(nullptr), lastCodecConfig_(nullptr)
40 {
41 LOG_INFO("[CodecFactory] %{public}s\n", __func__);
42 Initialize();
43 }
44
~A2dpCodecFactory()45 A2dpCodecFactory::~A2dpCodecFactory()
46 {
47 LOG_INFO("[CodecFactory] %{public}s\n", __func__);
48 for (auto iter = indexedCodecs_.begin(); iter != indexedCodecs_.end(); iter++) {
49 delete iter->second;
50 }
51 }
52
Initialize()53 bool A2dpCodecFactory::Initialize()
54 {
55 LOG_INFO("[CodecFactory] %{public}s\n", __func__);
56 for (int i = A2DP_CODEC_INDEX_MIN; i < A2DP_CODEC_INDEX_MAX; i++) {
57 auto codecIndex = static_cast<A2dpCodecIndex>(i);
58
59 // Select the codec priority if explicitly configured
60 A2dpCodecPriority codecPriority = A2DP_CODEC_PRIORITY_DEFAULT;
61
62 auto priority = codecPriorities_.find(codecIndex);
63 if (priority != codecPriorities_.end()) {
64 codecPriority = priority->second;
65 }
66 LOG_INFO("[CodecFactory] %{public}s codecIndex(%u) codecPriority(%u)\n", __func__, codecIndex, codecPriority);
67 A2dpCodecConfig *codecConfig = A2dpCodecConfig::CreateCodec(codecIndex, codecPriority);
68 if (codecConfig == nullptr) {
69 continue;
70 }
71
72 indexedCodecs_.insert(std::make_pair(codecIndex, codecConfig));
73
74 if (codecIndex < A2DP_SOURCE_CODEC_INDEX_MAX) {
75 indexedSourceCodecs_.push_back(codecConfig);
76 indexedSourceCodecs_.sort(OrderCodecPriority);
77 } else {
78 indexedSinkCodecs_.push_back(codecConfig);
79 indexedSinkCodecs_.sort(OrderCodecPriority);
80 }
81 }
82
83 if (indexedSourceCodecs_.empty()) {
84 LOG_ERROR("%{public}s: no Source codecs were initialized", __func__);
85 }
86
87 if (indexedSinkCodecs_.empty()) {
88 LOG_ERROR("%{public}s: no Sink codecs were initialized", __func__);
89 }
90
91 return (!indexedSourceCodecs_.empty() && !indexedSinkCodecs_.empty());
92 }
93
GetCodecConfig() const94 A2dpCodecConfig *A2dpCodecFactory::GetCodecConfig() const
95 {
96 return currentCodecConfig_;
97 }
98
FindSourceCodec(const uint8_t * codeInfo) const99 A2dpCodecConfig *A2dpCodecFactory::FindSourceCodec(const uint8_t *codeInfo) const
100 {
101 LOG_INFO("[CodecFactory] %{public}s\n", __func__);
102 A2dpCodecIndex codecIndex = GetSourceCodecIndex(codeInfo);
103 if (codecIndex == A2DP_SOURCE_CODEC_INDEX_MAX) {
104 return nullptr;
105 }
106
107 auto iter = indexedCodecs_.find(static_cast<A2dpCodecIndex>(codecIndex));
108 if (iter == indexedCodecs_.end()) {
109 LOG_WARN("[CodecFactory] %{public}s can't find codecIndex(%u)\n", __func__, codecIndex);
110 return nullptr;
111 }
112
113 return iter->second;
114 }
115
FindSinkCodec(const uint8_t * codeInfo) const116 A2dpCodecConfig *A2dpCodecFactory::FindSinkCodec(const uint8_t *codeInfo) const
117 {
118 LOG_INFO("[CodecFactory] %{public}s\n", __func__);
119 A2dpCodecIndex codecIndex = GetSinkCodecIndex(codeInfo);
120 if (codecIndex == A2DP_SINK_CODEC_INDEX_MAX) {
121 return nullptr;
122 }
123
124 auto iter = indexedCodecs_.find(static_cast<A2dpCodecIndex>(codecIndex));
125 if (iter == indexedCodecs_.end()) {
126 return nullptr;
127 }
128
129 return iter->second;
130 }
131
GetIndexedSourceCodecs() const132 std::list<A2dpCodecConfig *> A2dpCodecFactory::GetIndexedSourceCodecs() const
133 {
134 LOG_INFO("[CodecFactory] %{public}s\n", __func__);
135 return indexedSourceCodecs_;
136 }
137
GetIndexedSinkCodecs() const138 std::list<A2dpCodecConfig *> A2dpCodecFactory::GetIndexedSinkCodecs() const
139 {
140 LOG_INFO("[CodecFactory] %{public}s\n", __func__);
141 return indexedSinkCodecs_;
142 }
143
SetCodecConfig(const uint8_t * peerCodecInfo,uint8_t * resultCodecInfo)144 bool A2dpCodecFactory::SetCodecConfig(const uint8_t *peerCodecInfo, uint8_t *resultCodecInfo)
145 {
146 LOG_INFO("[CodecFactory] %{public}s\n", __func__);
147 A2dpCodecConfig *a2dpCodecConfig = FindSourceCodec(peerCodecInfo);
148 if (a2dpCodecConfig == nullptr) {
149 return false;
150 }
151 if (!a2dpCodecConfig->SetCodecConfig(peerCodecInfo, resultCodecInfo)) {
152 return false;
153 }
154
155 currentCodecConfig_ = a2dpCodecConfig;
156 return true;
157 }
158
SetSinkCodecConfig(const uint8_t * peerCodecInfo,uint8_t * resultCodecInfo)159 bool A2dpCodecFactory::SetSinkCodecConfig(const uint8_t *peerCodecInfo, uint8_t *resultCodecInfo)
160 {
161 bool ret = true;
162 LOG_INFO("[CodecFactory] %{public}s isCapability\n", __func__);
163 A2dpCodecConfig *a2dpCodecConfig = FindSinkCodec(peerCodecInfo);
164 if (a2dpCodecConfig == nullptr) {
165 return false;
166 }
167
168 if (!a2dpCodecConfig->SetCodecConfig(peerCodecInfo, resultCodecInfo)) {
169 ret = false;
170 }
171
172 currentCodecConfig_ = a2dpCodecConfig;
173 return ret;
174 }
175
ResetCodecUserConfig(void)176 bool A2dpCodecFactory::ResetCodecUserConfig(void)
177 {
178 currentCodecConfig_ = lastCodecConfig_;
179 return false;
180 }
181
UpdateCodecPriority(const A2dpCodecCapability & userConfig,A2dpCodecConfig * a2dpCodecConfig,bool * restartConfig)182 void A2dpCodecFactory::UpdateCodecPriority(
183 const A2dpCodecCapability &userConfig, A2dpCodecConfig *a2dpCodecConfig, bool *restartConfig)
184 {
185 A2dpCodecPriority lastPriority = a2dpCodecConfig->GetCodecPriority();
186 A2dpCodecPriority newPriority = userConfig.codecPriority_;
187 LOG_INFO("[CodecFactory] %{public}s newpriority(%u) lastPriority(%u)\n", __func__, newPriority, lastPriority);
188 a2dpCodecConfig->SetCodecPriority(newPriority);
189 newPriority = a2dpCodecConfig->GetCodecPriority();
190 LOG_INFO("[CodecFactory] %{public}s newpriority(%u) \n", __func__, newPriority);
191 do {
192 if (lastCodecConfig_ == nullptr) { // have no previous codec, so update the current codec
193 LOG_INFO("[CodecFactory] %{public}s update current codec config\n", __func__);
194 currentCodecConfig_ = a2dpCodecConfig;
195 *restartConfig = true;
196 break;
197 }
198
199 if (lastCodecConfig_ == a2dpCodecConfig) {
200 LOG_INFO("[CodecFactory] %{public}s codec not changed\n", __func__);
201 if (newPriority == lastPriority) {
202 LOG_INFO("[CodecFactory] %{public}s the priority not changed\n", __func__);
203 break;
204 }
205 if (newPriority < lastPriority) {
206 LOG_INFO("[CodecFactory] %{public}s the current priority is lower than before, "
207 "need select new codec\n",
208 __func__);
209 *restartConfig = true;
210 break;
211 }
212 }
213
214 if (newPriority <= lastPriority) {
215 LOG_INFO("[CodecFactory] %{public}s the new priority is lower than before, but not the current codec",
216 __func__);
217 break;
218 }
219 if (newPriority >= lastCodecConfig_->GetCodecPriority()) {
220 LOG_INFO("[CodecFactory] %{public}s the new priority is higher than before, update current codec",
221 __func__);
222 currentCodecConfig_ = a2dpCodecConfig;
223 lastCodecConfig_->SetDefaultCodecPriority();
224 *restartConfig = true;
225 }
226 } while (false);
227 LOG_INFO("[CodecFactory] %{public}s [index:%u\n", __func__, currentCodecConfig_->GetCodecIndex());
228 if (currentCodecConfig_->GetCodecIndex() < A2DP_SOURCE_CODEC_INDEX_MAX) {
229 indexedSourceCodecs_.sort(OrderCodecPriority);
230 } else {
231 indexedSinkCodecs_.sort(OrderCodecPriority);
232 }
233 }
234
SetCodecUserConfig(const A2dpCodecCapability & userConfig,const uint8_t * peerSinkCapabilities,uint8_t * resultCodecInfo,bool * restartConfig)235 bool A2dpCodecFactory::SetCodecUserConfig(const A2dpCodecCapability &userConfig, const uint8_t *peerSinkCapabilities,
236 uint8_t *resultCodecInfo, bool *restartConfig)
237 {
238 LOG_INFO("[CodecFactory] %{public}s\n", __func__);
239 A2dpCodecConfig *a2dpCodecConfig = nullptr;
240 lastCodecConfig_ = currentCodecConfig_;
241
242 if (userConfig.codecIndex_ < A2DP_CODEC_INDEX_MAX) {
243 auto iter = indexedCodecs_.find(userConfig.codecIndex_);
244 if (iter == indexedCodecs_.end()) {
245 return ResetCodecUserConfig();
246 }
247 a2dpCodecConfig = iter->second;
248 } else {
249 a2dpCodecConfig = currentCodecConfig_;
250 }
251
252 if (a2dpCodecConfig == nullptr) {
253 LOG_INFO("[CodecFactory] %{public}s a2dpCodecConfig is null\n", __func__);
254 return ResetCodecUserConfig();
255 }
256 A2dpCodecCapability codecAudioConfig = a2dpCodecConfig->GetAudioCodecConfig();
257 if (!a2dpCodecConfig->SetCodecUserConfig(
258 userConfig, codecAudioConfig, peerSinkCapabilities, resultCodecInfo, restartConfig)) {
259 LOG_INFO("[CodecFactory] %{public}s\n", __func__);
260 return ResetCodecUserConfig();
261 }
262
263 UpdateCodecPriority(userConfig, a2dpCodecConfig, restartConfig);
264 return true;
265 }
266
SetCodecAudioConfig(const A2dpCodecCapability & audioConfig,const uint8_t * peerSinkCapabilities,uint8_t * resultCodecInfo,bool * restartConfig)267 bool A2dpCodecFactory::SetCodecAudioConfig(const A2dpCodecCapability &audioConfig, const uint8_t *peerSinkCapabilities,
268 uint8_t *resultCodecInfo, bool *restartConfig)
269 {
270 LOG_INFO("[CodecFactory] %{public}s\n", __func__);
271 A2dpCodecConfig *a2dpCodecConfig = currentCodecConfig_;
272 *restartConfig = false;
273 if (a2dpCodecConfig == nullptr) {
274 return false;
275 }
276 A2dpCodecCapability codecUserConfig = a2dpCodecConfig->GetUserConfig();
277 if (!a2dpCodecConfig->SetCodecUserConfig(
278 codecUserConfig, audioConfig, peerSinkCapabilities, resultCodecInfo, restartConfig)) {
279 LOG_INFO("[CodecFactory] %{public}s\n", __func__);
280 return ResetCodecUserConfig();
281 }
282 return true;
283 }
284
SetPeerSinkCodecCapabilities(const uint8_t * capabilities)285 bool A2dpCodecFactory::SetPeerSinkCodecCapabilities(const uint8_t *capabilities)
286 {
287 LOG_INFO("[CodecFactory] %{public}s\n", __func__);
288 bool isPeerSinkCodecValid = IsPeerSinkCodecValid(capabilities);
289 if (!isPeerSinkCodecValid) {
290 return false;
291 }
292 A2dpCodecConfig *a2dpCodecConfig = FindSinkCodec(capabilities);
293 if (a2dpCodecConfig == nullptr) {
294 return false;
295 }
296
297 return a2dpCodecConfig->SetPeerCodecCapabilities(capabilities);
298 }
299
SetPeerSourceCodecCapabilities(const uint8_t * capabilities)300 bool A2dpCodecFactory::SetPeerSourceCodecCapabilities(const uint8_t *capabilities)
301 {
302 LOG_INFO("[CodecFactory] %{public}s\n", __func__);
303 bool isCodecValid = IsPeerSourceCodecValid(capabilities);
304 if (!isCodecValid) {
305 return false;
306 }
307
308 A2dpCodecConfig *a2dpCodecConfig = FindSourceCodec(capabilities);
309 if (a2dpCodecConfig == nullptr) {
310 return false;
311 }
312
313 return a2dpCodecConfig->SetPeerCodecCapabilities(capabilities);
314 }
315 } // namespace bluetooth
316 } // namespace OHOS