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