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_codecTypeMap = {
41 {CODEC_TYPE_SBC, A2DP_CODEC_TYPE_SBC_USER},
42 {CODEC_TYPE_AAC, A2DP_CODEC_TYPE_AAC_USER},
43 {CODEC_TYPE_L2HC, A2DP_CODEC_TYPE_L2HCV2_USER},
44 {CODEC_TYPE_L2HCST, A2DP_CODEC_TYPE_L2HCST_USER},
45 {CODEC_TYPE_LDAC, A2DP_CODEC_TYPE_LDAC_USER},
46 {CODEC_TYPE_INVALID, A2DP_CODEC_TYPE_NONA2DP_USER},
47 };
48
49 const static std::map<int32_t, int32_t> g_codecBitsPerSampleMap = {
50 {CODEC_BITS_PER_SAMPLE_NONE, A2DP_SAMPLE_BITS_NONE_USER},
51 {CODEC_BITS_PER_SAMPLE_16, A2DP_SAMPLE_BITS_16_USER},
52 {CODEC_BITS_PER_SAMPLE_24, A2DP_SAMPLE_BITS_24_USER},
53 {CODEC_BITS_PER_SAMPLE_32, A2DP_SAMPLE_BITS_32_USER},
54 };
55
56 const static std::map<int32_t, int32_t> g_codecChannelModeMap = {
57 {CODEC_CHANNEL_MODE_NONE, A2DP_CHANNEL_MODE_NONE_USER},
58 {CODEC_CHANNEL_MODE_MONO, A2DP_SBC_CHANNEL_MODE_MONO_USER},
59 {CODEC_CHANNEL_MODE_STEREO, A2DP_SBC_CHANNEL_MODE_STEREO_USER},
60 };
61
62 const static std::map<int32_t, int32_t> g_codecSampleRateMap = {
63 {CODEC_SAMPLE_RATE_NONE, A2DP_SAMPLE_RATE_NONE_USER},
64 {CODEC_SAMPLE_RATE_44100, A2DP_SBC_SAMPLE_RATE_44100_USER},
65 {CODEC_SAMPLE_RATE_48000, A2DP_L2HCV2_SAMPLE_RATE_48000_USER},
66 {CODEC_SAMPLE_RATE_88200, A2DP_SAMPLE_RATE_NONE_USER},
67 {CODEC_SAMPLE_RATE_96000, A2DP_L2HCV2_SAMPLE_RATE_96000_USER},
68 {CODEC_SAMPLE_RATE_176400, A2DP_SAMPLE_RATE_NONE_USER},
69 {CODEC_SAMPLE_RATE_192000, A2DP_SAMPLE_RATE_NONE_USER},
70 };
71
72 const static std::map<int32_t, CodecType> g_a2dpCodecTypeMap = {
73 {A2DP_CODEC_TYPE_SBC_USER, CODEC_TYPE_SBC},
74 {A2DP_CODEC_TYPE_AAC_USER, CODEC_TYPE_AAC},
75 {A2DP_CODEC_TYPE_L2HCV2_USER, CODEC_TYPE_L2HC},
76 {A2DP_CODEC_TYPE_L2HCST_USER, CODEC_TYPE_L2HCST},
77 {A2DP_CODEC_TYPE_LDAC_USER, CODEC_TYPE_LDAC},
78 {A2DP_CODEC_TYPE_NONA2DP_USER, CODEC_TYPE_INVALID},
79 };
80
81 const static std::map<int32_t, CodecBitsPerSample> g_a2dpCodecBitsPerSampleMap = {
82 {A2DP_SAMPLE_BITS_NONE_USER, CODEC_BITS_PER_SAMPLE_NONE},
83 {A2DP_SAMPLE_BITS_16_USER, CODEC_BITS_PER_SAMPLE_16},
84 {A2DP_SAMPLE_BITS_24_USER, CODEC_BITS_PER_SAMPLE_24},
85 {A2DP_SAMPLE_BITS_32_USER, CODEC_BITS_PER_SAMPLE_32},
86 };
87
88 const static std::map<int32_t, CodecChannelMode> g_a2dpCodecChannelModeMap = {
89 {A2DP_CHANNEL_MODE_NONE_USER, CODEC_CHANNEL_MODE_NONE},
90 {A2DP_SBC_CHANNEL_MODE_MONO_USER, CODEC_CHANNEL_MODE_MONO},
91 {A2DP_SBC_CHANNEL_MODE_STEREO_USER, CODEC_CHANNEL_MODE_STEREO},
92 };
93
94 const static std::map<int32_t, CodecSampleRate> g_a2dpCodecSampleRateMap = {
95 {A2DP_SAMPLE_RATE_NONE_USER, CODEC_SAMPLE_RATE_NONE},
96 {A2DP_SBC_SAMPLE_RATE_44100_USER, CODEC_SAMPLE_RATE_44100},
97 {A2DP_SBC_SAMPLE_RATE_48000_USER, CODEC_SAMPLE_RATE_48000},
98 {A2DP_L2HCV2_SAMPLE_RATE_48000_USER, CODEC_SAMPLE_RATE_48000},
99 {A2DP_L2HCV2_SAMPLE_RATE_96000_USER, CODEC_SAMPLE_RATE_96000},
100 };
101
DefineA2dpSourceJSClass(napi_env env,napi_value exports)102 napi_value NapiA2dpSource::DefineA2dpSourceJSClass(napi_env env, napi_value exports)
103 {
104 A2dpPropertyValueInit(env, exports);
105 napi_property_descriptor properties[] = {
106 DECLARE_NAPI_FUNCTION("on", On),
107 DECLARE_NAPI_FUNCTION("off", Off),
108 DECLARE_NAPI_FUNCTION("connect", Connect),
109 DECLARE_NAPI_FUNCTION("disconnect", Disconnect),
110 DECLARE_NAPI_FUNCTION("getPlayingState", GetPlayingState),
111 #ifndef BLUETOOTH_API_SINCE_10
112 DECLARE_NAPI_FUNCTION("getConnectionDevices", GetConnectionDevices),
113 DECLARE_NAPI_FUNCTION("getDeviceState", GetDeviceState),
114 #endif
115 #ifdef BLUETOOTH_API_SINCE_10
116 DECLARE_NAPI_FUNCTION("setConnectionStrategy", SetConnectionStrategy),
117 DECLARE_NAPI_FUNCTION("getConnectionStrategy", GetConnectionStrategy),
118 DECLARE_NAPI_FUNCTION("getConnectionState", GetConnectionState),
119 DECLARE_NAPI_FUNCTION("getConnectedDevices", GetConnectedDevices),
120 DECLARE_NAPI_FUNCTION("isAbsoluteVolumeSupported", IsAbsoluteVolumeSupported),
121 DECLARE_NAPI_FUNCTION("isAbsoluteVolumeEnabled", IsAbsoluteVolumeEnabled),
122 DECLARE_NAPI_FUNCTION("enableAbsoluteVolume", EnableAbsoluteVolume),
123 DECLARE_NAPI_FUNCTION("disableAbsoluteVolume", DisableAbsoluteVolume),
124 DECLARE_NAPI_FUNCTION("setCurrentCodecInfo", SetCurrentCodecInfo),
125 DECLARE_NAPI_FUNCTION("getCurrentCodecInfo", GetCurrentCodecInfo),
126 DECLARE_NAPI_FUNCTION("enableAutoPlay", EnableAutoPlay),
127 DECLARE_NAPI_FUNCTION("disableAutoPlay", DisableAutoPlay),
128 DECLARE_NAPI_FUNCTION("getAutoPlayDisabledDuration", GetAutoPlayDisabledDuration),
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
A2dpPropertyValueInit(napi_env env,napi_value exports)307 napi_value NapiA2dpSource::A2dpPropertyValueInit(napi_env env, napi_value exports)
308 {
309 napi_value playingStateObj = PlayingStateInit(env);
310 napi_value codecTypeObj = CodecTypeInit(env);
311 napi_value codecBitsPerSampleObj = CodecBitsPerSampleInit(env);
312 napi_value codecChannelModeObj = CodecChannelModeInit(env);
313 napi_value codecSampleRateObj = CodecSampleRateInit(env);
314 napi_property_descriptor exportProps[] = {
315 DECLARE_NAPI_PROPERTY("PlayingState", playingStateObj),
316 DECLARE_NAPI_PROPERTY("CodecType", codecTypeObj),
317 DECLARE_NAPI_PROPERTY("CodecBitsPerSample", codecBitsPerSampleObj),
318 DECLARE_NAPI_PROPERTY("CodecChannelMode", codecChannelModeObj),
319 DECLARE_NAPI_PROPERTY("CodecSampleRate", codecSampleRateObj),
320 };
321 HITRACE_METER_NAME(HITRACE_TAG_OHOS, "a2dp_src:napi_define_properties");
322 napi_define_properties(env, exports, sizeof(exportProps) / sizeof(*exportProps), exportProps);
323 return exports;
324 }
325
GetConnectionDevices(napi_env env,napi_callback_info info)326 napi_value NapiA2dpSource::GetConnectionDevices(napi_env env, napi_callback_info info)
327 {
328 HILOGI("enter");
329 napi_value ret = nullptr;
330 napi_create_array(env, &ret);
331 A2dpSource *profile = A2dpSource::GetProfile();
332 vector<int> states;
333 states.push_back(1);
334 vector<BluetoothRemoteDevice> devices;
335 int errorCode = profile->GetDevicesByStates(states, devices);
336 NAPI_BT_ASSERT_RETURN(env, (errorCode == BT_NO_ERROR), errorCode, ret);
337
338 vector<string> deviceVector;
339 for (auto &device : devices) {
340 deviceVector.push_back(device.GetDeviceAddr());
341 }
342 ConvertStringVectorToJS(env, ret, deviceVector);
343 return ret;
344 }
345
GetDeviceState(napi_env env,napi_callback_info info)346 napi_value NapiA2dpSource::GetDeviceState(napi_env env, napi_callback_info info)
347 {
348 HILOGD("enter");
349
350 size_t expectedArgsCount = ARGS_SIZE_ONE;
351 size_t argc = expectedArgsCount;
352 napi_value argv[ARGS_SIZE_ONE] = {0};
353 napi_value thisVar = nullptr;
354
355 napi_value ret = nullptr;
356 napi_get_undefined(env, &ret);
357
358 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
359 if (argc != expectedArgsCount) {
360 HILOGE("Requires 1 argument.");
361 return ret;
362 }
363 string deviceId;
364 if (!ParseString(env, deviceId, argv[PARAM0])) {
365 HILOGE("string expected.");
366 return ret;
367 }
368
369 A2dpSource *profile = A2dpSource::GetProfile();
370 BluetoothRemoteDevice device(deviceId, 1);
371
372 int32_t profileState = ProfileConnectionState::STATE_DISCONNECTED;
373 if (napi_create_int32(env, profileState, &ret) != napi_ok) {
374 HILOGE("napi_create_int32 failed.");
375 }
376
377 int btConnectState = static_cast<int32_t>(BTConnectState::DISCONNECTED);
378 int errorCode = profile->GetDeviceState(device, btConnectState);
379 NAPI_BT_ASSERT_RETURN(env, (errorCode == BT_NO_ERROR), errorCode, ret);
380
381 napi_value result = nullptr;
382 int status = GetProfileConnectionState(btConnectState);
383 napi_create_int32(env, status, &result);
384 HILOGD("status: %{public}d", status);
385 return result;
386 }
387
388 #ifdef BLUETOOTH_API_SINCE_10
DefineCreateProfile(napi_env env,napi_value exports)389 napi_value NapiA2dpSource::DefineCreateProfile(napi_env env, napi_value exports)
390 {
391 napi_property_descriptor properties[] = {
392 DECLARE_NAPI_FUNCTION("createA2dpSrcProfile", CreateA2dpSrcProfile),
393 };
394 HITRACE_METER_NAME(HITRACE_TAG_OHOS, "a2dp_src:napi_define_properties");
395 napi_define_properties(env, exports, sizeof(properties) / sizeof(properties[0]), properties);
396 return exports;
397 }
398
CreateA2dpSrcProfile(napi_env env,napi_callback_info info)399 napi_value NapiA2dpSource::CreateA2dpSrcProfile(napi_env env, napi_callback_info info)
400 {
401 napi_value profile;
402 napi_value constructor = nullptr;
403 napi_get_reference_value(env, g_napiProfile, &constructor);
404 napi_new_instance(env, constructor, 0, nullptr, &profile);
405 return profile;
406 }
407
SetConnectionStrategy(napi_env env,napi_callback_info info)408 napi_value NapiA2dpSource::SetConnectionStrategy(napi_env env, napi_callback_info info)
409 {
410 HILOGD("start");
411 std::string remoteAddr{};
412 int32_t strategy = 0;
413 auto status = CheckSetConnectStrategyParam(env, info, remoteAddr, strategy);
414 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
415
416 int transport = BT_TRANSPORT_BREDR;
417 auto func = [remoteAddr, transport, strategy]() {
418 BluetoothRemoteDevice remoteDevice(remoteAddr, transport);
419 A2dpSource *profile = A2dpSource::GetProfile();
420 int32_t err = profile->SetConnectStrategy(remoteDevice, strategy);
421 HILOGI("err: %{public}d", err);
422 return NapiAsyncWorkRet(err);
423 };
424 auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NO_NEED_CALLBACK);
425 NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
426 asyncWork->Run();
427 return asyncWork->GetRet();
428 }
429
GetConnectionStrategy(napi_env env,napi_callback_info info)430 napi_value NapiA2dpSource::GetConnectionStrategy(napi_env env, napi_callback_info info)
431 {
432 HILOGD("start");
433 std::string remoteAddr{};
434 auto status = CheckDeviceAddressParam(env, info, remoteAddr);
435 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
436
437 int transport = BT_TRANSPORT_BREDR;
438 auto func = [remoteAddr, transport]() {
439 int strategy = 0;
440 BluetoothRemoteDevice remoteDevice(remoteAddr, transport);
441 A2dpSource *profile = A2dpSource::GetProfile();
442 int32_t err = profile->GetConnectStrategy(remoteDevice, strategy);
443 HILOGD("err: %{public}d, deviceName: %{public}d", err, strategy);
444 auto object = std::make_shared<NapiNativeInt>(strategy);
445 return NapiAsyncWorkRet(err, object);
446 };
447 auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NO_NEED_CALLBACK);
448 NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
449 asyncWork->Run();
450 return asyncWork->GetRet();
451 }
452
GetConnectionState(napi_env env,napi_callback_info info)453 napi_value NapiA2dpSource::GetConnectionState(napi_env env, napi_callback_info info)
454 {
455 return GetDeviceState(env, info);
456 }
GetConnectedDevices(napi_env env,napi_callback_info info)457 napi_value NapiA2dpSource::GetConnectedDevices(napi_env env, napi_callback_info info)
458 {
459 return GetConnectionDevices(env, info);
460 }
461
IsAbsoluteVolumeSupported(napi_env env,napi_callback_info info)462 napi_value NapiA2dpSource::IsAbsoluteVolumeSupported(napi_env env, napi_callback_info info)
463 {
464 HILOGD("start");
465 std::string remoteAddr{};
466 auto status = CheckDeviceAddressParam(env, info, remoteAddr);
467 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
468
469 auto func = [remoteAddr]() {
470 int32_t ability = DeviceAbsVolumeAbility::DEVICE_ABSVOL_UNSUPPORT;
471 BluetoothRemoteDevice remoteDevice(remoteAddr, BT_TRANSPORT_BREDR);
472 int32_t err = AvrcpTarget::GetProfile()->GetDeviceAbsVolumeAbility(remoteDevice, ability);
473 if (ability == DeviceAbsVolumeAbility::DEVICE_ABSVOL_UNSUPPORT) {
474 return NapiAsyncWorkRet(err, std::make_shared<NapiNativeBool>(false));
475 }
476 return NapiAsyncWorkRet(err, std::make_shared<NapiNativeBool>(true));
477 };
478 auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NO_NEED_CALLBACK);
479 NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
480 asyncWork->Run();
481 return asyncWork->GetRet();
482 }
483
IsAbsoluteVolumeEnabled(napi_env env,napi_callback_info info)484 napi_value NapiA2dpSource::IsAbsoluteVolumeEnabled(napi_env env, napi_callback_info info)
485 {
486 HILOGD("start");
487 std::string remoteAddr{};
488 auto status = CheckDeviceAddressParam(env, info, remoteAddr);
489 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
490
491 auto func = [remoteAddr]() {
492 int32_t ability = DeviceAbsVolumeAbility::DEVICE_ABSVOL_UNSUPPORT;
493 BluetoothRemoteDevice remoteDevice(remoteAddr, BT_TRANSPORT_BREDR);
494 int32_t err = AvrcpTarget::GetProfile()->GetDeviceAbsVolumeAbility(remoteDevice, ability);
495 if (ability == DeviceAbsVolumeAbility::DEVICE_ABSVOL_OPEN) {
496 return NapiAsyncWorkRet(err, std::make_shared<NapiNativeBool>(true));
497 }
498 return NapiAsyncWorkRet(err, std::make_shared<NapiNativeBool>(false));
499 };
500 auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NO_NEED_CALLBACK);
501 NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
502 asyncWork->Run();
503 return asyncWork->GetRet();
504 }
505
EnableAbsoluteVolume(napi_env env,napi_callback_info info)506 napi_value NapiA2dpSource::EnableAbsoluteVolume(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_OPEN;
515 BluetoothRemoteDevice remoteDevice(remoteAddr, BT_TRANSPORT_BREDR);
516 int32_t err = AvrcpTarget::GetProfile()->SetDeviceAbsVolumeAbility(remoteDevice, ability);
517 return NapiAsyncWorkRet(err);
518 };
519 auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NO_NEED_CALLBACK);
520 NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
521 asyncWork->Run();
522 return asyncWork->GetRet();
523 }
524
DisableAbsoluteVolume(napi_env env,napi_callback_info info)525 napi_value NapiA2dpSource::DisableAbsoluteVolume(napi_env env, napi_callback_info info)
526 {
527 HILOGD("start");
528 std::string remoteAddr{};
529 auto status = CheckDeviceAddressParam(env, info, remoteAddr);
530 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
531
532 auto func = [remoteAddr]() {
533 int32_t ability = DeviceAbsVolumeAbility::DEVICE_ABSVOL_CLOSE;
534 BluetoothRemoteDevice remoteDevice(remoteAddr, BT_TRANSPORT_BREDR);
535 int32_t err = AvrcpTarget::GetProfile()->SetDeviceAbsVolumeAbility(remoteDevice, ability);
536 return NapiAsyncWorkRet(err);
537 };
538 auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NO_NEED_CALLBACK);
539 NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
540 asyncWork->Run();
541 return asyncWork->GetRet();
542 }
543
ConvertCodecType(A2dpCodecInfo & a2dpCodecInfo,int32_t codecType)544 static void ConvertCodecType(A2dpCodecInfo &a2dpCodecInfo, int32_t codecType)
545 {
546 auto iter = g_codecTypeMap.find(codecType);
547 if (iter != g_codecTypeMap.end()) {
548 a2dpCodecInfo.codecType = iter->second;
549 }
550 }
551
ConvertCodecBitsPerSample(A2dpCodecInfo & a2dpCodecInfo,int32_t codecBitsPerSample)552 static void ConvertCodecBitsPerSample(A2dpCodecInfo &a2dpCodecInfo, int32_t codecBitsPerSample)
553 {
554 auto iter = g_codecBitsPerSampleMap.find(codecBitsPerSample);
555 if (iter != g_codecBitsPerSampleMap.end()) {
556 a2dpCodecInfo.bitsPerSample = iter->second;
557 }
558 }
559
ConvertCodecChannelMode(A2dpCodecInfo & a2dpCodecInfo,int32_t codecChannelMode)560 static void ConvertCodecChannelMode(A2dpCodecInfo &a2dpCodecInfo, int32_t codecChannelMode)
561 {
562 auto iter = g_codecChannelModeMap.find(codecChannelMode);
563 if (iter != g_codecChannelModeMap.end()) {
564 a2dpCodecInfo.channelMode = iter->second;
565 }
566 }
567
ConvertCodecSampleRate(A2dpCodecInfo & a2dpCodecInfo,int32_t codecSampleRate)568 static void ConvertCodecSampleRate(A2dpCodecInfo &a2dpCodecInfo, int32_t codecSampleRate)
569 {
570 auto iter = g_codecSampleRateMap.find(codecSampleRate);
571 if (iter != g_codecSampleRateMap.end()) {
572 a2dpCodecInfo.sampleRate = iter->second;
573 }
574 }
575
ConvertCodecTypeToCodecInfo(CodecInfo & codecInfo,int32_t codecType)576 static void ConvertCodecTypeToCodecInfo(CodecInfo &codecInfo, int32_t codecType)
577 {
578 auto iter = g_a2dpCodecTypeMap.find(codecType);
579 if (iter != g_a2dpCodecTypeMap.end()) {
580 codecInfo.codecType = iter->second;
581 }
582 }
583
ConvertCodecBitsPerSampleToCodecInfo(CodecInfo & codecInfo,int32_t codecBitsPerSample)584 static void ConvertCodecBitsPerSampleToCodecInfo(CodecInfo &codecInfo, int32_t codecBitsPerSample)
585 {
586 auto iter = g_a2dpCodecBitsPerSampleMap.find(codecBitsPerSample);
587 if (iter != g_a2dpCodecBitsPerSampleMap.end()) {
588 codecInfo.codecBitsPerSample = iter->second;
589 }
590 }
591
ConvertCodecChannelModeToCodecInfo(CodecInfo & codecInfo,int32_t codecChannelMode)592 static void ConvertCodecChannelModeToCodecInfo(CodecInfo &codecInfo, int32_t codecChannelMode)
593 {
594 auto iter = g_a2dpCodecChannelModeMap.find(codecChannelMode);
595 if (iter != g_a2dpCodecChannelModeMap.end()) {
596 codecInfo.codecChannelMode = iter->second;
597 }
598 }
599
ConvertCodecSampleRateToCodecInfo(CodecInfo & codecInfo,int32_t codecSampleRate)600 static void ConvertCodecSampleRateToCodecInfo(CodecInfo &codecInfo, int32_t codecSampleRate)
601 {
602 auto iter = g_a2dpCodecSampleRateMap.find(codecSampleRate);
603 if (iter != g_a2dpCodecSampleRateMap.end()) {
604 codecInfo.codecSampleRate = iter->second;
605 }
606 }
607
ConvertCodecInfoToJs(napi_env env,napi_value & object,const A2dpCodecInfo & a2dpCodecInfo)608 static void ConvertCodecInfoToJs(napi_env env, napi_value &object, const A2dpCodecInfo &a2dpCodecInfo)
609 {
610 // convert A2dpCodecInfo to CodecInfo
611 CodecInfo codecInfo;
612 ConvertCodecSampleRateToCodecInfo(codecInfo, a2dpCodecInfo.sampleRate);
613 ConvertCodecChannelModeToCodecInfo(codecInfo, a2dpCodecInfo.channelMode);
614 ConvertCodecBitsPerSampleToCodecInfo(codecInfo, a2dpCodecInfo.bitsPerSample);
615 ConvertCodecTypeToCodecInfo(codecInfo, a2dpCodecInfo.codecType);
616 // convert CodecInfo to JS
617 napi_value value = nullptr;
618 napi_create_int32(env, codecInfo.codecType, &value);
619 napi_set_named_property(env, object, "codecType", value);
620 napi_create_int32(env, codecInfo.codecBitsPerSample, &value);
621 napi_set_named_property(env, object, "codecBitsPerSample", value);
622 napi_create_int32(env, codecInfo.codecChannelMode, &value);
623 napi_set_named_property(env, object, "codecChannelMode", value);
624 napi_create_int32(env, codecInfo.codecSampleRate, &value);
625 napi_set_named_property(env, object, "codecSampleRate", value);
626 }
627
CheckSetCodecPreferenceParam(napi_env env,napi_callback_info info,std::string & addr,A2dpCodecInfo & a2dpCodecInfo)628 static napi_status CheckSetCodecPreferenceParam(napi_env env, napi_callback_info info,
629 std::string &addr, A2dpCodecInfo &a2dpCodecInfo)
630 {
631 size_t argc = ARGS_SIZE_TWO;
632 napi_value argv[ARGS_SIZE_TWO] = {nullptr};
633 NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
634 NAPI_BT_RETURN_IF(argc != ARGS_SIZE_TWO, "Requires 2 arguments.", napi_invalid_arg);
635 NAPI_BT_CALL_RETURN(NapiParseBdAddr(env, argv[PARAM0], addr));
636 NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(
637 env, argv[PARAM1], {"codecType", "codecBitsPerSample", "codecChannelMode", "codecSampleRate"}));
638 // parse codecInfo
639 int32_t codecType = 0;
640 NAPI_BT_CALL_RETURN(NapiParseObjectInt32(env, argv[PARAM1], "codecType", codecType));
641 ConvertCodecType(a2dpCodecInfo, codecType);
642 int32_t codecBitsPerSample = 0;
643 NAPI_BT_CALL_RETURN(NapiParseObjectInt32(env, argv[PARAM1], "codecBitsPerSample", codecBitsPerSample));
644 ConvertCodecBitsPerSample(a2dpCodecInfo, codecBitsPerSample);
645 int32_t codecChannelMode = 0;
646 NAPI_BT_CALL_RETURN(NapiParseObjectInt32(env, argv[PARAM1], "codecChannelMode", codecChannelMode));
647 ConvertCodecChannelMode(a2dpCodecInfo, codecChannelMode);
648 int32_t codecSampleRate = 0;
649 NAPI_BT_CALL_RETURN(NapiParseObjectInt32(env, argv[PARAM1], "codecSampleRate", codecSampleRate));
650 ConvertCodecSampleRate(a2dpCodecInfo, codecSampleRate);
651 return napi_ok;
652 }
653
SetCurrentCodecInfo(napi_env env,napi_callback_info info)654 napi_value NapiA2dpSource::SetCurrentCodecInfo(napi_env env, napi_callback_info info)
655 {
656 std::string remoteAddr{};
657 A2dpCodecInfo a2dpCodecInfo;
658 auto status = CheckSetCodecPreferenceParam(env, info, remoteAddr, a2dpCodecInfo);
659 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
660 BluetoothRemoteDevice remoteDevice(remoteAddr, BT_TRANSPORT_BREDR);
661 A2dpSource *profile = A2dpSource::GetProfile();
662 int32_t errorCode = profile->SetCodecPreference(remoteDevice, a2dpCodecInfo);
663 HILOGI("err: %{public}d", errorCode);
664 NAPI_BT_ASSERT_RETURN_FALSE(env, errorCode == BT_NO_ERROR, errorCode);
665 return NapiGetBooleanTrue(env);
666 }
667
GetCurrentCodecInfo(napi_env env,napi_callback_info info)668 napi_value NapiA2dpSource::GetCurrentCodecInfo(napi_env env, napi_callback_info info)
669 {
670 HILOGI("start");
671 napi_value ret = nullptr;
672 napi_create_object(env, &ret);
673
674 std::string remoteAddr{};
675 bool checkRet = CheckDeivceIdParam(env, info, remoteAddr);
676 NAPI_BT_ASSERT_RETURN(env, checkRet, BT_ERR_INVALID_PARAM, ret);
677 A2dpCodecInfo a2dpCodecInfo;
678 int transport = BT_TRANSPORT_BREDR;
679 BluetoothRemoteDevice remoteDevice = BluetoothRemoteDevice(remoteAddr, transport);
680 A2dpSource *profile = A2dpSource::GetProfile();
681 int errorCode = profile->GetCodecPreference(remoteDevice, a2dpCodecInfo);
682 NAPI_BT_ASSERT_RETURN(env, (errorCode == BT_NO_ERROR), errorCode, ret);
683 ConvertCodecInfoToJs(env, ret, a2dpCodecInfo);
684 return ret;
685 }
686
EnableAutoPlay(napi_env env,napi_callback_info info)687 napi_value NapiA2dpSource::EnableAutoPlay(napi_env env, napi_callback_info info)
688 {
689 std::string deviceId = INVALID_MAC_ADDRESS;
690 auto status = CheckDeivceIdParam(env, info, deviceId);
691 NAPI_BT_ASSERT_RETURN_UNDEF(env, status, BT_ERR_INVALID_PARAM);
692
693 auto func = [deviceId]() {
694 BluetoothRemoteDevice device(deviceId, BT_TRANSPORT_BREDR);
695 A2dpSource *profile = A2dpSource::GetProfile();
696 int err = profile->EnableAutoPlay(device);
697 HILOGI("err: %{public}d", err);
698 return NapiAsyncWorkRet(err);
699 };
700 auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NO_NEED_CALLBACK);
701 NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
702 asyncWork->Run();
703 return asyncWork->GetRet();
704 }
705
IsInvalidAutoPlayDuration(int32_t duration)706 static bool IsInvalidAutoPlayDuration(int32_t duration)
707 {
708 return duration < MIN_AUTO_PLAY_DURATION_SEC
709 || duration> MAX_AUTO_PLAY_DURATION_SEC;
710 }
711
CheckDisableAutoPlayParam(napi_env env,napi_callback_info info,std::string & addr,int32_t & duration)712 static napi_status CheckDisableAutoPlayParam(napi_env env, napi_callback_info info, std::string &addr,
713 int32_t &duration)
714 {
715 size_t argc = ARGS_SIZE_TWO;
716 napi_value argv[ARGS_SIZE_TWO] = {nullptr};
717 NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
718 NAPI_BT_RETURN_IF(argc != ARGS_SIZE_TWO, "Requires 2 arguments", napi_invalid_arg);
719 NAPI_BT_CALL_RETURN(NapiParseBdAddr(env, argv[PARAM0], addr));
720 NAPI_BT_RETURN_IF(!ParseInt32(env, duration, argv[PARAM1]), "ParseInt failed", napi_invalid_arg);
721 NAPI_BT_RETURN_IF(IsInvalidAutoPlayDuration(duration), "Invalid duration", napi_invalid_arg);
722 return napi_ok;
723 }
724
DisableAutoPlay(napi_env env,napi_callback_info info)725 napi_value NapiA2dpSource::DisableAutoPlay(napi_env env, napi_callback_info info)
726 {
727 std::string deviceId = INVALID_MAC_ADDRESS;
728 int duration = 0;
729 auto status = CheckDisableAutoPlayParam(env, info, deviceId, duration);
730 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
731
732 auto func = [deviceId, duration]() {
733 BluetoothRemoteDevice device(deviceId, BT_TRANSPORT_BREDR);
734 A2dpSource *profile = A2dpSource::GetProfile();
735 int err = profile->DisableAutoPlay(device, duration);
736 HILOGI("err: %{public}d", err);
737 return NapiAsyncWorkRet(err);
738 };
739 auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NO_NEED_CALLBACK);
740 NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
741 asyncWork->Run();
742 return asyncWork->GetRet();
743 }
744
GetAutoPlayDisabledDuration(napi_env env,napi_callback_info info)745 napi_value NapiA2dpSource::GetAutoPlayDisabledDuration(napi_env env, napi_callback_info info)
746 {
747 std::string deviceId = INVALID_MAC_ADDRESS;
748 auto status = CheckDeivceIdParam(env, info, deviceId);
749 NAPI_BT_ASSERT_RETURN_UNDEF(env, status, BT_ERR_INVALID_PARAM);
750
751 auto func = [deviceId]() {
752 int duration = 0;
753 BluetoothRemoteDevice device(deviceId, BT_TRANSPORT_BREDR);
754 A2dpSource *profile = A2dpSource::GetProfile();
755 int err = profile->GetAutoPlayDisabledDuration(device, duration);
756 HILOGI("err: %{public}d, duration: %{public}d", err, duration);
757 auto object = std::make_shared<NapiNativeInt>(duration);
758 return NapiAsyncWorkRet(err, object);
759 };
760 auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NO_NEED_CALLBACK);
761 NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
762 asyncWork->Run();
763 return asyncWork->GetRet();
764 }
765 #endif
766 } // namespace Bluetooth
767 } // namespace OHOS