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_host.h"
18 #include "bluetooth_log.h"
19 #include "bluetooth_utils.h"
20
21 #include "napi/native_api.h"
22 #include "napi/native_node_api.h"
23 #include "napi_bluetooth_host.h"
24
25 #include <uv.h>
26
27 namespace OHOS {
28 namespace Bluetooth {
UvQueueWorkOnStateChanged(uv_work_t * work,BluetoothState & state)29 void NapiBluetoothHostObserver::UvQueueWorkOnStateChanged(uv_work_t *work, BluetoothState &state)
30 {
31 HILOGI("start");
32
33 if (work == nullptr) {
34 HILOGE("work is null");
35 return;
36 }
37 auto callbackData = (AfterWorkCallbackData<NapiBluetoothHostObserver,
38 decltype(&NapiBluetoothHostObserver::UvQueueWorkOnStateChanged),
39 BluetoothState> *)work->data;
40 if (callbackData == nullptr) {
41 HILOGE("callbackData is null");
42 return;
43 }
44
45 napi_value result = 0;
46 napi_value callback = 0;
47 napi_value undefined = 0;
48 napi_value callResult = 0;
49
50 napi_get_undefined(callbackData->env, &undefined);
51 HILOGD("state is %{public}d", state);
52 napi_create_int32(callbackData->env, static_cast<int32_t>(state), &result);
53 napi_get_reference_value(callbackData->env, callbackData->callback, &callback);
54 napi_call_function(callbackData->env, undefined, callback, ARGS_SIZE_ONE, &result, &callResult);
55 }
56
OnStateChanged(const int transport,const int status)57 void NapiBluetoothHostObserver::OnStateChanged(const int transport, const int status)
58 {
59 HILOGD("start");
60 BluetoothState state = BluetoothState::STATE_OFF;
61 if (!DealStateChange(transport, status, state)) {
62 return;
63 }
64 std::shared_ptr<BluetoothCallbackInfo> callbackInfo = GetCallbackInfoByType(REGISTER_STATE_CHANGE_TYPE);
65 if (callbackInfo == nullptr) {
66 HILOGI("This callback is not registered by ability.");
67 return;
68 }
69 uv_loop_s *loop = nullptr;
70 napi_get_uv_event_loop(callbackInfo->env_, &loop);
71 if (loop == nullptr) {
72 HILOGE("loop instance is nullptr");
73 return;
74 }
75
76 auto callbackData = new (std::nothrow) AfterWorkCallbackData<NapiBluetoothHostObserver,
77 decltype(&NapiBluetoothHostObserver::UvQueueWorkOnStateChanged),
78 BluetoothState>();
79 if (callbackData == nullptr) {
80 HILOGE("new callbackData failed");
81 return;
82 }
83
84 callbackData->object = this;
85 callbackData->function = &NapiBluetoothHostObserver::UvQueueWorkOnStateChanged;
86 callbackData->env = callbackInfo->env_;
87 callbackData->callback = callbackInfo->callback_;
88 callbackData->data = state;
89
90 uv_work_t *work = new (std::nothrow) uv_work_t;
91 if (work == nullptr) {
92 HILOGE("new work failed");
93 delete callbackData;
94 callbackData = nullptr;
95 return;
96 }
97 work->data = (void *)callbackData;
98 int ret = uv_queue_work(
99 loop, work, [](uv_work_t *work) {}, AfterWorkCallback<decltype(callbackData)>);
100 if (ret != 0) {
101 delete callbackData;
102 callbackData = nullptr;
103 delete work;
104 work = nullptr;
105 }
106 }
107
OnDiscoveryStateChanged(int status)108 void NapiBluetoothHostObserver::OnDiscoveryStateChanged(int status)
109 {
110 switch (status) {
111 case DISCOVERY_STARTED:
112 HILOGD("DISCOVERY_STARTED(1)");
113 break;
114 case DISCOVERYING:
115 HILOGD("DISCOVERYING(2)");
116 break;
117 case DISCOVERY_STOPED:
118 HILOGD("DISCOVERY_STOPED(3)");
119 break;
120 default:
121 HILOGE("invaild status is %{public}d", 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("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("deviceId is %{public}s", GetEncryptAddr(device->GetDeviceAddr()).c_str());
150 napi_create_array(callbackData->env, &result);
151 napi_create_string_utf8(callbackData->env, device->GetDeviceAddr().c_str(), device->GetDeviceAddr().size(), &value);
152 napi_set_element(callbackData->env, result, 0, value);
153
154 napi_get_reference_value(callbackData->env, callbackData->callback, &callback);
155 napi_call_function(callbackData->env, undefined, callback, ARGS_SIZE_ONE, &result, &callResult);
156 }
157
OnDiscoveryResult(const BluetoothRemoteDevice & device)158 void NapiBluetoothHostObserver::OnDiscoveryResult(const BluetoothRemoteDevice &device)
159 {
160 HILOGI("start");
161 std::shared_ptr<BluetoothCallbackInfo> callbackInfo = GetCallbackInfoByType(REGISTER_DEVICE_FIND_TYPE);
162 if (callbackInfo == nullptr) {
163 HILOGI("This callback is not registered by ability.");
164 return;
165 }
166 uv_loop_s *loop = nullptr;
167 napi_get_uv_event_loop(callbackInfo->env_, &loop);
168 if (loop == nullptr) {
169 HILOGE("loop instance is nullptr");
170 return;
171 }
172
173 auto callbackData = new (std::nothrow) AfterWorkCallbackData<NapiBluetoothHostObserver,
174 decltype(&NapiBluetoothHostObserver::UvQueueWorkOnDiscoveryResult),
175 std::shared_ptr<BluetoothRemoteDevice>>();
176 if (callbackData == nullptr) {
177 HILOGE("new callbackData failed");
178 return;
179 }
180
181 callbackData->object = this;
182 callbackData->function = &NapiBluetoothHostObserver::UvQueueWorkOnDiscoveryResult;
183 callbackData->env = callbackInfo->env_;
184 callbackData->callback = callbackInfo->callback_;
185 std::shared_ptr<BluetoothRemoteDevice> remoteDevice = std::make_shared<BluetoothRemoteDevice>(device);
186 callbackData->data = remoteDevice;
187
188 AddDiscoveryDevice(remoteDevice);
189
190 uv_work_t *work = new (std::nothrow) uv_work_t;
191 if (work == nullptr) {
192 HILOGE("new work failed");
193 delete callbackData;
194 callbackData = nullptr;
195 return;
196 }
197
198 work->data = (void *)callbackData;
199
200 int ret = uv_queue_work(
201 loop, work, [](uv_work_t *work) {}, AfterWorkCallback<decltype(callbackData)>);
202 if (ret != 0) {
203 delete callbackData;
204 callbackData = nullptr;
205 delete work;
206 work = nullptr;
207 }
208 }
209
OnPairRequested(const BluetoothRemoteDevice & device)210 void NapiBluetoothHostObserver::OnPairRequested(const BluetoothRemoteDevice &device)
211 {
212 HILOGI("start");
213 BluetoothRemoteDevice remoteDevice;
214 if (device.GetTransportType() == BT_TRANSPORT_BREDR) {
215 remoteDevice = BluetoothHost::GetDefaultHost().GetRemoteDevice(device.GetDeviceAddr(), BT_TRANSPORT_BREDR);
216 } else if (device.GetTransportType() == BT_TRANSPORT_BLE) {
217 remoteDevice = BluetoothHost::GetDefaultHost().GetRemoteDevice(device.GetDeviceAddr(), BT_TRANSPORT_BLE);
218 }
219 remoteDevice.PairRequestReply(true);
220 }
221
OnPairConfirmed(const BluetoothRemoteDevice & device,int reqType,int number)222 void NapiBluetoothHostObserver::OnPairConfirmed(const BluetoothRemoteDevice &device, int reqType, int number)
223 {
224 std::string remoteAddr = device.GetDeviceAddr();
225 int transportType = device.GetTransportType();
226 HILOGI("remote deviceId is %{public}s, transportType is %{public}d",
227 GetEncryptAddr(remoteAddr).c_str(), transportType);
228 if (transportType == BT_TRANSPORT_BREDR) {
229 DealBredrPairComfirmed(remoteAddr, reqType, number);
230 } else if (transportType == BT_TRANSPORT_BLE) {
231 DealBlePairComfirmed(remoteAddr, reqType, number);
232 }
233 }
234
OnScanModeChanged(int mode)235 void NapiBluetoothHostObserver::OnScanModeChanged(int mode)
236 {
237 HILOGI("mode is %{public}d", mode);
238 }
239
OnDeviceNameChanged(const std::string & deviceName)240 void NapiBluetoothHostObserver::OnDeviceNameChanged(const std::string &deviceName)
241 {
242 HILOGI("name is %{public}s", deviceName.c_str());
243 }
244
OnDeviceAddrChanged(const std::string & address)245 void NapiBluetoothHostObserver::OnDeviceAddrChanged(const std::string &address)
246 {
247 HILOGI("address is %{public}s", GetEncryptAddr(address).c_str());
248 }
249
EnableBt()250 void NapiBluetoothHostObserver::EnableBt()
251 {
252 HILOGI("start");
253 BluetoothHost *host = &BluetoothHost::GetDefaultHost();
254 bool enabled = host->EnableBt();
255 if (!enabled) {
256 HILOGE("failed");
257 }
258 SetCurrentAppOperate(false);
259 }
260
DisableBle()261 void NapiBluetoothHostObserver::DisableBle()
262 {
263 HILOGI("start");
264 BluetoothHost *host = &BluetoothHost::GetDefaultHost();
265 bool enabled = host->DisableBle();
266 if (!enabled) {
267 HILOGE("failed");
268 }
269 SetCurrentAppOperate(false);
270 }
271
DealStateChange(const int transport,const int status,BluetoothState & state)272 bool NapiBluetoothHostObserver::DealStateChange(const int transport, const int status, BluetoothState &state)
273 {
274 HILOGD("transport is %{public}d, status is %{public}d", transport, status);
275 bool isCallback = true;
276 if (transport == BT_TRANSPORT_BREDR) {
277 switch (status) {
278 case BTStateID::STATE_TURNING_ON:
279 HILOGD("STATE_TURNING_ON(1)");
280 state = BluetoothState::STATE_TURNING_ON;
281 break;
282 case BTStateID::STATE_TURN_ON:
283 HILOGD("STATE_ON(2)");
284 state = BluetoothState::STATE_ON;
285 break;
286 case BTStateID::STATE_TURNING_OFF:
287 HILOGD("STATE_TURNING_OFF(3)");
288 state = BluetoothState::STATE_TURNING_OFF;
289 break;
290 case BTStateID::STATE_TURN_OFF: {
291 HILOGD("STATE_OFF(0)");
292 isCallback = false;
293 BluetoothHost *host = &BluetoothHost::GetDefaultHost();
294 if (host->IsBleEnabled() && GetCurrentAppOperate()) {
295 DisableBle();
296 }
297 break;
298 }
299 default:
300 break;
301 }
302 } else if (transport == BT_TRANSPORT_BLE) {
303 switch (status) {
304 case BTStateID::STATE_TURNING_ON:
305 HILOGD("STATE_BLE_TURNING_ON(4)");
306 state = BluetoothState::STATE_BLE_TURNING_ON;
307 break;
308 case BTStateID::STATE_TURN_ON:
309 HILOGD("STATE_BLE_ON(5)");
310 state = BluetoothState::STATE_BLE_ON;
311 if (GetCurrentAppOperate()) {
312 EnableBt();
313 }
314 break;
315 case BTStateID::STATE_TURNING_OFF:
316 HILOGD("STATE_BLE_TURNING_OFF(6)");
317 state = BluetoothState::STATE_BLE_TURNING_OFF;
318 break;
319 case BTStateID::STATE_TURN_OFF:
320 HILOGD("STATE_OFF(0)");
321 state = BluetoothState::STATE_OFF;
322 break;
323 default:
324 break;
325 }
326 }
327 return isCallback;
328 }
329
DealBredrPairComfirmed(const std::string & addr,const int reqType,const int number)330 void NapiBluetoothHostObserver::DealBredrPairComfirmed(const std::string &addr, const int reqType, const int number)
331 {
332 switch (reqType) {
333 case PAIR_CONFIRM_TYPE_PIN_CODE:
334 HILOGD("PAIR_CONFIRM_TYPE_PIN_CODE(1)");
335 break;
336 case PAIR_CONFIRM_TYPE_PASSKEY_DISPLAY:
337 HILOGD("PAIR_CONFIRM_TYPE_PASSKEY_DISPLAY(2)");
338 OnPairConfirmedCallBack(addr, number);
339 break;
340 case PAIR_CONFIRM_TYPE_PASSKEY_INPUT:
341 HILOGD("PAIR_CONFIRM_TYPE_PASSKEY_INPUT(3)");
342 break;
343 case PAIR_CONFIRM_TYPE_NUMERIC:
344 HILOGD("PAIR_CONFIRM_TYPE_NUMERIC(4)");
345 OnPairConfirmedCallBack(addr, number);
346 break;
347 case PAIR_CONFIRM_TYPE_CONSENT:
348 HILOGD("PAIR_CONFIRM_TYPE_CONSENT(5)");
349 OnPairConfirmedCallBack(addr, number);
350 break;
351 default:
352 HILOGE("Invalid reqType is %{public}d", reqType);
353 break;
354 }
355 }
356
DealBlePairComfirmed(const std::string & addr,const int reqType,const int number)357 void NapiBluetoothHostObserver::DealBlePairComfirmed(const std::string &addr, const int reqType, const int number)
358 {
359 switch (reqType) {
360 case PAIR_CONFIRM_TYPE_PIN_CODE:
361 HILOGD("PAIR_CONFIRM_TYPE_PIN_CODE(1)");
362 break;
363 case PAIR_CONFIRM_TYPE_PASSKEY_DISPLAY:
364 HILOGD("PAIR_CONFIRM_TYPE_PASSKEY_DISPLAY(2)");
365 break;
366 case PAIR_CONFIRM_TYPE_PASSKEY_INPUT:
367 HILOGD("PAIR_CONFIRM_TYPE_PASSKEY_INPUT(3)");
368 break;
369 case PAIR_CONFIRM_TYPE_NUMERIC:
370 HILOGD("PAIR_CONFIRM_TYPE_NUMERIC(4)");
371 OnPairConfirmedCallBack(addr, number);
372 break;
373 default:
374 HILOGE("Invalid reqType is %{public}d", reqType);
375 break;
376 }
377 }
378
UvQueueWorkOnPairConfirmedCallBack(uv_work_t * work,std::pair<std::string,int> & data)379 void NapiBluetoothHostObserver::UvQueueWorkOnPairConfirmedCallBack(uv_work_t *work, std::pair<std::string, int> &data)
380 {
381 HILOGI("start");
382 if (work == nullptr) {
383 HILOGE("work is null");
384 return;
385 }
386 auto callbackData = (AfterWorkCallbackData<NapiBluetoothHostObserver,
387 decltype(&NapiBluetoothHostObserver::UvQueueWorkOnPairConfirmedCallBack),
388 std::pair<std::string, int>> *)work->data;
389 if (callbackData == nullptr) {
390 HILOGE("callbackData is null");
391 return;
392 }
393
394 napi_value result = 0;
395 napi_value callback = 0;
396 napi_value undefined = 0;
397 napi_value callResult = 0;
398 napi_get_undefined(callbackData->env, &undefined);
399 HILOGI("Addr is %{public}s", GetEncryptAddr(deviceAddr).c_str());
400 napi_create_object(callbackData->env, &result);
401 napi_value device = 0;
402 napi_create_string_utf8(
403 callbackData->env, callbackData->data.first.data(), callbackData->data.first.size(), &device);
404 napi_set_named_property(callbackData->env, result, "deviceId", device);
405 napi_value pinCode = 0;
406 napi_create_int32(callbackData->env, callbackData->data.second, &pinCode);
407 napi_set_named_property(callbackData->env, result, "pinCode", pinCode);
408
409 napi_get_reference_value(callbackData->env, callbackData->callback, &callback);
410 napi_call_function(callbackData->env, undefined, callback, ARGS_SIZE_ONE, &result, &callResult);
411 }
412
OnPairConfirmedCallBack(const std::string & deviceAddr,const int number)413 void NapiBluetoothHostObserver::OnPairConfirmedCallBack(const std::string &deviceAddr, const int number)
414 {
415 HILOGI("start");
416 std::shared_ptr<BluetoothCallbackInfo> callbackInfo = GetCallbackInfoByType(REGISTER_PIN_REQUEST_TYPE);
417 if (callbackInfo == nullptr) {
418 HILOGI("This callback is not registered by ability.");
419 return;
420 }
421 uv_loop_s *loop = nullptr;
422 napi_get_uv_event_loop(callbackInfo->env_, &loop);
423 if (loop == nullptr) {
424 HILOGE("loop instance is nullptr");
425 return;
426 }
427
428 auto callbackData = new (std::nothrow) AfterWorkCallbackData<NapiBluetoothHostObserver,
429 decltype(&NapiBluetoothHostObserver::UvQueueWorkOnPairConfirmedCallBack),
430 std::pair<std::string, int>>();
431 if (callbackData == nullptr) {
432 HILOGE("new callbackData failed");
433 return;
434 }
435
436 callbackData->object = this;
437 callbackData->function = &NapiBluetoothHostObserver::UvQueueWorkOnPairConfirmedCallBack;
438 callbackData->env = callbackInfo->env_;
439 callbackData->callback = callbackInfo->callback_;
440 callbackData->data = std::pair<std::string, int>(deviceAddr, number);
441
442 uv_work_t *work = new (std::nothrow) uv_work_t;
443 if (work == nullptr) {
444 HILOGE("new work failed");
445 delete callbackData;
446 callbackData = nullptr;
447 return;
448 }
449
450 work->data = (void *)callbackData;
451
452 int ret = uv_queue_work(
453 loop, work, [](uv_work_t *work) {}, AfterWorkCallback<decltype(callbackData)>);
454 if (ret != 0) {
455 delete callbackData;
456 callbackData = nullptr;
457 delete work;
458 work = nullptr;
459 }
460 }
461 } // namespace Bluetooth
462 } // namespace OHOS