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 "include/a2dp_aac_param_ctrl.h"
17 #include "include/a2dp_codec_config.h"
18 #include "include/a2dp_sbc_param_ctrl.h"
19 #include "log.h"
20 #include "memory.h"
21 #include "securec.h"
22 
23 namespace OHOS {
24 namespace bluetooth {
25 const int PRIORITY_SBC_BASIC = 1000;
26 const int PRIORITY_NUM_BASIC_VALUE = 1;
InitCodecConfig(A2dpCodecCapability & codecConfig,const A2dpCodecIndex codecIndex,const A2dpCodecPriority codecPriority)27 static void InitCodecConfig(
28     A2dpCodecCapability &codecConfig, const A2dpCodecIndex codecIndex, const A2dpCodecPriority codecPriority)
29 {
30     (void)memset_s(&codecConfig, sizeof(A2dpCodecCapability), 0, sizeof(A2dpCodecCapability));
31     codecConfig.codecIndex_ = codecIndex;
32     codecConfig.codecPriority_ = codecPriority;
33 }
34 
A2dpCodecConfig(A2dpCodecIndex index,A2dpCodecPriority priority)35 A2dpCodecConfig::A2dpCodecConfig(A2dpCodecIndex index, A2dpCodecPriority priority)
36     : codecIndex_(index), defaultPriority_(priority)
37 {
38     LOG_INFO("[CodecConfig] %{public}s\n", __func__);
39     SetCodecPriority(priority);
40     InitCodecConfig(codecConfig_, codecIndex_, GetCodecPriority());
41     InitCodecConfig(userCodecConfig_, codecIndex_, GetCodecPriority());
42     InitCodecConfig(savedCodecUserConfig_, codecIndex_, GetCodecPriority());
43     InitCodecConfig(audioCodecConfig_, codecIndex_, GetCodecPriority());
44     InitCodecConfig(codecSelectableCap_, codecIndex_, GetCodecPriority());
45     InitCodecConfig(codecLocalCap_, codecIndex_, GetCodecPriority());
46     InitCodecConfig(codecCap_, codecIndex_, GetCodecPriority());
47     InitCodecConfig(savedCodecCapability_, codecIndex_, GetCodecPriority());
48     InitCodecConfig(savedCodecConfig_, codecIndex_, GetCodecPriority());
49     InitCodecConfig(savedCodecSelectableCapability, codecIndex_, GetCodecPriority());
50     (void)memset_s(otaCodecConfig_, A2DP_CODEC_SIZE, 0, sizeof(otaCodecConfig_));
51     (void)memset_s(otaCodecPeerCapability_, A2DP_CODEC_SIZE, 0, sizeof(otaCodecPeerCapability_));
52     (void)memset_s(savedOtaCodecPeerCapability, A2DP_CODEC_SIZE, 0, sizeof(savedOtaCodecPeerCapability));
53     (void)memset_s(otaCodecPeerConfig_, A2DP_CODEC_SIZE, 0, sizeof(otaCodecPeerConfig_));
54     (void)memset_s(savedOtaCodecConfig_, A2DP_CODEC_SIZE, 0, sizeof(savedOtaCodecConfig_));
55 }
56 
GetCodecIndex() const57 A2dpCodecIndex A2dpCodecConfig::GetCodecIndex() const
58 {
59     LOG_INFO("[CodecConfig] %{public}s codecIndex:0x%x\n", __func__, codecCap_.codecIndex_);
60     return codecIndex_;
61 }
62 
GetCodecPriority() const63 A2dpCodecPriority A2dpCodecConfig::GetCodecPriority() const
64 {
65     LOG_INFO("[CodecConfig] %{public}s codecPriority_:0x%x\n", __func__, codecPriority_);
66     return codecPriority_;
67 }
68 
Name() const69 const std::string &A2dpCodecConfig::Name() const
70 {
71     LOG_INFO("[CodecConfig] %{public}s\n", __func__);
72 
73     return name_;
74 }
75 
GetCodecLocalCapability() const76 A2dpCodecCapability A2dpCodecConfig::GetCodecLocalCapability() const
77 {
78     LOG_INFO("[CodecConfig] %{public}s", __func__);
79     return codecLocalCap_;
80 }
81 
GetAudioBitsPerSample() const82 uint32_t A2dpCodecConfig::GetAudioBitsPerSample() const
83 {
84     LOG_INFO("[CodecConfig] %{public}s\n", __func__);
85     switch (codecConfig_.bitsPerSample) {
86         case A2DP_SAMPLE_BITS_16:
87             return A2DP_SAMPLE_BITS_16;
88         case A2DP_SAMPLE_BITS_24:
89             return A2DP_SAMPLE_BITS_24;
90         case A2DP_SAMPLE_BITS_32:
91             return A2DP_SAMPLE_BITS_32;
92         default:
93             LOG_INFO("Use default bitsPerSample: 16");
94             return A2DP_SAMPLE_BITS_16;
95     }
96 }
97 
GetCodecConfig() const98 A2dpCodecCapability A2dpCodecConfig::GetCodecConfig() const
99 {
100     LOG_INFO("[CodecConfig] %{public}s", __func__);
101     return codecConfig_;
102 }
103 
GetUserConfig() const104 A2dpCodecCapability A2dpCodecConfig::GetUserConfig() const
105 {
106     LOG_INFO("[CodecConfig] %{public}s", __func__);
107     return userCodecConfig_;
108 }
109 
GetAudioCodecConfig() const110 A2dpCodecCapability A2dpCodecConfig::GetAudioCodecConfig() const
111 {
112     LOG_INFO("[CodecConfig] %{public}s", __func__);
113     return audioCodecConfig_;
114 }
115 
CopyOutOtaCodecConfig(uint8_t * codecInfo) const116 bool A2dpCodecConfig::CopyOutOtaCodecConfig(uint8_t *codecInfo) const
117 {
118     LOG_INFO("[CodecConfig] %{public}s", __func__);
119     (void)memcpy_s(codecInfo, A2DP_CODEC_SIZE, otaCodecConfig_, A2DP_CODEC_SIZE);
120     return true;
121 }
122 
SetCodecPriority(A2dpCodecPriority codecPriority)123 void A2dpCodecConfig::SetCodecPriority(A2dpCodecPriority codecPriority)
124 {
125     LOG_INFO("[CodecConfig] %{public}s codecPriority:%u", __func__, codecPriority);
126     if (codecPriority == A2DP_CODEC_PRIORITY_DEFAULT) {
127         SetDefaultCodecPriority();
128     } else {
129         codecPriority_ = codecPriority;
130     }
131     codecConfig_.codecPriority_ = codecPriority_;
132 }
133 
SetDefaultCodecPriority()134 void A2dpCodecConfig::SetDefaultCodecPriority()
135 {
136     if (defaultPriority_ != A2DP_CODEC_PRIORITY_DEFAULT) {
137         codecPriority_ = defaultPriority_;
138     } else {
139         // Compute the default codec priority
140         const uint32_t priority = PRIORITY_SBC_BASIC * (codecIndex_ + PRIORITY_NUM_BASIC_VALUE) +
141             PRIORITY_NUM_BASIC_VALUE;
142         codecPriority_ = static_cast<A2dpCodecPriority>(priority);
143     }
144     codecConfig_.codecPriority_ = codecPriority_;
145 }
146 
IsConfigChanged(const uint8_t (& lastCodecInfo)[A2DP_CODEC_SIZE],const uint8_t * newCodecInfo)147 bool IsConfigChanged(const uint8_t (&lastCodecInfo)[A2DP_CODEC_SIZE], const uint8_t *newCodecInfo)
148 {
149     A2dpCodecType lastType = GetCodecType(lastCodecInfo);
150     A2dpCodecType newType = GetCodecType(newCodecInfo);
151     if (lastType != newType) {
152         return false;
153     }
154     switch (lastType) {
155         case A2DP_CODEC_TYPE_SBC:
156             return IsSbcConfigChanged(lastCodecInfo, newCodecInfo);
157         case A2DP_CODEC_TYPE_AAC:
158             return IsAacConfigChanged(lastCodecInfo, newCodecInfo);
159         default:
160             return false;
161     }
162 }
163 
SetCodecUserConfig(const A2dpCodecCapability & userConfig,const A2dpCodecCapability & audioConfig,const uint8_t * peerCodeInfo,uint8_t * resultCodecInfo,bool * restartConfig)164 bool A2dpCodecConfig::SetCodecUserConfig(const A2dpCodecCapability &userConfig, const A2dpCodecCapability &audioConfig,
165     const uint8_t *peerCodeInfo, uint8_t *resultCodecInfo, bool *restartConfig)
166 {
167     LOG_INFO("[CodecConfig] %{public}s\n", __func__);
168     bool ret = A2DP_SUCCESS;
169     A2dpCodecCapability savedCodecUserConfig = userCodecConfig_;
170     userCodecConfig_ = userConfig;
171     A2dpCodecCapability savedAudioConfig = audioCodecConfig_;
172     audioCodecConfig_ = audioConfig;
173     uint8_t lastOtaCodecConfig[A2DP_CODEC_SIZE];
174     (void)memcpy_s(lastOtaCodecConfig, A2DP_CODEC_SIZE, otaCodecConfig_, A2DP_CODEC_SIZE);
175     ret = SetCodecConfig(peerCodeInfo, resultCodecInfo);
176     LOG_INFO("[CodecConfig] %{public}s ret:%{public}d\n", __func__, ret);
177     if (!ret) {
178         userCodecConfig_ = savedCodecUserConfig;
179         audioCodecConfig_ = savedAudioConfig;
180         return ret;
181     }
182 
183     if (!IsConfigChanged(lastOtaCodecConfig, resultCodecInfo)) {
184         *restartConfig = true;
185     }
186 
187     return ret;
188 }
189 
CreateCodec(A2dpCodecIndex codecIndex,A2dpCodecPriority codecPriority)190 A2dpCodecConfig *A2dpCodecConfig::CreateCodec(A2dpCodecIndex codecIndex, A2dpCodecPriority codecPriority)
191 {
192     LOG_INFO("[CodecConfig] %{public}s [codecIndex:%u][codecPriority:%u]\n", __func__, codecIndex, codecPriority);
193     std::unique_ptr<A2dpCodecConfig>  codecConfig = nullptr;
194     switch (codecIndex) {
195         case A2DP_SOURCE_CODEC_INDEX_SBC:
196             codecConfig =  std::make_unique<A2dpCodecConfigSbcSource>(codecPriority);
197             break;
198         case A2DP_SINK_CODEC_INDEX_SBC:
199             codecConfig =  std::make_unique<A2dpCodecConfigSbcSink>(codecPriority);
200             break;
201         case A2DP_SOURCE_CODEC_INDEX_AAC:
202             codecConfig =  std::make_unique<A2dpCodecConfigAacSource>(codecPriority);
203             break;
204         case A2DP_SINK_CODEC_INDEX_AAC:
205             codecConfig =  std::make_unique<A2dpCodecConfigAacSink>(codecPriority);
206             break;
207         default:
208             break;
209     }
210 
211     return codecConfig.release();
212 }
213 
GetCodecType(const uint8_t * codecInfo)214 A2dpCodecType GetCodecType(const uint8_t *codecInfo)
215 {
216     LOG_INFO("[CodecConfig] %{public}s codectype(%u)\n", __func__, *(codecInfo + A2DP_CODEC_TYPE_INDEX));
217     return static_cast<A2dpCodecType>(*(codecInfo + A2DP_CODEC_TYPE_INDEX));
218 }
219 
GetSourceCodecIndex(const uint8_t * codecInfo)220 A2dpCodecIndex GetSourceCodecIndex(const uint8_t *codecInfo)
221 {
222     LOG_INFO("[CodecConfig] %{public}s\n", __func__);
223     A2dpCodecType codecType = GetCodecType(codecInfo);
224     LOG_INFO("[CodecConfig] %{public}s codecType:%u\n", __func__, codecType);
225     switch (codecType) {
226         case A2DP_CODEC_TYPE_SBC:
227             return A2DP_SOURCE_CODEC_INDEX_SBC;
228         case A2DP_CODEC_TYPE_AAC:
229             return A2DP_SOURCE_CODEC_INDEX_AAC;
230         default:
231             return A2DP_SOURCE_CODEC_INDEX_MAX;
232     }
233 }
234 
GetSinkCodecIndex(const uint8_t * codecInfo)235 A2dpCodecIndex GetSinkCodecIndex(const uint8_t *codecInfo)
236 {
237     LOG_INFO("%{public}s", __func__);
238     A2dpCodecType codecType = GetCodecType(codecInfo);
239     LOG_INFO("[CodecConfig] %{public}s codecType:%u\n", __func__, codecType);
240 
241     switch (codecType) {
242         case A2DP_CODEC_TYPE_SBC:
243             return A2DP_SINK_CODEC_INDEX_SBC;
244             break;
245         case A2DP_CODEC_TYPE_AAC:
246             return A2DP_SINK_CODEC_INDEX_AAC;
247             break;
248         default:
249             return A2DP_SINK_CODEC_INDEX_MAX;
250     }
251 }
252 
IsPeerSinkCodecValid(const uint8_t * codecInfo)253 bool IsPeerSinkCodecValid(const uint8_t *codecInfo)
254 {
255     bool ret = false;
256     A2dpCodecType codecType = GetCodecType(codecInfo);
257     A2dpSBCCapability sbcCap = {};
258     A2dpAACCapability aacCap = {};
259     LOG_INFO("[CodecConfig] %{public}s codecType:%u\n", __func__, codecType);
260     switch (codecType) {
261         case A2DP_CODEC_TYPE_SBC:
262             if (ParseInfoSbc(&sbcCap, codecInfo) == A2DP_SUCCESS) {
263                 ret = true;
264             }
265             break;
266         case A2DP_CODEC_TYPE_AAC:
267             if (ParseInfoAac(&aacCap, codecInfo) == A2DP_SUCCESS) {
268                 ret = true;
269             }
270             break;
271         default:
272             break;
273     }
274 
275     return ret;
276 }
277 
IsPeerSourceCodecValid(const uint8_t * codecInfo)278 bool IsPeerSourceCodecValid(const uint8_t *codecInfo)
279 {
280     bool ret = false;
281     A2dpCodecType codecType = GetCodecType(codecInfo);
282     A2dpSBCCapability sbcCap = {};
283     A2dpAACCapability aacCap = {};
284     LOG_INFO("[CodecConfig] %{public}s codecType:%u\n", __func__, codecType);
285     switch (codecType) {
286         case A2DP_CODEC_TYPE_SBC:
287             if (ParseInfoSbc(&sbcCap, codecInfo) == A2DP_SUCCESS) {
288                 ret = true;
289             }
290             break;
291         case A2DP_CODEC_TYPE_AAC:
292             if (ParseInfoAac(&aacCap, codecInfo) == A2DP_SUCCESS) {
293                 ret = true;
294             }
295             break;
296         default:
297             break;
298     }
299 
300     return ret;
301 }
302 }  // namespace bluetooth
303 }  // namespace OHOS
304