1 /*
2 * Copyright (C) 2023 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 #ifndef LOG_TAG
16 #define LOG_TAG "bt_napi_a2dp_src"
17 #endif
18
19 #include "bluetooth_a2dp_src.h"
20 #include "bluetooth_avrcp_tg.h"
21 #include "bluetooth_errorcode.h"
22 #include "napi_async_work.h"
23 #include "napi_bluetooth_profile.h"
24 #include "napi_bluetooth_a2dp_src.h"
25 #include "napi_bluetooth_event.h"
26 #include "napi_bluetooth_error.h"
27 #include "napi_bluetooth_host.h"
28 #include "napi_bluetooth_utils.h"
29 #include "parser/napi_parser_utils.h"
30 #include "hitrace_meter.h"
31
32 namespace OHOS {
33 namespace Bluetooth {
34 using namespace std;
35
36 std::shared_ptr<NapiA2dpSourceObserver> NapiA2dpSource::observer_ = std::make_shared<NapiA2dpSourceObserver>();
37 bool NapiA2dpSource::isRegistered_ = false;
38 thread_local napi_ref g_napiProfile = nullptr;
39
40 const static std::map<int32_t, int32_t> g_codecFrameLengthMap = {
41 {CODEC_FRAME_LENGTH_5MS, A2DP_L2HCST_FRAME_LENGTH_5MS},
42 {CODEC_FRAME_LENGTH_10MS, A2DP_L2HCST_FRAME_LENGTH_10MS},
43 };
44
45 const static std::map<int32_t, CodecType> g_a2dpCodecTypeMap = {
46 {A2DP_CODEC_TYPE_SBC_USER, CODEC_TYPE_SBC},
47 {A2DP_CODEC_TYPE_AAC_USER, CODEC_TYPE_AAC},
48 {A2DP_CODEC_TYPE_L2HCV2_USER, CODEC_TYPE_L2HC},
49 {A2DP_CODEC_TYPE_L2HCST_USER, CODEC_TYPE_L2HCST},
50 {A2DP_CODEC_TYPE_LDAC_USER, CODEC_TYPE_LDAC},
51 {A2DP_CODEC_TYPE_NONA2DP_USER, CODEC_TYPE_INVALID},
52 };
53
54 const static std::map<int32_t, CodecBitsPerSample> g_a2dpCodecBitsPerSampleMap = {
55 {A2DP_SAMPLE_BITS_NONE_USER, CODEC_BITS_PER_SAMPLE_NONE},
56 {A2DP_SAMPLE_BITS_16_USER, CODEC_BITS_PER_SAMPLE_16},
57 {A2DP_SAMPLE_BITS_24_USER, CODEC_BITS_PER_SAMPLE_24},
58 {A2DP_SAMPLE_BITS_32_USER, CODEC_BITS_PER_SAMPLE_32},
59 };
60
61 const static std::map<int32_t, CodecChannelMode> g_a2dpCodecChannelModeMap = {
62 {A2DP_CHANNEL_MODE_NONE_USER, CODEC_CHANNEL_MODE_NONE},
63 {A2DP_SBC_CHANNEL_MODE_MONO_USER, CODEC_CHANNEL_MODE_MONO},
64 {A2DP_SBC_CHANNEL_MODE_STEREO_USER, CODEC_CHANNEL_MODE_STEREO},
65 };
66
67 const static std::map<int32_t, CodecSampleRate> g_a2dpCodecSampleRateMap = {
68 {A2DP_SAMPLE_RATE_NONE_USER, CODEC_SAMPLE_RATE_NONE},
69 {A2DP_SBC_SAMPLE_RATE_44100_USER, CODEC_SAMPLE_RATE_44100},
70 {A2DP_SBC_SAMPLE_RATE_48000_USER, CODEC_SAMPLE_RATE_48000},
71 {A2DP_L2HCV2_SAMPLE_RATE_48000_USER, CODEC_SAMPLE_RATE_48000},
72 {A2DP_L2HCV2_SAMPLE_RATE_96000_USER, CODEC_SAMPLE_RATE_96000},
73 };
74
75 const static std::map<int32_t, CodecBitRate> g_a2dpCodecBitRateMap = {
76 {A2DP_L2HCST_BIT_RATE_96K, CODEC_BIT_RATE_96000},
77 {A2DP_L2HCST_BIT_RATE_128K, CODEC_BIT_RATE_128000},
78 {A2DP_L2HCST_BIT_RATE_192K, CODEC_BIT_RATE_192000},
79 {A2DP_L2HCST_BIT_RATE_256K, CODEC_BIT_RATE_256000},
80 {A2DP_L2HCST_BIT_RATE_320K, CODEC_BIT_RATE_320000},
81 {A2DP_L2HCST_BIT_RATE_480K, CODEC_BIT_RATE_480000},
82 {A2DP_L2HCST_BIT_RATE_640K, CODEC_BIT_RATE_640000},
83 {A2DP_L2HCST_BIT_RATE_960K, CODEC_BIT_RATE_960000},
84 {A2DP_L2HCST_BIT_RATE_AUTO_RATE, CODEC_BIT_RATE_ABR},
85 };
86
87 const static std::map<int32_t, CodecBitRate> g_a2dpL2hcV2BitRateMap = {
88 {A2DP_L2HCV2_BIT_RATE_320K, CODEC_BIT_RATE_320000},
89 {A2DP_L2HCV2_BIT_RATE_640K, CODEC_BIT_RATE_640000},
90 {A2DP_L2HCV2_BIT_RATE_960K, CODEC_BIT_RATE_960000},
91 {A2DP_L2HCV2_BIT_RATE_1500K, CODEC_BIT_RATE_1500000},
92 {A2DP_L2HCV2_BIT_RATE_2300K, CODEC_BIT_RATE_2300000},
93 {A2DP_L2HCV2_BIT_RATE_AUTO_RATE, CODEC_BIT_RATE_ABR},
94 };
95
96 const static std::map<int32_t, CodecFrameLength> g_a2dpCodecFrameLengthMap = {
97 {A2DP_L2HCST_FRAME_LENGTH_5MS, CODEC_FRAME_LENGTH_5MS},
98 {A2DP_L2HCST_FRAME_LENGTH_10MS, CODEC_FRAME_LENGTH_10MS},
99 };
100
DefineA2dpSourceJSClass(napi_env env,napi_value exports)101 napi_value NapiA2dpSource::DefineA2dpSourceJSClass(napi_env env, napi_value exports)
102 {
103 A2dpPropertyValueInit(env, exports);
104 napi_property_descriptor properties[] = {
105 DECLARE_NAPI_FUNCTION("on", On),
106 DECLARE_NAPI_FUNCTION("off", Off),
107 DECLARE_NAPI_FUNCTION("connect", Connect),
108 DECLARE_NAPI_FUNCTION("disconnect", Disconnect),
109 DECLARE_NAPI_FUNCTION("getPlayingState", GetPlayingState),
110 #ifndef BLUETOOTH_API_SINCE_10
111 DECLARE_NAPI_FUNCTION("getConnectionDevices", GetConnectionDevices),
112 DECLARE_NAPI_FUNCTION("getDeviceState", GetDeviceState),
113 #endif
114 #ifdef BLUETOOTH_API_SINCE_10
115 DECLARE_NAPI_FUNCTION("setConnectionStrategy", SetConnectionStrategy),
116 DECLARE_NAPI_FUNCTION("getConnectionStrategy", GetConnectionStrategy),
117 DECLARE_NAPI_FUNCTION("getConnectionState", GetConnectionState),
118 DECLARE_NAPI_FUNCTION("getConnectedDevices", GetConnectedDevices),
119 DECLARE_NAPI_FUNCTION("isAbsoluteVolumeSupported", IsAbsoluteVolumeSupported),
120 DECLARE_NAPI_FUNCTION("isAbsoluteVolumeEnabled", IsAbsoluteVolumeEnabled),
121 DECLARE_NAPI_FUNCTION("enableAbsoluteVolume", EnableAbsoluteVolume),
122 DECLARE_NAPI_FUNCTION("disableAbsoluteVolume", DisableAbsoluteVolume),
123 DECLARE_NAPI_FUNCTION("setCurrentCodecInfo", SetCurrentCodecInfo),
124 DECLARE_NAPI_FUNCTION("getCurrentCodecInfo", GetCurrentCodecInfo),
125 DECLARE_NAPI_FUNCTION("enableAutoPlay", EnableAutoPlay),
126 DECLARE_NAPI_FUNCTION("disableAutoPlay", DisableAutoPlay),
127 DECLARE_NAPI_FUNCTION("getAutoPlayDisabledDuration", GetAutoPlayDisabledDuration),
128 DECLARE_NAPI_FUNCTION("getCurrentFullCodecInfo", GetCurrentFullCodecInfo),
129 #endif
130 };
131
132 napi_value constructor;
133 napi_define_class(env,
134 "A2dpSource",
135 NAPI_AUTO_LENGTH,
136 A2dpSourceConstructor,
137 nullptr,
138 sizeof(properties) / sizeof(properties[0]),
139 properties,
140 &constructor);
141 #ifdef BLUETOOTH_API_SINCE_10
142 DefineCreateProfile(env, exports);
143 napi_create_reference(env, constructor, 1, &g_napiProfile);
144 #else
145 napi_value napiProfile;
146 napi_new_instance(env, constructor, 0, nullptr, &napiProfile);
147 NapiProfile::SetProfile(env, ProfileId::PROFILE_A2DP_SOURCE, napiProfile);
148 #endif
149 return exports;
150 }
151
A2dpSourceConstructor(napi_env env,napi_callback_info info)152 napi_value NapiA2dpSource::A2dpSourceConstructor(napi_env env, napi_callback_info info)
153 {
154 napi_value thisVar = nullptr;
155 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
156 return thisVar;
157 }
158
On(napi_env env,napi_callback_info info)159 napi_value NapiA2dpSource::On(napi_env env, napi_callback_info info)
160 {
161 if (observer_) {
162 auto status = observer_->eventSubscribe_.Register(env, info);
163 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
164 }
165
166 if (!isRegistered_) {
167 A2dpSource *profile = A2dpSource::GetProfile();
168 profile->RegisterObserver(observer_);
169 isRegistered_ = true;
170 }
171 return NapiGetUndefinedRet(env);
172 }
173
Off(napi_env env,napi_callback_info info)174 napi_value NapiA2dpSource::Off(napi_env env, napi_callback_info info)
175 {
176 if (observer_) {
177 auto status = observer_->eventSubscribe_.Deregister(env, info);
178 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
179 }
180 return NapiGetUndefinedRet(env);
181 }
182
GetPlayingState(napi_env env,napi_callback_info info)183 napi_value NapiA2dpSource::GetPlayingState(napi_env env, napi_callback_info info)
184 {
185 HILOGD("start");
186 int state = PlayingState::STATE_NOT_PLAYING;
187 napi_value ret = nullptr;
188 napi_create_int32(env, state, &ret);
189
190 std::string remoteAddr{};
191 bool checkRet = CheckDeivceIdParam(env, info, remoteAddr);
192 NAPI_BT_ASSERT_RETURN(env, checkRet, BT_ERR_INVALID_PARAM, ret);
193
194 int transport = BT_TRANSPORT_BREDR;
195 BluetoothRemoteDevice remoteDevice = BluetoothRemoteDevice(remoteAddr, transport);
196 A2dpSource *profile = A2dpSource::GetProfile();
197 int32_t errorCode = profile->GetPlayingState(remoteDevice, state);
198 HILOGI("errorCode: %{public}d", errorCode);
199 NAPI_BT_ASSERT_RETURN(env, (errorCode == BT_NO_ERROR), errorCode, ret);
200
201 return NapiGetInt32Ret(env, state);
202 }
203
Connect(napi_env env,napi_callback_info info)204 napi_value NapiA2dpSource::Connect(napi_env env, napi_callback_info info)
205 {
206 HILOGD("start");
207 std::string remoteAddr{};
208 bool checkRet = CheckDeivceIdParam(env, info, remoteAddr);
209 NAPI_BT_ASSERT_RETURN_FALSE(env, checkRet, BT_ERR_INVALID_PARAM);
210
211 int transport = BT_TRANSPORT_BREDR;
212 BluetoothRemoteDevice remoteDevice = BluetoothRemoteDevice(remoteAddr, transport);
213 A2dpSource *profile = A2dpSource::GetProfile();
214 int32_t ret = profile->Connect(remoteDevice);
215 NAPI_BT_ASSERT_RETURN_FALSE(env, ret == BT_NO_ERROR, ret);
216
217 return NapiGetBooleanTrue(env);
218 }
219
Disconnect(napi_env env,napi_callback_info info)220 napi_value NapiA2dpSource::Disconnect(napi_env env, napi_callback_info info)
221 {
222 HILOGD("start");
223 std::string remoteAddr{};
224 bool checkRet = CheckDeivceIdParam(env, info, remoteAddr);
225 NAPI_BT_ASSERT_RETURN_FALSE(env, checkRet, BT_ERR_INVALID_PARAM);
226
227 int transport = BT_TRANSPORT_BREDR;
228 BluetoothRemoteDevice remoteDevice = BluetoothRemoteDevice(remoteAddr, transport);
229 A2dpSource *profile = A2dpSource::GetProfile();
230 int32_t ret = profile->Disconnect(remoteDevice);
231 NAPI_BT_ASSERT_RETURN_FALSE(env, ret == BT_NO_ERROR, ret);
232
233 return NapiGetBooleanTrue(env);
234 }
235
PlayingStateInit(napi_env env)236 napi_value PlayingStateInit(napi_env env)
237 {
238 napi_value playingState = nullptr;
239 napi_create_object(env, &playingState);
240 SetNamedPropertyByInteger(env, playingState, PlayingState::STATE_NOT_PLAYING, "STATE_NOT_PLAYING");
241 SetNamedPropertyByInteger(env, playingState, PlayingState::STATE_PLAYING, "STATE_PLAYING");
242 return playingState;
243 }
244
CodecTypeInit(napi_env env)245 napi_value CodecTypeInit(napi_env env)
246 {
247 napi_value codecType = nullptr;
248 napi_create_object(env, &codecType);
249 SetNamedPropertyByInteger(env, codecType, CodecType::CODEC_TYPE_SBC, "CODEC_TYPE_SBC");
250 SetNamedPropertyByInteger(env, codecType, CodecType::CODEC_TYPE_AAC, "CODEC_TYPE_AAC");
251 SetNamedPropertyByInteger(env, codecType, CodecType::CODEC_TYPE_L2HC, "CODEC_TYPE_L2HC");
252 SetNamedPropertyByInteger(env, codecType, CodecType::CODEC_TYPE_L2HCST, "CODEC_TYPE_L2HCST");
253 SetNamedPropertyByInteger(env, codecType, CodecType::CODEC_TYPE_LDAC, "CODEC_TYPE_LDAC");
254 SetNamedPropertyByInteger(env, codecType, CodecType::CODEC_TYPE_INVALID, "CODEC_TYPE_INVALID");
255 return codecType;
256 }
257
CodecBitsPerSampleInit(napi_env env)258 napi_value CodecBitsPerSampleInit(napi_env env)
259 {
260 napi_value codecBitsPerSample = nullptr;
261 napi_create_object(env, &codecBitsPerSample);
262 SetNamedPropertyByInteger(env, codecBitsPerSample,
263 CodecBitsPerSample::CODEC_BITS_PER_SAMPLE_NONE, "CODEC_BITS_PER_SAMPLE_NONE");
264 SetNamedPropertyByInteger(env, codecBitsPerSample,
265 CodecBitsPerSample::CODEC_BITS_PER_SAMPLE_16, "CODEC_BITS_PER_SAMPLE_16");
266 SetNamedPropertyByInteger(env, codecBitsPerSample,
267 CodecBitsPerSample::CODEC_BITS_PER_SAMPLE_24, "CODEC_BITS_PER_SAMPLE_24");
268 SetNamedPropertyByInteger(env, codecBitsPerSample,
269 CodecBitsPerSample::CODEC_BITS_PER_SAMPLE_32, "CODEC_BITS_PER_SAMPLE_32");
270 return codecBitsPerSample;
271 }
272
CodecChannelModeInit(napi_env env)273 napi_value CodecChannelModeInit(napi_env env)
274 {
275 napi_value codecChannelMode = nullptr;
276 napi_create_object(env, &codecChannelMode);
277 SetNamedPropertyByInteger(env, codecChannelMode,
278 CodecChannelMode::CODEC_CHANNEL_MODE_NONE, "CODEC_CHANNEL_MODE_NONE");
279 SetNamedPropertyByInteger(env, codecChannelMode,
280 CodecChannelMode::CODEC_CHANNEL_MODE_MONO, "CODEC_CHANNEL_MODE_MONO");
281 SetNamedPropertyByInteger(env, codecChannelMode,
282 CodecChannelMode::CODEC_CHANNEL_MODE_STEREO, "CODEC_CHANNEL_MODE_STEREO");
283 return codecChannelMode;
284 }
285
CodecSampleRateInit(napi_env env)286 napi_value CodecSampleRateInit(napi_env env)
287 {
288 napi_value codecSampleRate = nullptr;
289 napi_create_object(env, &codecSampleRate);
290 SetNamedPropertyByInteger(env, codecSampleRate,
291 CodecSampleRate::CODEC_SAMPLE_RATE_NONE, "CODEC_SAMPLE_RATE_NONE");
292 SetNamedPropertyByInteger(env, codecSampleRate,
293 CodecSampleRate::CODEC_SAMPLE_RATE_44100, "CODEC_SAMPLE_RATE_44100");
294 SetNamedPropertyByInteger(env, codecSampleRate,
295 CodecSampleRate::CODEC_SAMPLE_RATE_48000, "CODEC_SAMPLE_RATE_48000");
296 SetNamedPropertyByInteger(env, codecSampleRate,
297 CodecSampleRate::CODEC_SAMPLE_RATE_88200, "CODEC_SAMPLE_RATE_88200");
298 SetNamedPropertyByInteger(env, codecSampleRate,
299 CodecSampleRate::CODEC_SAMPLE_RATE_96000, "CODEC_SAMPLE_RATE_96000");
300 SetNamedPropertyByInteger(env, codecSampleRate,
301 CodecSampleRate::CODEC_SAMPLE_RATE_176400, "CODEC_SAMPLE_RATE_176400");
302 SetNamedPropertyByInteger(env, codecSampleRate,
303 CodecSampleRate::CODEC_SAMPLE_RATE_192000, "CODEC_SAMPLE_RATE_192000");
304 return codecSampleRate;
305 }
306
CodecBitRateInit(napi_env env)307 napi_value CodecBitRateInit(napi_env env)
308 {
309 napi_value codecBitRate = nullptr;
310 napi_create_object(env, &codecBitRate);
311 SetNamedPropertyByInteger(env, codecBitRate,
312 CodecBitRate::CODEC_BIT_RATE_96000, "CODEC_BIT_RATE_96000");
313 SetNamedPropertyByInteger(env, codecBitRate,
314 CodecBitRate::CODEC_BIT_RATE_128000, "CODEC_BIT_RATE_128000");
315 SetNamedPropertyByInteger(env, codecBitRate,
316 CodecBitRate::CODEC_BIT_RATE_192000, "CODEC_BIT_RATE_192000");
317 SetNamedPropertyByInteger(env, codecBitRate,
318 CodecBitRate::CODEC_BIT_RATE_256000, "CODEC_BIT_RATE_256000");
319 SetNamedPropertyByInteger(env, codecBitRate,
320 CodecBitRate::CODEC_BIT_RATE_320000, "CODEC_BIT_RATE_320000");
321 SetNamedPropertyByInteger(env, codecBitRate,
322 CodecBitRate::CODEC_BIT_RATE_480000, "CODEC_BIT_RATE_480000");
323 SetNamedPropertyByInteger(env, codecBitRate,
324 CodecBitRate::CODEC_BIT_RATE_640000, "CODEC_BIT_RATE_640000");
325 SetNamedPropertyByInteger(env, codecBitRate,
326 CodecBitRate::CODEC_BIT_RATE_960000, "CODEC_BIT_RATE_960000");
327 SetNamedPropertyByInteger(env, codecBitRate,
328 CodecBitRate::CODEC_BIT_RATE_1500000, "CODEC_BIT_RATE_1500000");
329 SetNamedPropertyByInteger(env, codecBitRate,
330 CodecBitRate::CODEC_BIT_RATE_2300000, "CODEC_BIT_RATE_2300000");
331 SetNamedPropertyByInteger(env, codecBitRate,
332 CodecBitRate::CODEC_BIT_RATE_ABR, "CODEC_BIT_RATE_ABR");
333 return codecBitRate;
334 }
335
CodecFrameLengthInit(napi_env env)336 napi_value CodecFrameLengthInit(napi_env env)
337 {
338 napi_value codecFrameLength = nullptr;
339 napi_create_object(env, &codecFrameLength);
340 SetNamedPropertyByInteger(env, codecFrameLength,
341 CodecFrameLength::CODEC_FRAME_LENGTH_5MS, "CODEC_FRAME_LENGTH_5MS");
342 SetNamedPropertyByInteger(env, codecFrameLength,
343 CodecFrameLength::CODEC_FRAME_LENGTH_10MS, "CODEC_FRAME_LENGTH_10MS");
344 return codecFrameLength;
345 }
346
A2dpPropertyValueInit(napi_env env,napi_value exports)347 napi_value NapiA2dpSource::A2dpPropertyValueInit(napi_env env, napi_value exports)
348 {
349 napi_value playingStateObj = PlayingStateInit(env);
350 napi_value codecTypeObj = CodecTypeInit(env);
351 napi_value codecBitsPerSampleObj = CodecBitsPerSampleInit(env);
352 napi_value codecChannelModeObj = CodecChannelModeInit(env);
353 napi_value codecSampleRateObj = CodecSampleRateInit(env);
354 napi_value codecBitRateObj = CodecBitRateInit(env);
355 napi_value codecFrameLengthObj = CodecFrameLengthInit(env);
356 napi_property_descriptor exportProps[] = {
357 DECLARE_NAPI_PROPERTY("PlayingState", playingStateObj),
358 DECLARE_NAPI_PROPERTY("CodecType", codecTypeObj),
359 DECLARE_NAPI_PROPERTY("CodecBitsPerSample", codecBitsPerSampleObj),
360 DECLARE_NAPI_PROPERTY("CodecChannelMode", codecChannelModeObj),
361 DECLARE_NAPI_PROPERTY("CodecSampleRate", codecSampleRateObj),
362 DECLARE_NAPI_PROPERTY("CodecBitRate", codecBitRateObj),
363 DECLARE_NAPI_PROPERTY("CodecFrameLength", codecFrameLengthObj),
364 };
365 HITRACE_METER_NAME(HITRACE_TAG_OHOS, "a2dp_src:napi_define_properties");
366 napi_define_properties(env, exports, sizeof(exportProps) / sizeof(*exportProps), exportProps);
367 return exports;
368 }
369
GetConnectionDevices(napi_env env,napi_callback_info info)370 napi_value NapiA2dpSource::GetConnectionDevices(napi_env env, napi_callback_info info)
371 {
372 HILOGI("enter");
373 napi_value ret = nullptr;
374 napi_create_array(env, &ret);
375 A2dpSource *profile = A2dpSource::GetProfile();
376 vector<int> states;
377 states.push_back(1);
378 vector<BluetoothRemoteDevice> devices;
379 int errorCode = profile->GetDevicesByStates(states, devices);
380 NAPI_BT_ASSERT_RETURN(env, (errorCode == BT_NO_ERROR), errorCode, ret);
381
382 vector<string> deviceVector;
383 for (auto &device : devices) {
384 deviceVector.push_back(device.GetDeviceAddr());
385 }
386 ConvertStringVectorToJS(env, ret, deviceVector);
387 return ret;
388 }
389
GetDeviceState(napi_env env,napi_callback_info info)390 napi_value NapiA2dpSource::GetDeviceState(napi_env env, napi_callback_info info)
391 {
392 HILOGD("enter");
393
394 size_t expectedArgsCount = ARGS_SIZE_ONE;
395 size_t argc = expectedArgsCount;
396 napi_value argv[ARGS_SIZE_ONE] = {0};
397 napi_value thisVar = nullptr;
398
399 napi_value ret = nullptr;
400 napi_get_undefined(env, &ret);
401
402 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
403 if (argc != expectedArgsCount) {
404 HILOGE("Requires 1 argument.");
405 return ret;
406 }
407 string deviceId;
408 if (!ParseString(env, deviceId, argv[PARAM0])) {
409 HILOGE("string expected.");
410 return ret;
411 }
412
413 A2dpSource *profile = A2dpSource::GetProfile();
414 BluetoothRemoteDevice device(deviceId, 1);
415
416 int32_t profileState = ProfileConnectionState::STATE_DISCONNECTED;
417 if (napi_create_int32(env, profileState, &ret) != napi_ok) {
418 HILOGE("napi_create_int32 failed.");
419 }
420
421 int btConnectState = static_cast<int32_t>(BTConnectState::DISCONNECTED);
422 int errorCode = profile->GetDeviceState(device, btConnectState);
423 NAPI_BT_ASSERT_RETURN(env, (errorCode == BT_NO_ERROR), errorCode, ret);
424
425 napi_value result = nullptr;
426 int status = GetProfileConnectionState(btConnectState);
427 napi_create_int32(env, status, &result);
428 HILOGD("status: %{public}d", status);
429 return result;
430 }
431
432 #ifdef BLUETOOTH_API_SINCE_10
DefineCreateProfile(napi_env env,napi_value exports)433 napi_value NapiA2dpSource::DefineCreateProfile(napi_env env, napi_value exports)
434 {
435 napi_property_descriptor properties[] = {
436 DECLARE_NAPI_FUNCTION("createA2dpSrcProfile", CreateA2dpSrcProfile),
437 };
438 HITRACE_METER_NAME(HITRACE_TAG_OHOS, "a2dp_src:napi_define_properties");
439 napi_define_properties(env, exports, sizeof(properties) / sizeof(properties[0]), properties);
440 return exports;
441 }
442
CreateA2dpSrcProfile(napi_env env,napi_callback_info info)443 napi_value NapiA2dpSource::CreateA2dpSrcProfile(napi_env env, napi_callback_info info)
444 {
445 napi_value profile;
446 napi_value constructor = nullptr;
447 napi_get_reference_value(env, g_napiProfile, &constructor);
448 napi_new_instance(env, constructor, 0, nullptr, &profile);
449 return profile;
450 }
451
SetConnectionStrategy(napi_env env,napi_callback_info info)452 napi_value NapiA2dpSource::SetConnectionStrategy(napi_env env, napi_callback_info info)
453 {
454 HILOGD("start");
455 std::string remoteAddr{};
456 int32_t strategy = 0;
457 auto status = CheckSetConnectStrategyParam(env, info, remoteAddr, strategy);
458 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
459
460 int transport = BT_TRANSPORT_BREDR;
461 auto func = [remoteAddr, transport, strategy]() {
462 BluetoothRemoteDevice remoteDevice(remoteAddr, transport);
463 A2dpSource *profile = A2dpSource::GetProfile();
464 int32_t err = profile->SetConnectStrategy(remoteDevice, strategy);
465 HILOGI("err: %{public}d", err);
466 return NapiAsyncWorkRet(err);
467 };
468 auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NO_NEED_CALLBACK);
469 NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
470 asyncWork->Run();
471 return asyncWork->GetRet();
472 }
473
GetConnectionStrategy(napi_env env,napi_callback_info info)474 napi_value NapiA2dpSource::GetConnectionStrategy(napi_env env, napi_callback_info info)
475 {
476 HILOGD("start");
477 std::string remoteAddr{};
478 auto status = CheckDeviceAddressParam(env, info, remoteAddr);
479 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
480
481 int transport = BT_TRANSPORT_BREDR;
482 auto func = [remoteAddr, transport]() {
483 int strategy = 0;
484 BluetoothRemoteDevice remoteDevice(remoteAddr, transport);
485 A2dpSource *profile = A2dpSource::GetProfile();
486 int32_t err = profile->GetConnectStrategy(remoteDevice, strategy);
487 HILOGD("err: %{public}d, deviceName: %{public}d", err, strategy);
488 auto object = std::make_shared<NapiNativeInt>(strategy);
489 return NapiAsyncWorkRet(err, object);
490 };
491 auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NO_NEED_CALLBACK);
492 NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
493 asyncWork->Run();
494 return asyncWork->GetRet();
495 }
496
GetConnectionState(napi_env env,napi_callback_info info)497 napi_value NapiA2dpSource::GetConnectionState(napi_env env, napi_callback_info info)
498 {
499 return GetDeviceState(env, info);
500 }
GetConnectedDevices(napi_env env,napi_callback_info info)501 napi_value NapiA2dpSource::GetConnectedDevices(napi_env env, napi_callback_info info)
502 {
503 return GetConnectionDevices(env, info);
504 }
505
IsAbsoluteVolumeSupported(napi_env env,napi_callback_info info)506 napi_value NapiA2dpSource::IsAbsoluteVolumeSupported(napi_env env, napi_callback_info info)
507 {
508 HILOGD("start");
509 std::string remoteAddr{};
510 auto status = CheckDeviceAddressParam(env, info, remoteAddr);
511 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
512
513 auto func = [remoteAddr]() {
514 int32_t ability = DeviceAbsVolumeAbility::DEVICE_ABSVOL_UNSUPPORT;
515 BluetoothRemoteDevice remoteDevice(remoteAddr, BT_TRANSPORT_BREDR);
516 int32_t err = AvrcpTarget::GetProfile()->GetDeviceAbsVolumeAbility(remoteDevice, ability);
517 if (ability == DeviceAbsVolumeAbility::DEVICE_ABSVOL_UNSUPPORT) {
518 return NapiAsyncWorkRet(err, std::make_shared<NapiNativeBool>(false));
519 }
520 return NapiAsyncWorkRet(err, std::make_shared<NapiNativeBool>(true));
521 };
522 auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NO_NEED_CALLBACK);
523 NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
524 asyncWork->Run();
525 return asyncWork->GetRet();
526 }
527
IsAbsoluteVolumeEnabled(napi_env env,napi_callback_info info)528 napi_value NapiA2dpSource::IsAbsoluteVolumeEnabled(napi_env env, napi_callback_info info)
529 {
530 HILOGD("start");
531 std::string remoteAddr{};
532 auto status = CheckDeviceAddressParam(env, info, remoteAddr);
533 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
534
535 auto func = [remoteAddr]() {
536 int32_t ability = DeviceAbsVolumeAbility::DEVICE_ABSVOL_UNSUPPORT;
537 BluetoothRemoteDevice remoteDevice(remoteAddr, BT_TRANSPORT_BREDR);
538 int32_t err = AvrcpTarget::GetProfile()->GetDeviceAbsVolumeAbility(remoteDevice, ability);
539 if (ability == DeviceAbsVolumeAbility::DEVICE_ABSVOL_OPEN) {
540 return NapiAsyncWorkRet(err, std::make_shared<NapiNativeBool>(true));
541 }
542 return NapiAsyncWorkRet(err, std::make_shared<NapiNativeBool>(false));
543 };
544 auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NO_NEED_CALLBACK);
545 NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
546 asyncWork->Run();
547 return asyncWork->GetRet();
548 }
549
EnableAbsoluteVolume(napi_env env,napi_callback_info info)550 napi_value NapiA2dpSource::EnableAbsoluteVolume(napi_env env, napi_callback_info info)
551 {
552 HILOGD("start");
553 std::string remoteAddr{};
554 auto status = CheckDeviceAddressParam(env, info, remoteAddr);
555 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
556
557 auto func = [remoteAddr]() {
558 int32_t ability = DeviceAbsVolumeAbility::DEVICE_ABSVOL_OPEN;
559 BluetoothRemoteDevice remoteDevice(remoteAddr, BT_TRANSPORT_BREDR);
560 int32_t err = AvrcpTarget::GetProfile()->SetDeviceAbsVolumeAbility(remoteDevice, ability);
561 return NapiAsyncWorkRet(err);
562 };
563 auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NO_NEED_CALLBACK);
564 NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
565 asyncWork->Run();
566 return asyncWork->GetRet();
567 }
568
DisableAbsoluteVolume(napi_env env,napi_callback_info info)569 napi_value NapiA2dpSource::DisableAbsoluteVolume(napi_env env, napi_callback_info info)
570 {
571 HILOGD("start");
572 std::string remoteAddr{};
573 auto status = CheckDeviceAddressParam(env, info, remoteAddr);
574 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
575
576 auto func = [remoteAddr]() {
577 int32_t ability = DeviceAbsVolumeAbility::DEVICE_ABSVOL_CLOSE;
578 BluetoothRemoteDevice remoteDevice(remoteAddr, BT_TRANSPORT_BREDR);
579 int32_t err = AvrcpTarget::GetProfile()->SetDeviceAbsVolumeAbility(remoteDevice, ability);
580 return NapiAsyncWorkRet(err);
581 };
582 auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NO_NEED_CALLBACK);
583 NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
584 asyncWork->Run();
585 return asyncWork->GetRet();
586 }
587
ConvertCodecType(A2dpCodecInfo & a2dpCodecInfo,int32_t codecType)588 static void ConvertCodecType(A2dpCodecInfo &a2dpCodecInfo, int32_t codecType)
589 {
590 for (const auto& codecType_ : g_a2dpCodecTypeMap) {
591 if (codecType_.second == codecType) {
592 a2dpCodecInfo.codecType = codecType_.first;
593 break;
594 }
595 }
596 }
597
ConvertCodecBitsPerSample(A2dpCodecInfo & a2dpCodecInfo,int32_t codecBitsPerSample)598 static void ConvertCodecBitsPerSample(A2dpCodecInfo &a2dpCodecInfo, int32_t codecBitsPerSample)
599 {
600 for (const auto& bitsPerSample_ : g_a2dpCodecBitsPerSampleMap) {
601 if (bitsPerSample_.second == codecBitsPerSample) {
602 a2dpCodecInfo.bitsPerSample = bitsPerSample_.first;
603 break;
604 }
605 }
606 }
607
ConvertCodecChannelMode(A2dpCodecInfo & a2dpCodecInfo,int32_t codecChannelMode)608 static void ConvertCodecChannelMode(A2dpCodecInfo &a2dpCodecInfo, int32_t codecChannelMode)
609 {
610 for (const auto& channelMode : g_a2dpCodecChannelModeMap) {
611 if (channelMode.second == codecChannelMode) {
612 a2dpCodecInfo.channelMode = channelMode.first;
613 break;
614 }
615 }
616 }
617
ConvertCodecSampleRate(A2dpCodecInfo & a2dpCodecInfo,int32_t codecSampleRate)618 static void ConvertCodecSampleRate(A2dpCodecInfo &a2dpCodecInfo, int32_t codecSampleRate)
619 {
620 for (const auto& sampleRate : g_a2dpCodecSampleRateMap) {
621 if (sampleRate.second == codecSampleRate) {
622 a2dpCodecInfo.sampleRate = sampleRate.first;
623 break;
624 }
625 }
626 }
627
ConvertL2hcStCodecBitRate(A2dpCodecInfo & a2dpCodecInfo,int32_t codecBitRate)628 static void ConvertL2hcStCodecBitRate(A2dpCodecInfo &a2dpCodecInfo, int32_t codecBitRate)
629 {
630 for (const auto& bitRate : g_a2dpCodecBitRateMap) {
631 if (bitRate.second == codecBitRate) {
632 a2dpCodecInfo.codecSpecific4 = bitRate.first;
633 break;
634 }
635 }
636 }
637
ConvertL2hcV2BitRate(A2dpCodecInfo & a2dpCodecInfo,int32_t codecBitRate)638 static void ConvertL2hcV2BitRate(A2dpCodecInfo &a2dpCodecInfo, int32_t codecBitRate)
639 {
640 for (const auto& bitRate : g_a2dpL2hcV2BitRateMap) {
641 if (bitRate.second == codecBitRate) {
642 a2dpCodecInfo.codecSpecific4 = bitRate.first;
643 break;
644 }
645 }
646 }
647
ConvertCodecTypeToCodecInfo(CodecInfo & codecInfo,int32_t codecType)648 static void ConvertCodecTypeToCodecInfo(CodecInfo &codecInfo, int32_t codecType)
649 {
650 auto iter = g_a2dpCodecTypeMap.find(codecType);
651 if (iter != g_a2dpCodecTypeMap.end()) {
652 codecInfo.codecType = iter->second;
653 }
654 }
655
ConvertCodecBitsPerSampleToCodecInfo(CodecInfo & codecInfo,int32_t codecBitsPerSample)656 static void ConvertCodecBitsPerSampleToCodecInfo(CodecInfo &codecInfo, int32_t codecBitsPerSample)
657 {
658 auto iter = g_a2dpCodecBitsPerSampleMap.find(codecBitsPerSample);
659 if (iter != g_a2dpCodecBitsPerSampleMap.end()) {
660 codecInfo.codecBitsPerSample = iter->second;
661 }
662 }
663
ConvertCodecChannelModeToCodecInfo(CodecInfo & codecInfo,int32_t codecChannelMode)664 static void ConvertCodecChannelModeToCodecInfo(CodecInfo &codecInfo, int32_t codecChannelMode)
665 {
666 auto iter = g_a2dpCodecChannelModeMap.find(codecChannelMode);
667 if (iter != g_a2dpCodecChannelModeMap.end()) {
668 codecInfo.codecChannelMode = iter->second;
669 }
670 }
671
ConvertCodecSampleRateToCodecInfo(CodecInfo & codecInfo,int32_t codecSampleRate)672 static void ConvertCodecSampleRateToCodecInfo(CodecInfo &codecInfo, int32_t codecSampleRate)
673 {
674 auto iter = g_a2dpCodecSampleRateMap.find(codecSampleRate);
675 if (iter != g_a2dpCodecSampleRateMap.end()) {
676 codecInfo.codecSampleRate = iter->second;
677 }
678 }
679
ConvertCodecBitRateToCodecInfo(CodecInfo & codecInfo,int32_t codecBitRate)680 static void ConvertCodecBitRateToCodecInfo(CodecInfo &codecInfo, int32_t codecBitRate)
681 {
682 auto iter = g_a2dpCodecBitRateMap.find(codecBitRate);
683 if (iter != g_a2dpCodecBitRateMap.end()) {
684 codecInfo.codecBitRate = iter->second;
685 } else {
686 codecInfo.codecBitRate = CODEC_BIT_RATE_ABR; // default value is ABR
687 }
688 }
689
ConvertL2hcV2BitRateToCodecInfo(CodecInfo & codecInfo,int32_t codecBitRate)690 static void ConvertL2hcV2BitRateToCodecInfo(CodecInfo &codecInfo, int32_t codecBitRate)
691 {
692 auto iter = g_a2dpL2hcV2BitRateMap.find(codecBitRate);
693 if (iter != g_a2dpL2hcV2BitRateMap.end()) {
694 codecInfo.codecBitRate = iter->second;
695 } else {
696 codecInfo.codecBitRate = CODEC_BIT_RATE_ABR; // default value is ABR
697 }
698 }
699
ConvertCodecInfoToJs(napi_env env,napi_value & object,const A2dpCodecInfo & a2dpCodecInfo)700 static void ConvertCodecInfoToJs(napi_env env, napi_value &object, const A2dpCodecInfo &a2dpCodecInfo)
701 {
702 // convert A2dpCodecInfo to CodecInfo
703 CodecInfo codecInfo;
704 ConvertCodecSampleRateToCodecInfo(codecInfo, a2dpCodecInfo.sampleRate);
705 ConvertCodecChannelModeToCodecInfo(codecInfo, a2dpCodecInfo.channelMode);
706 ConvertCodecBitsPerSampleToCodecInfo(codecInfo, a2dpCodecInfo.bitsPerSample);
707 ConvertCodecTypeToCodecInfo(codecInfo, a2dpCodecInfo.codecType);
708 if (a2dpCodecInfo.codecType == A2DP_CODEC_TYPE_L2HCST_USER) {
709 ConvertCodecBitRateToCodecInfo(codecInfo, a2dpCodecInfo.codecSpecific4);
710 } else if (a2dpCodecInfo.codecType == A2DP_CODEC_TYPE_L2HCV2_USER) {
711 ConvertL2hcV2BitRateToCodecInfo(codecInfo, a2dpCodecInfo.codecSpecific4);
712 }
713
714 // convert CodecInfo to JS
715 napi_value value = nullptr;
716 napi_create_int32(env, codecInfo.codecType, &value);
717 napi_set_named_property(env, object, "codecType", value);
718 napi_create_int32(env, codecInfo.codecBitsPerSample, &value);
719 napi_set_named_property(env, object, "codecBitsPerSample", value);
720 napi_create_int32(env, codecInfo.codecChannelMode, &value);
721 napi_set_named_property(env, object, "codecChannelMode", value);
722 napi_create_int32(env, codecInfo.codecSampleRate, &value);
723 napi_set_named_property(env, object, "codecSampleRate", value);
724 napi_create_int32(env, codecInfo.codecBitRate, &value);
725 napi_set_named_property(env, object, "codecBitRate", value);
726 if (a2dpCodecInfo.codecType == A2DP_CODEC_TYPE_L2HCST_USER ||
727 a2dpCodecInfo.codecType == A2DP_CODEC_TYPE_L2HCV2_USER) {
728 napi_create_int32(env, CODEC_FRAME_LENGTH_10MS, &value); // only 10ms frame length is supported
729 napi_set_named_property(env, object, "codecFrameLength", value);
730 }
731 }
732
ConvertCodecType(napi_env env,napi_value & object,int32_t codecType)733 static void ConvertCodecType(napi_env env, napi_value &object, int32_t codecType)
734 {
735 auto iter = g_a2dpCodecTypeMap.find(codecType);
736 int codecType_ = -1;
737 if (iter != g_a2dpCodecTypeMap.end()) {
738 codecType_ = iter->second;
739 } else {
740 HILOGE("not find valid codec type");
741 }
742 napi_value value = nullptr;
743 napi_create_int32(env, codecType_, &value);
744 napi_set_named_property(env, object, "codecType", value);
745 }
746
ConvertCodecBitsPerSampleVector(napi_env env,napi_value & object,int32_t codecSampleRate)747 static void ConvertCodecBitsPerSampleVector(napi_env env, napi_value &object, int32_t codecSampleRate)
748 {
749 int count = 0;
750 napi_value value = nullptr;
751 napi_value codecBitsPerSampleArray = nullptr;
752 napi_create_array(env, &codecBitsPerSampleArray);
753
754 if (codecSampleRate == A2dpUserCodecBitsPerSample::A2DP_SAMPLE_BITS_NONE_USER) {
755 napi_create_int32(env, CODEC_BITS_PER_SAMPLE_NONE, &value);
756 napi_set_element(env, codecBitsPerSampleArray, count, value);
757 count++;
758 }
759 if (static_cast<uint8_t>(codecSampleRate) & A2dpUserCodecBitsPerSample::A2DP_SAMPLE_BITS_32_USER) {
760 napi_create_int32(env, CODEC_BITS_PER_SAMPLE_32, &value);
761 napi_set_element(env, codecBitsPerSampleArray, count, value);
762 count++;
763 }
764 if (static_cast<uint8_t>(codecSampleRate) & A2dpUserCodecBitsPerSample::A2DP_SAMPLE_BITS_24_USER) {
765 napi_create_int32(env, CODEC_BITS_PER_SAMPLE_24, &value);
766 napi_set_element(env, codecBitsPerSampleArray, count, value);
767 count++;
768 }
769 if (static_cast<uint8_t>(codecSampleRate) & A2dpUserCodecBitsPerSample::A2DP_SAMPLE_BITS_16_USER) {
770 napi_create_int32(env, CODEC_BITS_PER_SAMPLE_16, &value);
771 napi_set_element(env, codecBitsPerSampleArray, count, value);
772 count++;
773 }
774
775 napi_set_named_property(env, object, "codecBitsPerSampleArray", codecBitsPerSampleArray);
776 }
777
ConvertCodecChannelModeVector(napi_env env,napi_value & object,int32_t channelMode)778 static void ConvertCodecChannelModeVector(napi_env env, napi_value &object, int32_t channelMode)
779 {
780 int count = 0;
781 napi_value value = nullptr;
782 napi_value codecChannelModeArray = nullptr;
783 napi_create_array(env, &codecChannelModeArray);
784 if (channelMode == A2dpUserCodecChannelMode::A2DP_CHANNEL_MODE_NONE_USER) {
785 napi_create_int32(env, CODEC_CHANNEL_MODE_NONE, &value);
786 napi_set_element(env, codecChannelModeArray, count, value);
787 count++;
788 }
789 if (static_cast<uint8_t>(channelMode) & A2dpUserCodecChannelMode::A2DP_SBC_CHANNEL_MODE_MONO_STEREO_USER) {
790 napi_create_int32(env, CODEC_CHANNEL_MODE_STEREO, &value);
791 napi_set_element(env, codecChannelModeArray, count, value);
792 count++;
793 }
794 if (static_cast<uint8_t>(channelMode) & A2dpUserCodecChannelMode::A2DP_SBC_CHANNEL_MODE_MONO_USER) {
795 napi_create_int32(env, CODEC_CHANNEL_MODE_MONO, &value);
796 napi_set_element(env, codecChannelModeArray, count, value);
797 count++;
798 }
799
800 napi_set_named_property(env, object, "codecChannelModeArray", codecChannelModeArray);
801 }
802
ConvertCodecSampleRateVector(napi_env env,napi_value & object,int32_t codecSampleRate)803 static void ConvertCodecSampleRateVector(napi_env env, napi_value &object, int32_t codecSampleRate)
804 {
805 int count = 0;
806 napi_value value = nullptr;
807 napi_value codecSampleRateArray = nullptr;
808 napi_create_array(env, &codecSampleRateArray);
809 if (codecSampleRate == A2dpUserCodecSampleRate::A2DP_SAMPLE_RATE_NONE_USER) {
810 napi_create_int32(env, CODEC_SAMPLE_RATE_NONE, &value);
811 napi_set_element(env, codecSampleRateArray, count, value);
812 count++;
813 }
814 if (static_cast<uint32_t>(codecSampleRate) & A2dpUserCodecSampleRate::A2DP_L2HCV2_SAMPLE_RATE_96000_USER) {
815 napi_create_int32(env, CODEC_SAMPLE_RATE_96000, &value);
816 napi_set_element(env, codecSampleRateArray, count, value);
817 count++;
818 }
819 if (static_cast<uint32_t>(codecSampleRate) & A2dpUserCodecSampleRate::A2DP_L2HCV2_SAMPLE_RATE_48000_USER) {
820 napi_create_int32(env, CODEC_SAMPLE_RATE_48000, &value);
821 napi_set_element(env, codecSampleRateArray, count, value);
822 count++;
823 }
824 if (static_cast<uint32_t>(codecSampleRate) & A2dpUserCodecSampleRate::A2DP_SBC_SAMPLE_RATE_44100_USER) {
825 napi_create_int32(env, CODEC_SAMPLE_RATE_44100, &value);
826 napi_set_element(env, codecSampleRateArray, count, value);
827 count++;
828 }
829
830 napi_set_named_property(env, object, "codecSampleRateArray", codecSampleRateArray);
831 }
832
ConvertL2hcV2CodecBitRateVector(napi_env env,napi_value & object,int32_t codecBitRate)833 static void ConvertL2hcV2CodecBitRateVector(napi_env env, napi_value &object, int32_t codecBitRate)
834 {
835 int count = 0;
836 napi_value value = nullptr;
837 napi_value codecBitRateArray = nullptr;
838 napi_create_array(env, &codecBitRateArray);
839 if (static_cast<uint32_t>(codecBitRate) & A2dpUserL2hcV2CodecBitRate::A2DP_L2HCV2_BIT_RATE_AUTO_RATE) {
840 napi_create_int32(env, CODEC_BIT_RATE_ABR, &value);
841 napi_set_element(env, codecBitRateArray, count, value);
842 count++;
843 }
844 if (static_cast<uint32_t>(codecBitRate) & A2dpUserL2hcV2CodecBitRate::A2DP_L2HCV2_BIT_RATE_320K) {
845 napi_create_int32(env, CODEC_BIT_RATE_320000, &value);
846 napi_set_element(env, codecBitRateArray, count, value);
847 count++;
848 }
849 if (static_cast<uint32_t>(codecBitRate) & A2dpUserL2hcV2CodecBitRate::A2DP_L2HCV2_BIT_RATE_640K) {
850 napi_create_int32(env, CODEC_BIT_RATE_640000, &value);
851 napi_set_element(env, codecBitRateArray, count, value);
852 count++;
853 }
854 if (static_cast<uint32_t>(codecBitRate) & A2dpUserL2hcV2CodecBitRate::A2DP_L2HCV2_BIT_RATE_960K) {
855 napi_create_int32(env, CODEC_BIT_RATE_960000, &value);
856 napi_set_element(env, codecBitRateArray, count, value);
857 count++;
858 }
859 if (static_cast<uint32_t>(codecBitRate) & A2dpUserL2hcV2CodecBitRate::A2DP_L2HCV2_BIT_RATE_1500K) {
860 napi_create_int32(env, CODEC_BIT_RATE_1500000, &value);
861 napi_set_element(env, codecBitRateArray, count, value);
862 count++;
863 }
864 if (static_cast<uint32_t>(codecBitRate) & A2dpUserL2hcV2CodecBitRate::A2DP_L2HCV2_BIT_RATE_2300K) {
865 napi_create_int32(env, CODEC_BIT_RATE_2300000, &value);
866 napi_set_element(env, codecBitRateArray, count, value);
867 count++;
868 }
869 napi_set_named_property(env, object, "codecBitRateArray", codecBitRateArray);
870 }
871
ConvertL2hcStCodecBitRateVector(napi_env env,napi_value & object,int32_t codecBitRate)872 static void ConvertL2hcStCodecBitRateVector(napi_env env, napi_value &object, int32_t codecBitRate)
873 {
874 int count = 0;
875 napi_value value = nullptr;
876 napi_value codecBitRateArray = nullptr;
877 napi_create_array(env, &codecBitRateArray);
878 if (static_cast<uint32_t>(codecBitRate) & A2dpUserL2hcStCodecBitRate::A2DP_L2HCST_BIT_RATE_AUTO_RATE) {
879 napi_create_int32(env, CODEC_BIT_RATE_ABR, &value);
880 napi_set_element(env, codecBitRateArray, count, value);
881 count++;
882 }
883 if (static_cast<uint32_t>(codecBitRate) & A2dpUserL2hcStCodecBitRate::A2DP_L2HCST_BIT_RATE_96K) {
884 napi_create_int32(env, CODEC_BIT_RATE_96000, &value);
885 napi_set_element(env, codecBitRateArray, count, value);
886 count++;
887 }
888 if (static_cast<uint32_t>(codecBitRate) & A2dpUserL2hcStCodecBitRate::A2DP_L2HCST_BIT_RATE_192K) {
889 napi_create_int32(env, CODEC_BIT_RATE_192000, &value);
890 napi_set_element(env, codecBitRateArray, count, value);
891 count++;
892 }
893 if (static_cast<uint32_t>(codecBitRate) & A2dpUserL2hcStCodecBitRate::A2DP_L2HCST_BIT_RATE_256K) {
894 napi_create_int32(env, CODEC_BIT_RATE_256000, &value);
895 napi_set_element(env, codecBitRateArray, count, value);
896 count++;
897 }
898 if (static_cast<uint32_t>(codecBitRate) & A2dpUserL2hcStCodecBitRate::A2DP_L2HCST_BIT_RATE_320K) {
899 napi_create_int32(env, CODEC_BIT_RATE_320000, &value);
900 napi_set_element(env, codecBitRateArray, count, value);
901 count++;
902 }
903 if (static_cast<uint32_t>(codecBitRate) & A2dpUserL2hcStCodecBitRate::A2DP_L2HCST_BIT_RATE_480K) {
904 napi_create_int32(env, CODEC_BIT_RATE_480000, &value);
905 napi_set_element(env, codecBitRateArray, count, value);
906 count++;
907 }
908 if (static_cast<uint32_t>(codecBitRate) & A2dpUserL2hcStCodecBitRate::A2DP_L2HCST_BIT_RATE_640K) {
909 napi_create_int32(env, CODEC_BIT_RATE_640000, &value);
910 napi_set_element(env, codecBitRateArray, count, value);
911 count++;
912 }
913 if (static_cast<uint32_t>(codecBitRate) & A2dpUserL2hcStCodecBitRate::A2DP_L2HCST_BIT_RATE_960K) {
914 napi_create_int32(env, CODEC_BIT_RATE_960000, &value);
915 napi_set_element(env, codecBitRateArray, count, value);
916 count++;
917 }
918 napi_set_named_property(env, object, "codecBitRateArray", codecBitRateArray);
919 }
920
ConvertCodecFrameLengthVector(napi_env env,napi_value & object,int32_t codecSampleRate)921 static void ConvertCodecFrameLengthVector(napi_env env, napi_value &object, int32_t codecSampleRate)
922 {
923 napi_value codecFrameLengthArray = nullptr;
924 napi_create_array(env, &codecFrameLengthArray);
925 int count = 0;
926 napi_value value = nullptr;
927 napi_create_int32(env, CODEC_FRAME_LENGTH_10MS, &value); // only 10ms frame length is supported
928 napi_set_element(env, codecFrameLengthArray, count, value);
929 napi_set_named_property(env, object, "codecFrameLengthArray", codecFrameLengthArray);
930 }
931
ConvertCodecInfoListToJS(napi_env env,napi_value & object,const A2dpCodecInfo & a2dpCodecInfo)932 static void ConvertCodecInfoListToJS(napi_env env, napi_value &object, const A2dpCodecInfo &a2dpCodecInfo)
933 {
934 ConvertCodecType(env, object, a2dpCodecInfo.codecType);
935 ConvertCodecBitsPerSampleVector(env, object, a2dpCodecInfo.bitsPerSample);
936 ConvertCodecChannelModeVector(env, object, a2dpCodecInfo.channelMode);
937 ConvertCodecSampleRateVector(env, object, a2dpCodecInfo.sampleRate);
938 if (a2dpCodecInfo.codecType == A2DP_CODEC_TYPE_L2HCST_USER) {
939 ConvertL2hcStCodecBitRateVector(env, object, a2dpCodecInfo.codecSpecific3);
940 } else if (a2dpCodecInfo.codecType == A2DP_CODEC_TYPE_L2HCV2_USER) {
941 ConvertL2hcV2CodecBitRateVector(env, object, a2dpCodecInfo.codecSpecific3);
942 }
943 if (a2dpCodecInfo.codecType == A2DP_CODEC_TYPE_L2HCST_USER ||
944 a2dpCodecInfo.codecType == A2DP_CODEC_TYPE_L2HCV2_USER) {
945 ConvertCodecFrameLengthVector(env, object, a2dpCodecInfo.codecSpecific2);
946 }
947 }
948
ConvertCodecInfoConfirmedCapToJs(napi_env env,napi_value & object,const std::vector<A2dpCodecInfo> & codecInfoConfirmedCap)949 static void ConvertCodecInfoConfirmedCapToJs(napi_env env, napi_value &object,
950 const std::vector<A2dpCodecInfo> &codecInfoConfirmedCap)
951 {
952 size_t count = 0;
953 for (auto &iter : codecInfoConfirmedCap) {
954 napi_value temp = nullptr;
955 napi_create_object(env, &temp);
956 ConvertCodecInfoListToJS(env, temp, iter);
957 napi_set_element(env, object, count, temp);
958 count++;
959 }
960 }
961
CheckSetCodecPreferenceParam(napi_env env,napi_callback_info info,std::string & addr,A2dpCodecInfo & a2dpCodecInfo)962 static napi_status CheckSetCodecPreferenceParam(napi_env env, napi_callback_info info,
963 std::string &addr, A2dpCodecInfo &a2dpCodecInfo)
964 {
965 size_t argc = ARGS_SIZE_TWO;
966 napi_value argv[ARGS_SIZE_TWO] = {nullptr};
967 NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
968 NAPI_BT_RETURN_IF(argc != ARGS_SIZE_TWO, "Requires 2 arguments.", napi_invalid_arg);
969 NAPI_BT_CALL_RETURN(NapiParseBdAddr(env, argv[PARAM0], addr));
970 NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, argv[PARAM1], {"codecType",
971 "codecBitsPerSample", "codecChannelMode", "codecSampleRate", "codecBitRate", "codecFrameLength"}));
972 // parse codecInfo
973 int32_t codecType = 0;
974 NAPI_BT_CALL_RETURN(NapiParseObjectInt32(env, argv[PARAM1], "codecType", codecType));
975 ConvertCodecType(a2dpCodecInfo, codecType);
976 int32_t codecBitsPerSample = 0;
977 NAPI_BT_CALL_RETURN(NapiParseObjectInt32(env, argv[PARAM1], "codecBitsPerSample", codecBitsPerSample));
978 ConvertCodecBitsPerSample(a2dpCodecInfo, codecBitsPerSample);
979 int32_t codecChannelMode = 0;
980 NAPI_BT_CALL_RETURN(NapiParseObjectInt32(env, argv[PARAM1], "codecChannelMode", codecChannelMode));
981 ConvertCodecChannelMode(a2dpCodecInfo, codecChannelMode);
982 int32_t codecSampleRate = 0;
983 NAPI_BT_CALL_RETURN(NapiParseObjectInt32(env, argv[PARAM1], "codecSampleRate", codecSampleRate));
984 ConvertCodecSampleRate(a2dpCodecInfo, codecSampleRate);
985 if (NapiIsObjectPropertyExist(env, argv[PARAM1], "codecBitRate")) {
986 int32_t codecBitRate = 0;
987 NAPI_BT_CALL_RETURN(NapiParseObjectInt32(env, argv[PARAM1], "codecBitRate", codecBitRate));
988 if (a2dpCodecInfo.codecType == A2DP_CODEC_TYPE_L2HCST_USER) {
989 ConvertL2hcStCodecBitRate(a2dpCodecInfo, codecBitRate);
990 } else if (a2dpCodecInfo.codecType == A2DP_CODEC_TYPE_L2HCV2_USER) {
991 ConvertL2hcV2BitRate(a2dpCodecInfo, codecBitRate);
992 }
993 }
994 return napi_ok;
995 }
996
SetCurrentCodecInfo(napi_env env,napi_callback_info info)997 napi_value NapiA2dpSource::SetCurrentCodecInfo(napi_env env, napi_callback_info info)
998 {
999 std::string remoteAddr{};
1000 A2dpCodecInfo a2dpCodecInfo;
1001 auto status = CheckSetCodecPreferenceParam(env, info, remoteAddr, a2dpCodecInfo);
1002 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
1003 BluetoothRemoteDevice remoteDevice(remoteAddr, BT_TRANSPORT_BREDR);
1004 A2dpSource *profile = A2dpSource::GetProfile();
1005 int32_t errorCode = profile->SetCodecPreference(remoteDevice, a2dpCodecInfo);
1006 HILOGI("err: %{public}d", errorCode);
1007 NAPI_BT_ASSERT_RETURN_FALSE(env, errorCode == BT_NO_ERROR, errorCode);
1008 return NapiGetBooleanTrue(env);
1009 }
1010
GetCurrentCodecInfo(napi_env env,napi_callback_info info)1011 napi_value NapiA2dpSource::GetCurrentCodecInfo(napi_env env, napi_callback_info info)
1012 {
1013 HILOGI("start");
1014 napi_value ret = nullptr;
1015 napi_create_object(env, &ret);
1016
1017 std::string remoteAddr{};
1018 bool checkRet = CheckDeivceIdParam(env, info, remoteAddr);
1019 NAPI_BT_ASSERT_RETURN(env, checkRet, BT_ERR_INVALID_PARAM, ret);
1020 A2dpCodecInfo a2dpCodecInfo;
1021 int transport = BT_TRANSPORT_BREDR;
1022 BluetoothRemoteDevice remoteDevice = BluetoothRemoteDevice(remoteAddr, transport);
1023 A2dpSource *profile = A2dpSource::GetProfile();
1024 int errorCode = profile->GetCodecPreference(remoteDevice, a2dpCodecInfo);
1025 NAPI_BT_ASSERT_RETURN(env, (errorCode == BT_NO_ERROR), errorCode, ret);
1026 ConvertCodecInfoToJs(env, ret, a2dpCodecInfo);
1027 return ret;
1028 }
1029
GetCurrentFullCodecInfo(napi_env env,napi_callback_info info)1030 napi_value NapiA2dpSource::GetCurrentFullCodecInfo(napi_env env, napi_callback_info info)
1031 {
1032 HILOGI("start");
1033 napi_value ret = nullptr;
1034 napi_create_array(env, &ret);
1035
1036 std::string remoteAddr{};
1037 bool checkRet = CheckDeivceIdParam(env, info, remoteAddr);
1038 NAPI_BT_ASSERT_RETURN(env, checkRet, BT_ERR_INVALID_PARAM, ret);
1039 A2dpCodecStatus a2dpCodecStatus;
1040 int transport = BT_TRANSPORT_BREDR;
1041 BluetoothRemoteDevice remoteDevice = BluetoothRemoteDevice(remoteAddr, transport);
1042 A2dpSource *profile = A2dpSource::GetProfile();
1043 a2dpCodecStatus = profile->GetCodecStatus(remoteDevice);
1044 ConvertCodecInfoConfirmedCapToJs(env, ret, a2dpCodecStatus.codecInfoConfirmedCap);
1045 return ret;
1046 }
1047
EnableAutoPlay(napi_env env,napi_callback_info info)1048 napi_value NapiA2dpSource::EnableAutoPlay(napi_env env, napi_callback_info info)
1049 {
1050 std::string deviceId = INVALID_MAC_ADDRESS;
1051 auto status = CheckDeivceIdParam(env, info, deviceId);
1052 NAPI_BT_ASSERT_RETURN_UNDEF(env, status, BT_ERR_INVALID_PARAM);
1053
1054 auto func = [deviceId]() {
1055 BluetoothRemoteDevice device(deviceId, BT_TRANSPORT_BREDR);
1056 A2dpSource *profile = A2dpSource::GetProfile();
1057 int err = profile->EnableAutoPlay(device);
1058 HILOGI("err: %{public}d", err);
1059 return NapiAsyncWorkRet(err);
1060 };
1061 auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NO_NEED_CALLBACK);
1062 NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
1063 asyncWork->Run();
1064 return asyncWork->GetRet();
1065 }
1066
IsInvalidAutoPlayDuration(int32_t duration)1067 static bool IsInvalidAutoPlayDuration(int32_t duration)
1068 {
1069 return duration < MIN_AUTO_PLAY_DURATION_SEC
1070 || duration> MAX_AUTO_PLAY_DURATION_SEC;
1071 }
1072
CheckDisableAutoPlayParam(napi_env env,napi_callback_info info,std::string & addr,int32_t & duration)1073 static napi_status CheckDisableAutoPlayParam(napi_env env, napi_callback_info info, std::string &addr,
1074 int32_t &duration)
1075 {
1076 size_t argc = ARGS_SIZE_TWO;
1077 napi_value argv[ARGS_SIZE_TWO] = {nullptr};
1078 NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
1079 NAPI_BT_RETURN_IF(argc != ARGS_SIZE_TWO, "Requires 2 arguments", napi_invalid_arg);
1080 NAPI_BT_CALL_RETURN(NapiParseBdAddr(env, argv[PARAM0], addr));
1081 NAPI_BT_RETURN_IF(!ParseInt32(env, duration, argv[PARAM1]), "ParseInt failed", napi_invalid_arg);
1082 NAPI_BT_RETURN_IF(IsInvalidAutoPlayDuration(duration), "Invalid duration", napi_invalid_arg);
1083 return napi_ok;
1084 }
1085
DisableAutoPlay(napi_env env,napi_callback_info info)1086 napi_value NapiA2dpSource::DisableAutoPlay(napi_env env, napi_callback_info info)
1087 {
1088 std::string deviceId = INVALID_MAC_ADDRESS;
1089 int duration = 0;
1090 auto status = CheckDisableAutoPlayParam(env, info, deviceId, duration);
1091 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
1092
1093 auto func = [deviceId, duration]() {
1094 BluetoothRemoteDevice device(deviceId, BT_TRANSPORT_BREDR);
1095 A2dpSource *profile = A2dpSource::GetProfile();
1096 int err = profile->DisableAutoPlay(device, duration);
1097 HILOGI("err: %{public}d", err);
1098 return NapiAsyncWorkRet(err);
1099 };
1100 auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NO_NEED_CALLBACK);
1101 NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
1102 asyncWork->Run();
1103 return asyncWork->GetRet();
1104 }
1105
GetAutoPlayDisabledDuration(napi_env env,napi_callback_info info)1106 napi_value NapiA2dpSource::GetAutoPlayDisabledDuration(napi_env env, napi_callback_info info)
1107 {
1108 std::string deviceId = INVALID_MAC_ADDRESS;
1109 auto status = CheckDeivceIdParam(env, info, deviceId);
1110 NAPI_BT_ASSERT_RETURN_UNDEF(env, status, BT_ERR_INVALID_PARAM);
1111
1112 auto func = [deviceId]() {
1113 int duration = 0;
1114 BluetoothRemoteDevice device(deviceId, BT_TRANSPORT_BREDR);
1115 A2dpSource *profile = A2dpSource::GetProfile();
1116 int err = profile->GetAutoPlayDisabledDuration(device, duration);
1117 HILOGI("err: %{public}d, duration: %{public}d", err, duration);
1118 auto object = std::make_shared<NapiNativeInt>(duration);
1119 return NapiAsyncWorkRet(err, object);
1120 };
1121 auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NO_NEED_CALLBACK);
1122 NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
1123 asyncWork->Run();
1124 return asyncWork->GetRet();
1125 }
1126 #endif
1127 } // namespace Bluetooth
1128 } // namespace OHOS