• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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