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 #include "bluetooth_a2dp_src.h"
16 #include "bluetooth_avrcp_tg.h"
17 #include "bluetooth_errorcode.h"
18 #include "napi_async_work.h"
19 #include "napi_bluetooth_profile.h"
20 #include "napi_bluetooth_a2dp_src.h"
21 #include "napi_bluetooth_event.h"
22 #include "napi_bluetooth_error.h"
23 #include "napi_bluetooth_host.h"
24 #include "napi_bluetooth_utils.h"
25 #include "../parser/napi_parser_utils.h"
26 #include "hitrace_meter.h"
27
28 namespace OHOS {
29 namespace Bluetooth {
30 using namespace std;
31
32 std::shared_ptr<NapiA2dpSourceObserver> NapiA2dpSource::observer_ = std::make_shared<NapiA2dpSourceObserver>();
33 bool NapiA2dpSource::isRegistered_ = false;
34 thread_local napi_ref g_napiProfile = nullptr;
35
36 const static std::map<int32_t, int32_t> g_codecTypeMap = {
37 {CODEC_TYPE_SBC, A2DP_CODEC_TYPE_SBC_USER},
38 {CODEC_TYPE_AAC, A2DP_CODEC_TYPE_AAC_USER},
39 {CODEC_TYPE_L2HC, A2DP_CODEC_TYPE_L2HCV2_USER},
40 {CODEC_TYPE_L2HCST, A2DP_CODEC_TYPE_L2HCST_USER},
41 {CODEC_TYPE_LDAC, A2DP_CODEC_TYPE_LDAC_USER},
42 {CODEC_TYPE_INVALID, A2DP_CODEC_TYPE_NONA2DP_USER},
43 };
44
45 const static std::map<int32_t, int32_t> g_codecBitsPerSampleMap = {
46 {CODEC_BITS_PER_SAMPLE_NONE, A2DP_SAMPLE_BITS_NONE_USER},
47 {CODEC_BITS_PER_SAMPLE_16, A2DP_SAMPLE_BITS_16_USER},
48 {CODEC_BITS_PER_SAMPLE_24, A2DP_SAMPLE_BITS_24_USER},
49 {CODEC_BITS_PER_SAMPLE_32, A2DP_SAMPLE_BITS_32_USER},
50 };
51
52 const static std::map<int32_t, int32_t> g_codecChannelModeMap = {
53 {CODEC_CHANNEL_MODE_NONE, A2DP_CHANNEL_MODE_NONE_USER},
54 {CODEC_CHANNEL_MODE_MONO, A2DP_SBC_CHANNEL_MODE_MONO_USER},
55 {CODEC_CHANNEL_MODE_STEREO, A2DP_SBC_CHANNEL_MODE_STEREO_USER},
56 };
57
58 const static std::map<int32_t, int32_t> g_codecSampleRateMap = {
59 {CODEC_SAMPLE_RATE_NONE, A2DP_SAMPLE_RATE_NONE_USER},
60 {CODEC_SAMPLE_RATE_44100, A2DP_SBC_SAMPLE_RATE_44100_USER},
61 {CODEC_SAMPLE_RATE_48000, A2DP_L2HCV2_SAMPLE_RATE_48000_USER},
62 {CODEC_SAMPLE_RATE_88200, A2DP_SAMPLE_RATE_NONE_USER},
63 {CODEC_SAMPLE_RATE_96000, A2DP_L2HCV2_SAMPLE_RATE_96000_USER},
64 {CODEC_SAMPLE_RATE_176400, A2DP_SAMPLE_RATE_NONE_USER},
65 {CODEC_SAMPLE_RATE_192000, A2DP_SAMPLE_RATE_NONE_USER},
66 };
67
68 const static std::map<int32_t, CodecType> g_a2dpCodecTypeMap = {
69 {A2DP_CODEC_TYPE_SBC_USER, CODEC_TYPE_SBC},
70 {A2DP_CODEC_TYPE_AAC_USER, CODEC_TYPE_AAC},
71 {A2DP_CODEC_TYPE_L2HCV2_USER, CODEC_TYPE_L2HC},
72 {A2DP_CODEC_TYPE_L2HCST_USER, CODEC_TYPE_L2HCST},
73 {A2DP_CODEC_TYPE_LDAC_USER, CODEC_TYPE_LDAC},
74 {A2DP_CODEC_TYPE_NONA2DP_USER, CODEC_TYPE_INVALID},
75 };
76
77 const static std::map<int32_t, CodecBitsPerSample> g_a2dpCodecBitsPerSampleMap = {
78 {A2DP_SAMPLE_BITS_NONE_USER, CODEC_BITS_PER_SAMPLE_NONE},
79 {A2DP_SAMPLE_BITS_16_USER, CODEC_BITS_PER_SAMPLE_16},
80 {A2DP_SAMPLE_BITS_24_USER, CODEC_BITS_PER_SAMPLE_24},
81 {A2DP_SAMPLE_BITS_32_USER, CODEC_BITS_PER_SAMPLE_32},
82 };
83
84 const static std::map<int32_t, CodecChannelMode> g_a2dpCodecChannelModeMap = {
85 {A2DP_CHANNEL_MODE_NONE_USER, CODEC_CHANNEL_MODE_NONE},
86 {A2DP_SBC_CHANNEL_MODE_MONO_USER, CODEC_CHANNEL_MODE_MONO},
87 {A2DP_SBC_CHANNEL_MODE_STEREO_USER, CODEC_CHANNEL_MODE_STEREO},
88 };
89
90 const static std::map<int32_t, CodecSampleRate> g_a2dpCodecSampleRateMap = {
91 {A2DP_SAMPLE_RATE_NONE_USER, CODEC_SAMPLE_RATE_NONE},
92 {A2DP_SBC_SAMPLE_RATE_44100_USER, CODEC_SAMPLE_RATE_44100},
93 {A2DP_SBC_SAMPLE_RATE_48000_USER, CODEC_SAMPLE_RATE_48000},
94 {A2DP_L2HCV2_SAMPLE_RATE_48000_USER, CODEC_SAMPLE_RATE_48000},
95 {A2DP_L2HCV2_SAMPLE_RATE_96000_USER, CODEC_SAMPLE_RATE_96000},
96 };
97
DefineA2dpSourceJSClass(napi_env env,napi_value exports)98 napi_value NapiA2dpSource::DefineA2dpSourceJSClass(napi_env env, napi_value exports)
99 {
100 A2dpPropertyValueInit(env, exports);
101 napi_property_descriptor properties[] = {
102 DECLARE_NAPI_FUNCTION("on", On),
103 DECLARE_NAPI_FUNCTION("off", Off),
104 DECLARE_NAPI_FUNCTION("connect", Connect),
105 DECLARE_NAPI_FUNCTION("disconnect", Disconnect),
106 DECLARE_NAPI_FUNCTION("getPlayingState", GetPlayingState),
107 #ifndef BLUETOOTH_API_SINCE_10
108 DECLARE_NAPI_FUNCTION("getConnectionDevices", GetConnectionDevices),
109 DECLARE_NAPI_FUNCTION("getDeviceState", GetDeviceState),
110 #endif
111 #ifdef BLUETOOTH_API_SINCE_10
112 DECLARE_NAPI_FUNCTION("setConnectionStrategy", SetConnectionStrategy),
113 DECLARE_NAPI_FUNCTION("getConnectionStrategy", GetConnectionStrategy),
114 DECLARE_NAPI_FUNCTION("getConnectionState", GetConnectionState),
115 DECLARE_NAPI_FUNCTION("getConnectedDevices", GetConnectedDevices),
116 DECLARE_NAPI_FUNCTION("isAbsoluteVolumeSupported", IsAbsoluteVolumeSupported),
117 DECLARE_NAPI_FUNCTION("isAbsoluteVolumeEnabled", IsAbsoluteVolumeEnabled),
118 DECLARE_NAPI_FUNCTION("enableAbsoluteVolume", EnableAbsoluteVolume),
119 DECLARE_NAPI_FUNCTION("disableAbsoluteVolume", DisableAbsoluteVolume),
120 DECLARE_NAPI_FUNCTION("setCurrentCodecInfo", SetCurrentCodecInfo),
121 DECLARE_NAPI_FUNCTION("getCurrentCodecInfo", GetCurrentCodecInfo),
122 DECLARE_NAPI_FUNCTION("enableAutoPlay", EnableAutoPlay),
123 DECLARE_NAPI_FUNCTION("disableAutoPlay", DisableAutoPlay),
124 DECLARE_NAPI_FUNCTION("getAutoPlayDisabledDuration", GetAutoPlayDisabledDuration),
125 #endif
126 };
127
128 napi_value constructor;
129 napi_define_class(env,
130 "A2dpSource",
131 NAPI_AUTO_LENGTH,
132 A2dpSourceConstructor,
133 nullptr,
134 sizeof(properties) / sizeof(properties[0]),
135 properties,
136 &constructor);
137 #ifdef BLUETOOTH_API_SINCE_10
138 DefineCreateProfile(env, exports);
139 napi_create_reference(env, constructor, 1, &g_napiProfile);
140 #else
141 napi_value napiProfile;
142 napi_new_instance(env, constructor, 0, nullptr, &napiProfile);
143 NapiProfile::SetProfile(env, ProfileId::PROFILE_A2DP_SOURCE, napiProfile);
144 #endif
145 return exports;
146 }
147
A2dpSourceConstructor(napi_env env,napi_callback_info info)148 napi_value NapiA2dpSource::A2dpSourceConstructor(napi_env env, napi_callback_info info)
149 {
150 napi_value thisVar = nullptr;
151 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
152 return thisVar;
153 }
154
On(napi_env env,napi_callback_info info)155 napi_value NapiA2dpSource::On(napi_env env, napi_callback_info info)
156 {
157 if (observer_) {
158 auto status = observer_->eventSubscribe_.Register(env, info);
159 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
160 }
161
162 if (!isRegistered_) {
163 A2dpSource *profile = A2dpSource::GetProfile();
164 profile->RegisterObserver(observer_);
165 isRegistered_ = true;
166 }
167 return NapiGetUndefinedRet(env);
168 }
169
Off(napi_env env,napi_callback_info info)170 napi_value NapiA2dpSource::Off(napi_env env, napi_callback_info info)
171 {
172 if (observer_) {
173 auto status = observer_->eventSubscribe_.Deregister(env, info);
174 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
175 }
176 return NapiGetUndefinedRet(env);
177 }
178
GetPlayingState(napi_env env,napi_callback_info info)179 napi_value NapiA2dpSource::GetPlayingState(napi_env env, napi_callback_info info)
180 {
181 HILOGD("start");
182 int state = PlayingState::STATE_NOT_PLAYING;
183 napi_value ret = nullptr;
184 napi_create_int32(env, state, &ret);
185
186 std::string remoteAddr{};
187 bool checkRet = CheckDeivceIdParam(env, info, remoteAddr);
188 NAPI_BT_ASSERT_RETURN(env, checkRet, BT_ERR_INVALID_PARAM, ret);
189
190 int transport = BT_TRANSPORT_BREDR;
191 BluetoothRemoteDevice remoteDevice = BluetoothRemoteDevice(remoteAddr, transport);
192 A2dpSource *profile = A2dpSource::GetProfile();
193 int32_t errorCode = profile->GetPlayingState(remoteDevice, state);
194 HILOGI("errorCode: %{public}d", errorCode);
195 NAPI_BT_ASSERT_RETURN(env, (errorCode == BT_NO_ERROR), errorCode, ret);
196
197 return NapiGetInt32Ret(env, state);
198 }
199
Connect(napi_env env,napi_callback_info info)200 napi_value NapiA2dpSource::Connect(napi_env env, napi_callback_info info)
201 {
202 HILOGD("start");
203 std::string remoteAddr{};
204 bool checkRet = CheckDeivceIdParam(env, info, remoteAddr);
205 NAPI_BT_ASSERT_RETURN_FALSE(env, checkRet, BT_ERR_INVALID_PARAM);
206
207 int transport = BT_TRANSPORT_BREDR;
208 BluetoothRemoteDevice remoteDevice = BluetoothRemoteDevice(remoteAddr, transport);
209 A2dpSource *profile = A2dpSource::GetProfile();
210 int32_t ret = profile->Connect(remoteDevice);
211 NAPI_BT_ASSERT_RETURN_FALSE(env, ret == BT_NO_ERROR, ret);
212
213 return NapiGetBooleanTrue(env);
214 }
215
Disconnect(napi_env env,napi_callback_info info)216 napi_value NapiA2dpSource::Disconnect(napi_env env, napi_callback_info info)
217 {
218 HILOGD("start");
219 std::string remoteAddr{};
220 bool checkRet = CheckDeivceIdParam(env, info, remoteAddr);
221 NAPI_BT_ASSERT_RETURN_FALSE(env, checkRet, BT_ERR_INVALID_PARAM);
222
223 int transport = BT_TRANSPORT_BREDR;
224 BluetoothRemoteDevice remoteDevice = BluetoothRemoteDevice(remoteAddr, transport);
225 A2dpSource *profile = A2dpSource::GetProfile();
226 int32_t ret = profile->Disconnect(remoteDevice);
227 NAPI_BT_ASSERT_RETURN_FALSE(env, ret == BT_NO_ERROR, ret);
228
229 return NapiGetBooleanTrue(env);
230 }
231
PlayingStateInit(napi_env env)232 napi_value PlayingStateInit(napi_env env)
233 {
234 napi_value playingState = nullptr;
235 napi_create_object(env, &playingState);
236 SetNamedPropertyByInteger(env, playingState, PlayingState::STATE_NOT_PLAYING, "STATE_NOT_PLAYING");
237 SetNamedPropertyByInteger(env, playingState, PlayingState::STATE_PLAYING, "STATE_PLAYING");
238 return playingState;
239 }
240
CodecTypeInit(napi_env env)241 napi_value CodecTypeInit(napi_env env)
242 {
243 napi_value codecType = nullptr;
244 napi_create_object(env, &codecType);
245 SetNamedPropertyByInteger(env, codecType, CodecType::CODEC_TYPE_SBC, "CODEC_TYPE_SBC");
246 SetNamedPropertyByInteger(env, codecType, CodecType::CODEC_TYPE_AAC, "CODEC_TYPE_AAC");
247 SetNamedPropertyByInteger(env, codecType, CodecType::CODEC_TYPE_L2HC, "CODEC_TYPE_L2HC");
248 SetNamedPropertyByInteger(env, codecType, CodecType::CODEC_TYPE_L2HCST, "CODEC_TYPE_L2HCST");
249 SetNamedPropertyByInteger(env, codecType, CodecType::CODEC_TYPE_LDAC, "CODEC_TYPE_LDAC");
250 SetNamedPropertyByInteger(env, codecType, CodecType::CODEC_TYPE_INVALID, "CODEC_TYPE_INVALID");
251 return codecType;
252 }
253
CodecBitsPerSampleInit(napi_env env)254 napi_value CodecBitsPerSampleInit(napi_env env)
255 {
256 napi_value codecBitsPerSample = nullptr;
257 napi_create_object(env, &codecBitsPerSample);
258 SetNamedPropertyByInteger(env, codecBitsPerSample,
259 CodecBitsPerSample::CODEC_BITS_PER_SAMPLE_NONE, "CODEC_BITS_PER_SAMPLE_NONE");
260 SetNamedPropertyByInteger(env, codecBitsPerSample,
261 CodecBitsPerSample::CODEC_BITS_PER_SAMPLE_16, "CODEC_BITS_PER_SAMPLE_16");
262 SetNamedPropertyByInteger(env, codecBitsPerSample,
263 CodecBitsPerSample::CODEC_BITS_PER_SAMPLE_24, "CODEC_BITS_PER_SAMPLE_24");
264 SetNamedPropertyByInteger(env, codecBitsPerSample,
265 CodecBitsPerSample::CODEC_BITS_PER_SAMPLE_32, "CODEC_BITS_PER_SAMPLE_32");
266 return codecBitsPerSample;
267 }
268
CodecChannelModeInit(napi_env env)269 napi_value CodecChannelModeInit(napi_env env)
270 {
271 napi_value codecChannelMode = nullptr;
272 napi_create_object(env, &codecChannelMode);
273 SetNamedPropertyByInteger(env, codecChannelMode,
274 CodecChannelMode::CODEC_CHANNEL_MODE_NONE, "CODEC_CHANNEL_MODE_NONE");
275 SetNamedPropertyByInteger(env, codecChannelMode,
276 CodecChannelMode::CODEC_CHANNEL_MODE_MONO, "CODEC_CHANNEL_MODE_MONO");
277 SetNamedPropertyByInteger(env, codecChannelMode,
278 CodecChannelMode::CODEC_CHANNEL_MODE_STEREO, "CODEC_CHANNEL_MODE_STEREO");
279 return codecChannelMode;
280 }
281
CodecSampleRateInit(napi_env env)282 napi_value CodecSampleRateInit(napi_env env)
283 {
284 napi_value codecSampleRate = nullptr;
285 napi_create_object(env, &codecSampleRate);
286 SetNamedPropertyByInteger(env, codecSampleRate,
287 CodecSampleRate::CODEC_SAMPLE_RATE_NONE, "CODEC_SAMPLE_RATE_NONE");
288 SetNamedPropertyByInteger(env, codecSampleRate,
289 CodecSampleRate::CODEC_SAMPLE_RATE_44100, "CODEC_SAMPLE_RATE_44100");
290 SetNamedPropertyByInteger(env, codecSampleRate,
291 CodecSampleRate::CODEC_SAMPLE_RATE_48000, "CODEC_SAMPLE_RATE_48000");
292 SetNamedPropertyByInteger(env, codecSampleRate,
293 CodecSampleRate::CODEC_SAMPLE_RATE_88200, "CODEC_SAMPLE_RATE_88200");
294 SetNamedPropertyByInteger(env, codecSampleRate,
295 CodecSampleRate::CODEC_SAMPLE_RATE_96000, "CODEC_SAMPLE_RATE_96000");
296 SetNamedPropertyByInteger(env, codecSampleRate,
297 CodecSampleRate::CODEC_SAMPLE_RATE_176400, "CODEC_SAMPLE_RATE_176400");
298 SetNamedPropertyByInteger(env, codecSampleRate,
299 CodecSampleRate::CODEC_SAMPLE_RATE_192000, "CODEC_SAMPLE_RATE_192000");
300 return codecSampleRate;
301 }
302
A2dpPropertyValueInit(napi_env env,napi_value exports)303 napi_value NapiA2dpSource::A2dpPropertyValueInit(napi_env env, napi_value exports)
304 {
305 napi_value playingStateObj = PlayingStateInit(env);
306 napi_value codecTypeObj = CodecTypeInit(env);
307 napi_value codecBitsPerSampleObj = CodecBitsPerSampleInit(env);
308 napi_value codecChannelModeObj = CodecChannelModeInit(env);
309 napi_value codecSampleRateObj = CodecSampleRateInit(env);
310 napi_property_descriptor exportProps[] = {
311 DECLARE_NAPI_PROPERTY("PlayingState", playingStateObj),
312 DECLARE_NAPI_PROPERTY("CodecType", codecTypeObj),
313 DECLARE_NAPI_PROPERTY("CodecBitsPerSample", codecBitsPerSampleObj),
314 DECLARE_NAPI_PROPERTY("CodecChannelMode", codecChannelModeObj),
315 DECLARE_NAPI_PROPERTY("CodecSampleRate", codecSampleRateObj),
316 };
317 HITRACE_METER_NAME(HITRACE_TAG_OHOS, "a2dp_src:napi_define_properties");
318 napi_define_properties(env, exports, sizeof(exportProps) / sizeof(*exportProps), exportProps);
319 return exports;
320 }
321
GetConnectionDevices(napi_env env,napi_callback_info info)322 napi_value NapiA2dpSource::GetConnectionDevices(napi_env env, napi_callback_info info)
323 {
324 HILOGI("enter");
325 napi_value ret = nullptr;
326 napi_create_array(env, &ret);
327 A2dpSource *profile = A2dpSource::GetProfile();
328 vector<int> states;
329 states.push_back(1);
330 vector<BluetoothRemoteDevice> devices;
331 int errorCode = profile->GetDevicesByStates(states, devices);
332 NAPI_BT_ASSERT_RETURN(env, (errorCode == BT_NO_ERROR), errorCode, ret);
333
334 vector<string> deviceVector;
335 for (auto &device : devices) {
336 deviceVector.push_back(device.GetDeviceAddr());
337 }
338 ConvertStringVectorToJS(env, ret, deviceVector);
339 return ret;
340 }
341
GetDeviceState(napi_env env,napi_callback_info info)342 napi_value NapiA2dpSource::GetDeviceState(napi_env env, napi_callback_info info)
343 {
344 HILOGD("enter");
345
346 size_t expectedArgsCount = ARGS_SIZE_ONE;
347 size_t argc = expectedArgsCount;
348 napi_value argv[ARGS_SIZE_ONE] = {0};
349 napi_value thisVar = nullptr;
350
351 napi_value ret = nullptr;
352 napi_get_undefined(env, &ret);
353
354 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
355 if (argc != expectedArgsCount) {
356 HILOGE("Requires 1 argument.");
357 return ret;
358 }
359 string deviceId;
360 if (!ParseString(env, deviceId, argv[PARAM0])) {
361 HILOGE("string expected.");
362 return ret;
363 }
364
365 A2dpSource *profile = A2dpSource::GetProfile();
366 BluetoothRemoteDevice device(deviceId, 1);
367
368 int32_t profileState = ProfileConnectionState::STATE_DISCONNECTED;
369 if (napi_create_int32(env, profileState, &ret) != napi_ok) {
370 HILOGE("napi_create_int32 failed.");
371 }
372
373 int btConnectState = static_cast<int32_t>(BTConnectState::DISCONNECTED);
374 int errorCode = profile->GetDeviceState(device, btConnectState);
375 NAPI_BT_ASSERT_RETURN(env, (errorCode == BT_NO_ERROR), errorCode, ret);
376
377 napi_value result = nullptr;
378 int status = GetProfileConnectionState(btConnectState);
379 napi_create_int32(env, status, &result);
380 HILOGD("status: %{public}d", status);
381 return result;
382 }
383
384 #ifdef BLUETOOTH_API_SINCE_10
DefineCreateProfile(napi_env env,napi_value exports)385 napi_value NapiA2dpSource::DefineCreateProfile(napi_env env, napi_value exports)
386 {
387 napi_property_descriptor properties[] = {
388 DECLARE_NAPI_FUNCTION("createA2dpSrcProfile", CreateA2dpSrcProfile),
389 };
390 HITRACE_METER_NAME(HITRACE_TAG_OHOS, "a2dp_src:napi_define_properties");
391 napi_define_properties(env, exports, sizeof(properties) / sizeof(properties[0]), properties);
392 return exports;
393 }
394
CreateA2dpSrcProfile(napi_env env,napi_callback_info info)395 napi_value NapiA2dpSource::CreateA2dpSrcProfile(napi_env env, napi_callback_info info)
396 {
397 napi_value profile;
398 napi_value constructor = nullptr;
399 napi_get_reference_value(env, g_napiProfile, &constructor);
400 napi_new_instance(env, constructor, 0, nullptr, &profile);
401 return profile;
402 }
403
SetConnectionStrategy(napi_env env,napi_callback_info info)404 napi_value NapiA2dpSource::SetConnectionStrategy(napi_env env, napi_callback_info info)
405 {
406 HILOGD("start");
407 std::string remoteAddr{};
408 int32_t strategy = 0;
409 auto status = CheckSetConnectStrategyParam(env, info, remoteAddr, strategy);
410 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
411
412 int transport = BT_TRANSPORT_BREDR;
413 auto func = [remoteAddr, transport, strategy]() {
414 BluetoothRemoteDevice remoteDevice(remoteAddr, transport);
415 A2dpSource *profile = A2dpSource::GetProfile();
416 int32_t err = profile->SetConnectStrategy(remoteDevice, strategy);
417 HILOGI("err: %{public}d", err);
418 return NapiAsyncWorkRet(err);
419 };
420 auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NO_NEED_CALLBACK);
421 NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
422 asyncWork->Run();
423 return asyncWork->GetRet();
424 }
425
GetConnectionStrategy(napi_env env,napi_callback_info info)426 napi_value NapiA2dpSource::GetConnectionStrategy(napi_env env, napi_callback_info info)
427 {
428 HILOGD("start");
429 std::string remoteAddr{};
430 auto status = CheckDeviceAddressParam(env, info, remoteAddr);
431 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
432
433 int transport = BT_TRANSPORT_BREDR;
434 auto func = [remoteAddr, transport]() {
435 int strategy = 0;
436 BluetoothRemoteDevice remoteDevice(remoteAddr, transport);
437 A2dpSource *profile = A2dpSource::GetProfile();
438 int32_t err = profile->GetConnectStrategy(remoteDevice, strategy);
439 HILOGD("err: %{public}d, deviceName: %{public}d", err, strategy);
440 auto object = std::make_shared<NapiNativeInt>(strategy);
441 return NapiAsyncWorkRet(err, object);
442 };
443 auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NO_NEED_CALLBACK);
444 NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
445 asyncWork->Run();
446 return asyncWork->GetRet();
447 }
448
GetConnectionState(napi_env env,napi_callback_info info)449 napi_value NapiA2dpSource::GetConnectionState(napi_env env, napi_callback_info info)
450 {
451 return GetDeviceState(env, info);
452 }
GetConnectedDevices(napi_env env,napi_callback_info info)453 napi_value NapiA2dpSource::GetConnectedDevices(napi_env env, napi_callback_info info)
454 {
455 return GetConnectionDevices(env, info);
456 }
457
IsAbsoluteVolumeSupported(napi_env env,napi_callback_info info)458 napi_value NapiA2dpSource::IsAbsoluteVolumeSupported(napi_env env, napi_callback_info info)
459 {
460 HILOGD("start");
461 std::string remoteAddr{};
462 auto status = CheckDeviceAddressParam(env, info, remoteAddr);
463 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
464
465 auto func = [remoteAddr]() {
466 int32_t ability = DeviceAbsVolumeAbility::DEVICE_ABSVOL_UNSUPPORT;
467 BluetoothRemoteDevice remoteDevice(remoteAddr, BT_TRANSPORT_BREDR);
468 int32_t err = AvrcpTarget::GetProfile()->GetDeviceAbsVolumeAbility(remoteDevice, ability);
469 if (ability == DeviceAbsVolumeAbility::DEVICE_ABSVOL_UNSUPPORT) {
470 return NapiAsyncWorkRet(err, std::make_shared<NapiNativeBool>(false));
471 }
472 return NapiAsyncWorkRet(err, std::make_shared<NapiNativeBool>(true));
473 };
474 auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NO_NEED_CALLBACK);
475 NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
476 asyncWork->Run();
477 return asyncWork->GetRet();
478 }
479
IsAbsoluteVolumeEnabled(napi_env env,napi_callback_info info)480 napi_value NapiA2dpSource::IsAbsoluteVolumeEnabled(napi_env env, napi_callback_info info)
481 {
482 HILOGD("start");
483 std::string remoteAddr{};
484 auto status = CheckDeviceAddressParam(env, info, remoteAddr);
485 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
486
487 auto func = [remoteAddr]() {
488 int32_t ability = DeviceAbsVolumeAbility::DEVICE_ABSVOL_UNSUPPORT;
489 BluetoothRemoteDevice remoteDevice(remoteAddr, BT_TRANSPORT_BREDR);
490 int32_t err = AvrcpTarget::GetProfile()->GetDeviceAbsVolumeAbility(remoteDevice, ability);
491 if (ability == DeviceAbsVolumeAbility::DEVICE_ABSVOL_OPEN) {
492 return NapiAsyncWorkRet(err, std::make_shared<NapiNativeBool>(true));
493 }
494 return NapiAsyncWorkRet(err, std::make_shared<NapiNativeBool>(false));
495 };
496 auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NO_NEED_CALLBACK);
497 NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
498 asyncWork->Run();
499 return asyncWork->GetRet();
500 }
501
EnableAbsoluteVolume(napi_env env,napi_callback_info info)502 napi_value NapiA2dpSource::EnableAbsoluteVolume(napi_env env, napi_callback_info info)
503 {
504 HILOGD("start");
505 std::string remoteAddr{};
506 auto status = CheckDeviceAddressParam(env, info, remoteAddr);
507 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
508
509 auto func = [remoteAddr]() {
510 int32_t ability = DeviceAbsVolumeAbility::DEVICE_ABSVOL_OPEN;
511 BluetoothRemoteDevice remoteDevice(remoteAddr, BT_TRANSPORT_BREDR);
512 int32_t err = AvrcpTarget::GetProfile()->SetDeviceAbsVolumeAbility(remoteDevice, ability);
513 return NapiAsyncWorkRet(err);
514 };
515 auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NO_NEED_CALLBACK);
516 NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
517 asyncWork->Run();
518 return asyncWork->GetRet();
519 }
520
DisableAbsoluteVolume(napi_env env,napi_callback_info info)521 napi_value NapiA2dpSource::DisableAbsoluteVolume(napi_env env, napi_callback_info info)
522 {
523 HILOGD("start");
524 std::string remoteAddr{};
525 auto status = CheckDeviceAddressParam(env, info, remoteAddr);
526 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
527
528 auto func = [remoteAddr]() {
529 int32_t ability = DeviceAbsVolumeAbility::DEVICE_ABSVOL_CLOSE;
530 BluetoothRemoteDevice remoteDevice(remoteAddr, BT_TRANSPORT_BREDR);
531 int32_t err = AvrcpTarget::GetProfile()->SetDeviceAbsVolumeAbility(remoteDevice, ability);
532 return NapiAsyncWorkRet(err);
533 };
534 auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NO_NEED_CALLBACK);
535 NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
536 asyncWork->Run();
537 return asyncWork->GetRet();
538 }
539
ConvertCodecType(A2dpCodecInfo & a2dpCodecInfo,int32_t codecType)540 static void ConvertCodecType(A2dpCodecInfo &a2dpCodecInfo, int32_t codecType)
541 {
542 auto iter = g_codecTypeMap.find(codecType);
543 if (iter != g_codecTypeMap.end()) {
544 a2dpCodecInfo.codecType = iter->second;
545 }
546 }
547
ConvertCodecBitsPerSample(A2dpCodecInfo & a2dpCodecInfo,int32_t codecBitsPerSample)548 static void ConvertCodecBitsPerSample(A2dpCodecInfo &a2dpCodecInfo, int32_t codecBitsPerSample)
549 {
550 auto iter = g_codecBitsPerSampleMap.find(codecBitsPerSample);
551 if (iter != g_codecBitsPerSampleMap.end()) {
552 a2dpCodecInfo.bitsPerSample = iter->second;
553 }
554 }
555
ConvertCodecChannelMode(A2dpCodecInfo & a2dpCodecInfo,int32_t codecChannelMode)556 static void ConvertCodecChannelMode(A2dpCodecInfo &a2dpCodecInfo, int32_t codecChannelMode)
557 {
558 auto iter = g_codecChannelModeMap.find(codecChannelMode);
559 if (iter != g_codecChannelModeMap.end()) {
560 a2dpCodecInfo.channelMode = iter->second;
561 }
562 }
563
ConvertCodecSampleRate(A2dpCodecInfo & a2dpCodecInfo,int32_t codecSampleRate)564 static void ConvertCodecSampleRate(A2dpCodecInfo &a2dpCodecInfo, int32_t codecSampleRate)
565 {
566 auto iter = g_codecSampleRateMap.find(codecSampleRate);
567 if (iter != g_codecSampleRateMap.end()) {
568 a2dpCodecInfo.sampleRate = iter->second;
569 }
570 }
571
ConvertCodecTypeToCodecInfo(CodecInfo & codecInfo,int32_t codecType)572 static void ConvertCodecTypeToCodecInfo(CodecInfo &codecInfo, int32_t codecType)
573 {
574 auto iter = g_a2dpCodecTypeMap.find(codecType);
575 if (iter != g_a2dpCodecTypeMap.end()) {
576 codecInfo.codecType = iter->second;
577 }
578 }
579
ConvertCodecBitsPerSampleToCodecInfo(CodecInfo & codecInfo,int32_t codecBitsPerSample)580 static void ConvertCodecBitsPerSampleToCodecInfo(CodecInfo &codecInfo, int32_t codecBitsPerSample)
581 {
582 auto iter = g_a2dpCodecBitsPerSampleMap.find(codecBitsPerSample);
583 if (iter != g_a2dpCodecBitsPerSampleMap.end()) {
584 codecInfo.codecBitsPerSample = iter->second;
585 }
586 }
587
ConvertCodecChannelModeToCodecInfo(CodecInfo & codecInfo,int32_t codecChannelMode)588 static void ConvertCodecChannelModeToCodecInfo(CodecInfo &codecInfo, int32_t codecChannelMode)
589 {
590 auto iter = g_a2dpCodecChannelModeMap.find(codecChannelMode);
591 if (iter != g_a2dpCodecChannelModeMap.end()) {
592 codecInfo.codecChannelMode = iter->second;
593 }
594 }
595
ConvertCodecSampleRateToCodecInfo(CodecInfo & codecInfo,int32_t codecSampleRate)596 static void ConvertCodecSampleRateToCodecInfo(CodecInfo &codecInfo, int32_t codecSampleRate)
597 {
598 auto iter = g_a2dpCodecSampleRateMap.find(codecSampleRate);
599 if (iter != g_a2dpCodecSampleRateMap.end()) {
600 codecInfo.codecSampleRate = iter->second;
601 }
602 }
603
ConvertCodecInfoToJs(napi_env env,napi_value & object,const A2dpCodecInfo & a2dpCodecInfo)604 static void ConvertCodecInfoToJs(napi_env env, napi_value &object, const A2dpCodecInfo &a2dpCodecInfo)
605 {
606 // convert A2dpCodecInfo to CodecInfo
607 CodecInfo codecInfo;
608 ConvertCodecSampleRateToCodecInfo(codecInfo, a2dpCodecInfo.sampleRate);
609 ConvertCodecChannelModeToCodecInfo(codecInfo, a2dpCodecInfo.channelMode);
610 ConvertCodecBitsPerSampleToCodecInfo(codecInfo, a2dpCodecInfo.bitsPerSample);
611 ConvertCodecTypeToCodecInfo(codecInfo, a2dpCodecInfo.codecType);
612 // convert CodecInfo to JS
613 napi_value value = nullptr;
614 napi_create_int32(env, codecInfo.codecType, &value);
615 napi_set_named_property(env, object, "codecType", value);
616 napi_create_int32(env, codecInfo.codecBitsPerSample, &value);
617 napi_set_named_property(env, object, "codecBitsPerSample", value);
618 napi_create_int32(env, codecInfo.codecChannelMode, &value);
619 napi_set_named_property(env, object, "codecChannelMode", value);
620 napi_create_int32(env, codecInfo.codecSampleRate, &value);
621 napi_set_named_property(env, object, "codecSampleRate", value);
622 }
623
CheckSetCodecPreferenceParam(napi_env env,napi_callback_info info,std::string & addr,A2dpCodecInfo & a2dpCodecInfo)624 static napi_status CheckSetCodecPreferenceParam(napi_env env, napi_callback_info info,
625 std::string &addr, A2dpCodecInfo &a2dpCodecInfo)
626 {
627 size_t argc = ARGS_SIZE_TWO;
628 napi_value argv[ARGS_SIZE_TWO] = {nullptr};
629 NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
630 NAPI_BT_RETURN_IF(argc != ARGS_SIZE_TWO, "Requires 2 arguments.", napi_invalid_arg);
631 NAPI_BT_CALL_RETURN(NapiParseBdAddr(env, argv[PARAM0], addr));
632 NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(
633 env, argv[PARAM1], {"codecType", "codecBitsPerSample", "codecChannelMode", "codecSampleRate"}));
634 // parse codecInfo
635 int32_t codecType = 0;
636 NAPI_BT_CALL_RETURN(NapiParseObjectInt32(env, argv[PARAM1], "codecType", codecType));
637 ConvertCodecType(a2dpCodecInfo, codecType);
638 int32_t codecBitsPerSample = 0;
639 NAPI_BT_CALL_RETURN(NapiParseObjectInt32(env, argv[PARAM1], "codecBitsPerSample", codecBitsPerSample));
640 ConvertCodecBitsPerSample(a2dpCodecInfo, codecBitsPerSample);
641 int32_t codecChannelMode = 0;
642 NAPI_BT_CALL_RETURN(NapiParseObjectInt32(env, argv[PARAM1], "codecChannelMode", codecChannelMode));
643 ConvertCodecChannelMode(a2dpCodecInfo, codecChannelMode);
644 int32_t codecSampleRate = 0;
645 NAPI_BT_CALL_RETURN(NapiParseObjectInt32(env, argv[PARAM1], "codecSampleRate", codecSampleRate));
646 ConvertCodecSampleRate(a2dpCodecInfo, codecSampleRate);
647 return napi_ok;
648 }
649
SetCurrentCodecInfo(napi_env env,napi_callback_info info)650 napi_value NapiA2dpSource::SetCurrentCodecInfo(napi_env env, napi_callback_info info)
651 {
652 std::string remoteAddr{};
653 A2dpCodecInfo a2dpCodecInfo;
654 auto status = CheckSetCodecPreferenceParam(env, info, remoteAddr, a2dpCodecInfo);
655 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
656 BluetoothRemoteDevice remoteDevice(remoteAddr, BT_TRANSPORT_BREDR);
657 A2dpSource *profile = A2dpSource::GetProfile();
658 int32_t errorCode = profile->SetCodecPreference(remoteDevice, a2dpCodecInfo);
659 HILOGI("err: %{public}d", errorCode);
660 NAPI_BT_ASSERT_RETURN_FALSE(env, errorCode == BT_NO_ERROR, errorCode);
661 return NapiGetBooleanTrue(env);
662 }
663
GetCurrentCodecInfo(napi_env env,napi_callback_info info)664 napi_value NapiA2dpSource::GetCurrentCodecInfo(napi_env env, napi_callback_info info)
665 {
666 HILOGI("start");
667 napi_value ret = nullptr;
668 napi_create_object(env, &ret);
669
670 std::string remoteAddr{};
671 bool checkRet = CheckDeivceIdParam(env, info, remoteAddr);
672 NAPI_BT_ASSERT_RETURN(env, checkRet, BT_ERR_INVALID_PARAM, ret);
673 A2dpCodecInfo a2dpCodecInfo;
674 int transport = BT_TRANSPORT_BREDR;
675 BluetoothRemoteDevice remoteDevice = BluetoothRemoteDevice(remoteAddr, transport);
676 A2dpSource *profile = A2dpSource::GetProfile();
677 int errorCode = profile->GetCodecPreference(remoteDevice, a2dpCodecInfo);
678 NAPI_BT_ASSERT_RETURN(env, (errorCode == BT_NO_ERROR), errorCode, ret);
679 ConvertCodecInfoToJs(env, ret, a2dpCodecInfo);
680 return ret;
681 }
682
EnableAutoPlay(napi_env env,napi_callback_info info)683 napi_value NapiA2dpSource::EnableAutoPlay(napi_env env, napi_callback_info info)
684 {
685 std::string deviceId = INVALID_MAC_ADDRESS;
686 auto status = CheckDeivceIdParam(env, info, deviceId);
687 NAPI_BT_ASSERT_RETURN_UNDEF(env, status, BT_ERR_INVALID_PARAM);
688
689 auto func = [deviceId]() {
690 BluetoothRemoteDevice device(deviceId, BT_TRANSPORT_BREDR);
691 A2dpSource *profile = A2dpSource::GetProfile();
692 int err = profile->EnableAutoPlay(device);
693 HILOGI("err: %{public}d", err);
694 return NapiAsyncWorkRet(err);
695 };
696 auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NO_NEED_CALLBACK);
697 NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
698 asyncWork->Run();
699 return asyncWork->GetRet();
700 }
701
IsInvalidAutoPlayDuration(int32_t duration)702 static bool IsInvalidAutoPlayDuration(int32_t duration)
703 {
704 return duration < MIN_AUTO_PLAY_DURATION_SEC
705 || duration> MAX_AUTO_PLAY_DURATION_SEC;
706 }
707
CheckDisableAutoPlayParam(napi_env env,napi_callback_info info,std::string & addr,int32_t & duration)708 static napi_status CheckDisableAutoPlayParam(napi_env env, napi_callback_info info, std::string &addr,
709 int32_t &duration)
710 {
711 size_t argc = ARGS_SIZE_TWO;
712 napi_value argv[ARGS_SIZE_TWO] = {nullptr};
713 NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
714 NAPI_BT_RETURN_IF(argc != ARGS_SIZE_TWO, "Requires 2 arguments", napi_invalid_arg);
715 NAPI_BT_CALL_RETURN(NapiParseBdAddr(env, argv[PARAM0], addr));
716 NAPI_BT_RETURN_IF(!ParseInt32(env, duration, argv[PARAM1]), "ParseInt failed", napi_invalid_arg);
717 NAPI_BT_RETURN_IF(IsInvalidAutoPlayDuration(duration), "Invalid duration", napi_invalid_arg);
718 return napi_ok;
719 }
720
DisableAutoPlay(napi_env env,napi_callback_info info)721 napi_value NapiA2dpSource::DisableAutoPlay(napi_env env, napi_callback_info info)
722 {
723 std::string deviceId = INVALID_MAC_ADDRESS;
724 int duration = 0;
725 auto status = CheckDisableAutoPlayParam(env, info, deviceId, duration);
726 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
727
728 auto func = [deviceId, duration]() {
729 BluetoothRemoteDevice device(deviceId, BT_TRANSPORT_BREDR);
730 A2dpSource *profile = A2dpSource::GetProfile();
731 int err = profile->DisableAutoPlay(device, duration);
732 HILOGI("err: %{public}d", err);
733 return NapiAsyncWorkRet(err);
734 };
735 auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NO_NEED_CALLBACK);
736 NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
737 asyncWork->Run();
738 return asyncWork->GetRet();
739 }
740
GetAutoPlayDisabledDuration(napi_env env,napi_callback_info info)741 napi_value NapiA2dpSource::GetAutoPlayDisabledDuration(napi_env env, napi_callback_info info)
742 {
743 std::string deviceId = INVALID_MAC_ADDRESS;
744 auto status = CheckDeivceIdParam(env, info, deviceId);
745 NAPI_BT_ASSERT_RETURN_UNDEF(env, status, BT_ERR_INVALID_PARAM);
746
747 auto func = [deviceId]() {
748 int duration = 0;
749 BluetoothRemoteDevice device(deviceId, BT_TRANSPORT_BREDR);
750 A2dpSource *profile = A2dpSource::GetProfile();
751 int err = profile->GetAutoPlayDisabledDuration(device, duration);
752 HILOGI("err: %{public}d, duration: %{public}d", err, duration);
753 auto object = std::make_shared<NapiNativeInt>(duration);
754 return NapiAsyncWorkRet(err, object);
755 };
756 auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NO_NEED_CALLBACK);
757 NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
758 asyncWork->Run();
759 return asyncWork->GetRet();
760 }
761 #endif
762 } // namespace Bluetooth
763 } // namespace OHOS