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