1 /*
2 * Copyright (C) 2021-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include "napi_bluetooth_host_observer.h"
16
17 #include "bluetooth_log.h"
18 #include "bluetooth_utils.h"
19
20 #include "napi/native_api.h"
21 #include "napi/native_node_api.h"
22
23 #include <uv.h>
24
25 namespace OHOS {
26 namespace Bluetooth {
UvQueueWorkOnStateChanged(uv_work_t * work,BluetoothState & state)27 void NapiBluetoothHostObserver::UvQueueWorkOnStateChanged(uv_work_t *work, BluetoothState &state)
28 {
29 HILOGI("OnStateChanged uv_work_t start");
30
31 if (work == nullptr) {
32 HILOGE("work is null");
33 return;
34 }
35 auto callbackData = (AfterWorkCallbackData<NapiBluetoothHostObserver,
36 decltype(&NapiBluetoothHostObserver::UvQueueWorkOnStateChanged),
37 BluetoothState> *)work->data;
38 if (callbackData == nullptr) {
39 HILOGE("callbackData is null");
40 return;
41 }
42
43 napi_value result = 0;
44 napi_value callback = 0;
45 napi_value undefined = 0;
46 napi_value callResult = 0;
47
48 napi_get_undefined(callbackData->env, &undefined);
49 HILOGD("UvQueueWorkOnStateChanged Status is %{public}d", state);
50 napi_create_int32(callbackData->env, static_cast<int32_t>(state), &result);
51 napi_get_reference_value(callbackData->env, callbackData->callback, &callback);
52 napi_call_function(callbackData->env, undefined, callback, ARGS_SIZE_ONE, &result, &callResult);
53 }
54
OnStateChanged(const int transport,const int status)55 void NapiBluetoothHostObserver::OnStateChanged(const int transport, const int status)
56 {
57 HILOGD("NapiBluetoothHostObserver::OnStateChanged called");
58 std::map<std::string, std::shared_ptr<BluetoothCallbackInfo>> observers = GetObserver();
59 if (!observers[REGISTER_STATE_CHANGE_TYPE]) {
60 HILOGE("NapiBluetoothHostObserver::OnStateChanged: This callback is not registered by ability.");
61 return;
62 }
63
64 std::shared_ptr<BluetoothCallbackInfo> callbackInfo = observers[REGISTER_STATE_CHANGE_TYPE];
65 uv_loop_s *loop = nullptr;
66 napi_get_uv_event_loop(callbackInfo->env_, &loop);
67 if (loop == nullptr) {
68 HILOGE("loop instance is nullptr");
69 return;
70 }
71
72 BluetoothState state;
73 DealStateChange(transport, status, state);
74
75 auto callbackData = new (std::nothrow) AfterWorkCallbackData<NapiBluetoothHostObserver,
76 decltype(&NapiBluetoothHostObserver::UvQueueWorkOnStateChanged),
77 BluetoothState>();
78 if (callbackData == nullptr) {
79 HILOGE("new callbackData failed");
80 return;
81 }
82
83 callbackData->object = this;
84 callbackData->function = &NapiBluetoothHostObserver::UvQueueWorkOnStateChanged;
85 callbackData->env = callbackInfo->env_;
86 callbackData->callback = callbackInfo->callback_;
87 callbackData->data = state;
88
89 uv_work_t *work = new (std::nothrow) uv_work_t;
90 if (work == nullptr) {
91 HILOGE("new work failed");
92 delete callbackData;
93 callbackData = nullptr;
94 return;
95 }
96 work->data = (void *)callbackData;
97 int ret = uv_queue_work(
98 loop, work, [](uv_work_t *work) {}, AfterWorkCallback<decltype(callbackData)>);
99 if (ret != 0) {
100 delete callbackData;
101 callbackData = nullptr;
102 delete work;
103 work = nullptr;
104 }
105 }
106
OnDiscoveryStateChanged(int status)107 void NapiBluetoothHostObserver::OnDiscoveryStateChanged(int status)
108 {
109 HILOGI("NapiBluetoothHostObserver::OnDiscoveryStateChanged called, status is %{public}d", status);
110 switch (status) {
111 case DISCOVERY_STARTED:
112 HILOGD("NapiBluetoothHostObserver::OnDiscoveryStateChanged discover start");
113 break;
114 case DISCOVERYING:
115 HILOGD("NapiBluetoothHostObserver::OnDiscoveryStateChanged discovering");
116 break;
117 case DISCOVERY_STOPED:
118 HILOGD("NapiBluetoothHostObserver::OnDiscoveryStateChanged discover stop");
119 break;
120 default:
121 HILOGD("NapiBluetoothHostObserver::OnDiscoveryStateChanged other status");
122 break;
123 }
124 }
125
UvQueueWorkOnDiscoveryResult(uv_work_t * work,std::shared_ptr<BluetoothRemoteDevice> & device)126 void NapiBluetoothHostObserver::UvQueueWorkOnDiscoveryResult(
127 uv_work_t *work, std::shared_ptr<BluetoothRemoteDevice> &device)
128 {
129 HILOGI("OnDiscoveryResult uv_work_t start");
130
131 if (work == nullptr) {
132 HILOGE("work is null");
133 return;
134 }
135 auto callbackData = (AfterWorkCallbackData<NapiBluetoothHostObserver,
136 decltype(&NapiBluetoothHostObserver::UvQueueWorkOnDiscoveryResult),
137 std::shared_ptr<BluetoothRemoteDevice>> *)work->data;
138 if (callbackData == nullptr) {
139 HILOGE("callbackData is null");
140 return;
141 }
142
143 napi_value result = 0;
144 napi_value value = 0;
145 napi_value callback = 0;
146 napi_value undefined = 0;
147 napi_value callResult = 0;
148 napi_get_undefined(callbackData->env, &undefined);
149 HILOGD("NapiBluetoothHostObserver::OnDiscoveryResult: Status is %{public}s",
150 GetEncryptAddr(device->GetDeviceAddr()).c_str());
151 napi_create_array(callbackData->env, &result);
152 napi_create_string_utf8(callbackData->env, device->GetDeviceAddr().c_str(), device->GetDeviceAddr().size(), &value);
153 napi_set_element(callbackData->env, result, 0, value);
154
155 napi_get_reference_value(callbackData->env, callbackData->callback, &callback);
156 napi_call_function(callbackData->env, undefined, callback, ARGS_SIZE_ONE, &result, &callResult);
157 }
158
OnDiscoveryResult(const BluetoothRemoteDevice & device)159 void NapiBluetoothHostObserver::OnDiscoveryResult(const BluetoothRemoteDevice &device)
160 {
161 HILOGI("NapiBluetoothHostObserver::OnDiscoveryResult called");
162 std::map<std::string, std::shared_ptr<BluetoothCallbackInfo>> observers = GetObserver();
163 if (!observers[REGISTER_DEVICE_FIND_TYPE]) {
164 HILOGE("NapiBluetoothHostObserver::OnDiscoveryResult: This callback is not registered by ability.");
165 return;
166 }
167 HILOGD("NapiBluetoothHostObserver::OnDiscoveryResult: %{public}s is registered by ability",
168 REGISTER_DEVICE_FIND_TYPE.c_str());
169 std::shared_ptr<BluetoothCallbackInfo> callbackInfo = observers[REGISTER_DEVICE_FIND_TYPE];
170 uv_loop_s *loop = nullptr;
171 napi_get_uv_event_loop(callbackInfo->env_, &loop);
172 if (loop == nullptr) {
173 HILOGE("loop instance is nullptr");
174 return;
175 }
176
177 auto callbackData = new (std::nothrow) AfterWorkCallbackData<NapiBluetoothHostObserver,
178 decltype(&NapiBluetoothHostObserver::UvQueueWorkOnDiscoveryResult),
179 std::shared_ptr<BluetoothRemoteDevice>>();
180 if (callbackData == nullptr) {
181 HILOGE("new callbackData failed");
182 return;
183 }
184
185 callbackData->object = this;
186 callbackData->function = &NapiBluetoothHostObserver::UvQueueWorkOnDiscoveryResult;
187 callbackData->env = callbackInfo->env_;
188 callbackData->callback = callbackInfo->callback_;
189 callbackData->data = std::make_shared<BluetoothRemoteDevice>(device);
190
191 uv_work_t *work = new (std::nothrow) uv_work_t;
192 if (work == nullptr) {
193 HILOGE("new work failed");
194 delete callbackData;
195 callbackData = nullptr;
196 return;
197 }
198
199 work->data = (void *)callbackData;
200
201 int ret = uv_queue_work(
202 loop, work, [](uv_work_t *work) {}, AfterWorkCallback<decltype(callbackData)>);
203 if (ret != 0) {
204 delete callbackData;
205 callbackData = nullptr;
206 delete work;
207 work = nullptr;
208 }
209 }
210
OnPairRequested(const BluetoothRemoteDevice & device)211 void NapiBluetoothHostObserver::OnPairRequested(const BluetoothRemoteDevice &device)
212 {
213 HILOGI("NapiBluetoothHostObserver::OnPairRequested called");
214 BluetoothRemoteDevice remoteDevice;
215 if (device.GetTransportType() == BT_TRANSPORT_BREDR) {
216 remoteDevice = BluetoothHost::GetDefaultHost().GetRemoteDevice(device.GetDeviceAddr(), BT_TRANSPORT_BREDR);
217 } else if (device.GetTransportType() == BT_TRANSPORT_BLE) {
218 remoteDevice = BluetoothHost::GetDefaultHost().GetRemoteDevice(device.GetDeviceAddr(), BT_TRANSPORT_BLE);
219 }
220 remoteDevice.PairRequestReply(true);
221 }
222
OnPairConfirmed(const BluetoothRemoteDevice & device,int reqType,int number)223 void NapiBluetoothHostObserver::OnPairConfirmed(const BluetoothRemoteDevice &device, int reqType, int number)
224 {
225 HILOGI("NapiBluetoothHostObserver::OnPairConfirmed called");
226 if (device.GetTransportType() == BT_TRANSPORT_BREDR) {
227 DealBredrPairComfirmed(device.GetDeviceAddr(), reqType, number);
228 } else if (device.GetTransportType() == BT_TRANSPORT_BLE) {
229 DealBlePairComfirmed(device.GetDeviceAddr(), reqType, number);
230 }
231 }
232
OnScanModeChanged(int mode)233 void NapiBluetoothHostObserver::OnScanModeChanged(int mode)
234 {
235 HILOGI("NapiBluetoothHostObserver::OnScanModeChanged called, mode is %{public}d", mode);
236 }
237
OnDeviceNameChanged(const std::string & deviceName)238 void NapiBluetoothHostObserver::OnDeviceNameChanged(const std::string &deviceName)
239 {
240 HILOGI("NapiBluetoothHostObserver::OnDeviceNameChanged called, name is %{public}s", deviceName.c_str());
241 }
242
OnDeviceAddrChanged(const std::string & address)243 void NapiBluetoothHostObserver::OnDeviceAddrChanged(const std::string &address)
244 {
245 HILOGI("address is %{public}s", GetEncryptAddr(address).c_str());
246 }
247
DealStateChange(const int transport,const int status,BluetoothState & state)248 void NapiBluetoothHostObserver::DealStateChange(const int transport, const int status, BluetoothState &state)
249 {
250 if (transport == BT_TRANSPORT_BREDR) {
251 switch (status) {
252 case BTStateID::STATE_TURNING_ON:
253 HILOGD("NapiBluetoothHostObserver::OnStateChanged BREDR Turning on");
254 state = BluetoothState::STATE_TURNING_ON;
255 break;
256 case BTStateID::STATE_TURN_ON:
257 HILOGD("NapiBluetoothHostObserver::OnStateChanged BREDR Turn on");
258 state = BluetoothState::STATE_ON;
259 break;
260 case BTStateID::STATE_TURNING_OFF:
261 HILOGD("NapiBluetoothHostObserver::OnStateChanged BREDR Turning off");
262 state = BluetoothState::STATE_TURNING_OFF;
263 break;
264 case BTStateID::STATE_TURN_OFF:
265 HILOGD("NapiBluetoothHostObserver::OnStateChanged BREDR Turn off");
266 state = BluetoothState::STATE_OFF;
267 break;
268 default:
269 break;
270 }
271 } else if (transport == BT_TRANSPORT_BLE) {
272 switch (status) {
273 case BTStateID::STATE_TURNING_ON:
274 HILOGD("NapiBluetoothHostObserver::OnStateChanged BLE Turning on");
275 state = BluetoothState::STATE_BLE_TURNING_ON;
276 break;
277 case BTStateID::STATE_TURN_ON:
278 HILOGD("NapiBluetoothHostObserver::OnStateChanged BLE Turn on");
279 state = BluetoothState::STATE_BLE_ON;
280 break;
281 case BTStateID::STATE_TURNING_OFF:
282 HILOGD("NapiBluetoothHostObserver::OnStateChanged BLE Turning off");
283 state = BluetoothState::STATE_BLE_TURNING_OFF;
284 break;
285 case BTStateID::STATE_TURN_OFF:
286 HILOGD("NapiBluetoothHostObserver::OnStateChanged BLE Turn off");
287 state = BluetoothState::STATE_OFF;
288 break;
289 default:
290 break;
291 }
292 } else {
293 HILOGD("NapiBluetoothHostObserver::OnStateChanged error");
294 }
295 }
296
DealBredrPairComfirmed(const std::string & addr,const int reqType,const int number)297 void NapiBluetoothHostObserver::DealBredrPairComfirmed(const std::string &addr, const int reqType, const int number)
298 {
299 switch (reqType) {
300 case PAIR_CONFIRM_TYPE_PIN_CODE: {
301 HILOGD("PAIR_CONFIRM_TYPE_PIN_CODE");
302 break;
303 }
304 case PAIR_CONFIRM_TYPE_PASSKEY_DISPLAY: {
305 HILOGD("PAIR_CONFIRM_TYPE_PASSKEY_DISPLAY");
306 break;
307 }
308 case PAIR_CONFIRM_TYPE_PASSKEY_INPUT: {
309 HILOGD("PAIR_CONFIRM_TYPE_PASSKEY_INPUT");
310 break;
311 }
312 case PAIR_CONFIRM_TYPE_NUMERIC: {
313 HILOGD("PAIR_CONFIRM_TYPE_NUMERIC, please setPairConfirm.");
314 OnPairConfirmedCallBack(addr, number);
315 break;
316 }
317 case PAIR_CONFIRM_TYPE_CONSENT: {
318 HILOGD("PAIR_CONFIRM_TYPE_CONSENT, please setPairConfirm.");
319 OnPairConfirmedCallBack(addr, number);
320 break;
321 }
322 default:
323 break;
324 }
325 }
326
DealBlePairComfirmed(const std::string & addr,const int reqType,const int number)327 void NapiBluetoothHostObserver::DealBlePairComfirmed(const std::string &addr, const int reqType, const int number)
328 {
329 switch (reqType) {
330 case PAIR_CONFIRM_TYPE_PIN_CODE: {
331 HILOGD("PAIR_CONFIRM_TYPE_PIN_CODE");
332 break;
333 }
334 case PAIR_CONFIRM_TYPE_PASSKEY_DISPLAY: {
335 HILOGD("PAIR_CONFIRM_TYPE_PASSKEY_DISPLAY");
336 break;
337 }
338 case PAIR_CONFIRM_TYPE_PASSKEY_INPUT: {
339 HILOGD("PAIR_CONFIRM_TYPE_PASSKEY_INPUT");
340 break;
341 }
342 case PAIR_CONFIRM_TYPE_NUMERIC: {
343 HILOGD("PAIR_CONFIRM_TYPE_NUMERIC, please setPairConfirm.");
344 OnPairConfirmedCallBack(addr, number);
345 break;
346 }
347 }
348 }
349
UvQueueWorkOnPairConfirmedCallBack(uv_work_t * work,std::pair<std::string,int> & data)350 void NapiBluetoothHostObserver::UvQueueWorkOnPairConfirmedCallBack(uv_work_t *work, std::pair<std::string, int> &data)
351 {
352 HILOGI("OnPairConfirmedCallBack uv_work_t start");
353
354 if (work == nullptr) {
355 HILOGE("work is null");
356 return;
357 }
358 auto callbackData = (AfterWorkCallbackData<NapiBluetoothHostObserver,
359 decltype(&NapiBluetoothHostObserver::UvQueueWorkOnPairConfirmedCallBack),
360 std::pair<std::string, int>> *)work->data;
361 if (callbackData == nullptr) {
362 HILOGE("callbackData is null");
363 return;
364 }
365
366 napi_value result = 0;
367 napi_value callback = 0;
368 napi_value undefined = 0;
369 napi_value callResult = 0;
370 napi_get_undefined(callbackData->env, &undefined);
371 HILOGI("NapiBluetoothHostObserver::UvQueueWorkOnPairConfirmedCallBack: Addr is %{public}s", deviceAddr.c_str());
372 napi_create_object(callbackData->env, &result);
373 napi_value device = 0;
374 napi_create_string_utf8(
375 callbackData->env, callbackData->data.first.data(), callbackData->data.first.size(), &device);
376 napi_set_named_property(callbackData->env, result, "deviceId", device);
377 napi_value pinCode = 0;
378 napi_create_int32(callbackData->env, callbackData->data.second, &pinCode);
379 napi_set_named_property(callbackData->env, result, "pinCode", pinCode);
380
381 napi_get_reference_value(callbackData->env, callbackData->callback, &callback);
382 napi_call_function(callbackData->env, undefined, callback, ARGS_SIZE_ONE, &result, &callResult);
383 }
384
OnPairConfirmedCallBack(const std::string & deviceAddr,const int number)385 void NapiBluetoothHostObserver::OnPairConfirmedCallBack(const std::string &deviceAddr, const int number)
386 {
387 std::map<std::string, std::shared_ptr<BluetoothCallbackInfo>> observers = GetObserver();
388 if (!observers[REGISTER_PIN_REQUEST_TYPE]) {
389 HILOGE("NapiBluetoothHostObserver::OnPairConfirmedCallBack: This callback is not registered by ability.");
390 return;
391 }
392 HILOGD("NapiBluetoothHostObserver::OnPairConfirmedCallBack: %{public}s is registered by ability",
393 REGISTER_PIN_REQUEST_TYPE.c_str());
394 std::shared_ptr<BluetoothCallbackInfo> callbackInfo = observers[REGISTER_PIN_REQUEST_TYPE];
395 uv_loop_s *loop = nullptr;
396 napi_get_uv_event_loop(callbackInfo->env_, &loop);
397 if (loop == nullptr) {
398 HILOGE("loop instance is nullptr");
399 return;
400 }
401
402 auto callbackData = new (std::nothrow) AfterWorkCallbackData<NapiBluetoothHostObserver,
403 decltype(&NapiBluetoothHostObserver::UvQueueWorkOnPairConfirmedCallBack),
404 std::pair<std::string, int>>();
405 if (callbackData == nullptr) {
406 HILOGE("new callbackData failed");
407 return;
408 }
409
410 callbackData->object = this;
411 callbackData->function = &NapiBluetoothHostObserver::UvQueueWorkOnPairConfirmedCallBack;
412 callbackData->env = callbackInfo->env_;
413 callbackData->callback = callbackInfo->callback_;
414 callbackData->data = std::pair<std::string, int>(deviceAddr, number);
415
416 uv_work_t *work = new (std::nothrow) uv_work_t;
417 if (work == nullptr) {
418 HILOGE("new work failed");
419 delete callbackData;
420 callbackData = nullptr;
421 return;
422 }
423
424 work->data = (void *)callbackData;
425
426 int ret = uv_queue_work(
427 loop, work, [](uv_work_t *work) {}, AfterWorkCallback<decltype(callbackData)>);
428 if (ret != 0) {
429 delete callbackData;
430 callbackData = nullptr;
431 delete work;
432 work = nullptr;
433 }
434 }
435 } // namespace Bluetooth
436 } // namespace OHOS
437