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