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