1 /*
2 * Copyright (C) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include "napi_bluetooth_connection_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_connection.h"
24
25 #include <uv.h>
26
27 namespace {
28 constexpr uint32_t FORMAT_PINCODE_LENGTH = 6;
29 } // namespace
30
31 namespace OHOS {
32 namespace Bluetooth {
OnDiscoveryStateChanged(int status)33 void NapiBluetoothConnectionObserver::OnDiscoveryStateChanged(int status)
34 {
35 switch (status) {
36 case DISCOVERY_STARTED:
37 HILOGD("DISCOVERY_STARTED(1)");
38 break;
39 case DISCOVERYING:
40 HILOGD("DISCOVERYING(2)");
41 break;
42 case DISCOVERY_STOPED:
43 HILOGD("DISCOVERY_STOPED(3)");
44 break;
45 default:
46 HILOGE("invaild status is %{public}d", status);
47 break;
48 }
49 }
50
UvQueueWorkOnDiscoveryResult(uv_work_t * work,std::shared_ptr<BluetoothRemoteDevice> & device)51 void NapiBluetoothConnectionObserver::UvQueueWorkOnDiscoveryResult(
52 uv_work_t *work, std::shared_ptr<BluetoothRemoteDevice> &device)
53 {
54 HILOGD("start");
55
56 if (work == nullptr) {
57 HILOGE("work is null");
58 return;
59 }
60 auto callbackData = (AfterWorkCallbackData<NapiBluetoothConnectionObserver,
61 decltype(&NapiBluetoothConnectionObserver::UvQueueWorkOnDiscoveryResult),
62 std::shared_ptr<BluetoothRemoteDevice>> *)work->data;
63 if (callbackData == nullptr) {
64 HILOGE("callbackData is null");
65 return;
66 }
67
68 napi_value result = 0;
69 napi_value value = 0;
70 napi_value callback = 0;
71 napi_value undefined = 0;
72 napi_value callResult = 0;
73 napi_get_undefined(callbackData->env, &undefined);
74 HILOGD("deviceId is %{public}s", GetEncryptAddr(device->GetDeviceAddr()).c_str());
75 napi_create_array(callbackData->env, &result);
76 napi_create_string_utf8(callbackData->env, device->GetDeviceAddr().c_str(), device->GetDeviceAddr().size(), &value);
77 napi_set_element(callbackData->env, result, 0, value);
78
79 napi_get_reference_value(callbackData->env, callbackData->callback, &callback);
80 napi_call_function(callbackData->env, undefined, callback, ARGS_SIZE_ONE, &result, &callResult);
81 }
82
OnDiscoveryResult(const BluetoothRemoteDevice & device)83 void NapiBluetoothConnectionObserver::OnDiscoveryResult(const BluetoothRemoteDevice &device)
84 {
85 HILOGD("start");
86 std::shared_ptr<BluetoothCallbackInfo> callbackInfo = GetCallback(REGISTER_DEVICE_FIND_TYPE);
87 if (callbackInfo == nullptr) {
88 HILOGD("This callback is not registered by ability.");
89 return;
90 }
91 uv_loop_s *loop = nullptr;
92 napi_get_uv_event_loop(callbackInfo->env_, &loop);
93 if (loop == nullptr) {
94 HILOGE("loop instance is nullptr");
95 return;
96 }
97
98 auto callbackData = new (std::nothrow) AfterWorkCallbackData<NapiBluetoothConnectionObserver,
99 decltype(&NapiBluetoothConnectionObserver::UvQueueWorkOnDiscoveryResult),
100 std::shared_ptr<BluetoothRemoteDevice>>();
101 if (callbackData == nullptr) {
102 HILOGE("new callbackData failed");
103 return;
104 }
105
106 callbackData->object = this;
107 callbackData->function = &NapiBluetoothConnectionObserver::UvQueueWorkOnDiscoveryResult;
108 callbackData->env = callbackInfo->env_;
109 callbackData->callback = callbackInfo->callback_;
110 std::shared_ptr<BluetoothRemoteDevice> remoteDevice = std::make_shared<BluetoothRemoteDevice>(device);
111 callbackData->data = remoteDevice;
112
113 AddDiscoveryDevice(remoteDevice);
114
115 uv_work_t *work = new (std::nothrow) uv_work_t;
116 if (work == nullptr) {
117 HILOGE("new work failed");
118 delete callbackData;
119 callbackData = nullptr;
120 return;
121 }
122
123 work->data = static_cast<void *>(callbackData);
124
125 int ret = uv_queue_work(loop, work, [](uv_work_t *work) {}, AfterWorkCallback<decltype(callbackData)>);
126 if (ret != 0) {
127 delete callbackData;
128 callbackData = nullptr;
129 delete work;
130 work = nullptr;
131 }
132 }
133
OnPairRequested(const BluetoothRemoteDevice & device)134 void NapiBluetoothConnectionObserver::OnPairRequested(const BluetoothRemoteDevice &device)
135 {
136 HILOGI("start");
137 BluetoothRemoteDevice remoteDevice;
138 if (device.GetTransportType() == BT_TRANSPORT_BREDR) {
139 remoteDevice = BluetoothHost::GetDefaultHost().GetRemoteDevice(device.GetDeviceAddr(), BT_TRANSPORT_BREDR);
140 } else if (device.GetTransportType() == BT_TRANSPORT_BLE) {
141 remoteDevice = BluetoothHost::GetDefaultHost().GetRemoteDevice(device.GetDeviceAddr(), BT_TRANSPORT_BLE);
142 }
143 remoteDevice.PairRequestReply(true);
144 }
145
OnPairConfirmed(const BluetoothRemoteDevice & device,int reqType,int number)146 void NapiBluetoothConnectionObserver::OnPairConfirmed(const BluetoothRemoteDevice &device, int reqType, int number)
147 {
148 HILOGI("OnPairConfirmed");
149 std::shared_ptr<PairConfirmedCallBackInfo> pairConfirmInfo =
150 std::make_shared<PairConfirmedCallBackInfo>(number, reqType, device.GetDeviceAddr());
151 OnPairConfirmedCallBack(pairConfirmInfo);
152 }
153
OnScanModeChanged(int mode)154 void NapiBluetoothConnectionObserver::OnScanModeChanged(int mode)
155 {
156 HILOGI("mode is %{public}d", mode);
157 }
158
OnDeviceNameChanged(const std::string & deviceName)159 void NapiBluetoothConnectionObserver::OnDeviceNameChanged(const std::string &deviceName)
160 {
161 HILOGI("name is %{public}s", deviceName.c_str());
162 }
163
OnDeviceAddrChanged(const std::string & address)164 void NapiBluetoothConnectionObserver::OnDeviceAddrChanged(const std::string &address)
165 {
166 HILOGI("address is %{public}s", GetEncryptAddr(address).c_str());
167 }
168
RegisterCallback(const std::string & callbackName,const std::shared_ptr<BluetoothCallbackInfo> & callback)169 void NapiBluetoothConnectionObserver::RegisterCallback(
170 const std::string &callbackName, const std::shared_ptr<BluetoothCallbackInfo> &callback)
171 {
172 std::lock_guard<std::mutex> lock(callbacksMapLock_);
173 callbacks_[callbackName] = callback;
174 }
175
DeRegisterCallback(const std::string & callbackName)176 void NapiBluetoothConnectionObserver::DeRegisterCallback(const std::string &callbackName)
177 {
178 std::lock_guard<std::mutex> lock(callbacksMapLock_);
179 callbacks_.erase(callbackName);
180 }
181
GetCallback(const std::string & callbackName)182 std::shared_ptr<BluetoothCallbackInfo> NapiBluetoothConnectionObserver::GetCallback(const std::string &callbackName)
183 {
184 std::lock_guard<std::mutex> lock(callbacksMapLock_);
185 if (callbacks_.find(callbackName) != callbacks_.end()) {
186 return callbacks_[callbackName];
187 }
188 return nullptr;
189 }
190
GetFormatPinCode(const uint32_t pinType,const uint32_t pinCode)191 static std::string GetFormatPinCode(const uint32_t pinType, const uint32_t pinCode)
192 {
193 std::string pinCodeStr = std::to_string(pinCode);
194 if (pinType != PIN_TYPE_CONFIRM_PASSKEY && pinType != PIN_TYPE_NOTIFY_PASSKEY) {
195 return pinCodeStr;
196 }
197 while (pinCodeStr.length() < FORMAT_PINCODE_LENGTH) {
198 pinCodeStr = "0" + pinCodeStr;
199 }
200 return pinCodeStr;
201 }
202
UvQueueWorkOnPairConfirmedCallBack(uv_work_t * work,const std::shared_ptr<PairConfirmedCallBackInfo> & pairConfirmInfo)203 void NapiBluetoothConnectionObserver::UvQueueWorkOnPairConfirmedCallBack(
204 uv_work_t *work, const std::shared_ptr<PairConfirmedCallBackInfo> &pairConfirmInfo)
205 {
206 HILOGI("start");
207 if (work == nullptr) {
208 HILOGE("work is null");
209 return;
210 }
211 auto callbackData = (AfterWorkCallbackData<NapiBluetoothConnectionObserver,
212 decltype(&NapiBluetoothConnectionObserver::UvQueueWorkOnPairConfirmedCallBack),
213 std::shared_ptr<PairConfirmedCallBackInfo>> *)work->data;
214 if (callbackData == nullptr) {
215 HILOGE("callbackData is null");
216 return;
217 }
218
219 napi_value result = 0;
220 napi_value callback = 0;
221 napi_value undefined = 0;
222 napi_value callResult = 0;
223 napi_get_undefined(callbackData->env, &undefined);
224 HILOGI("Addr is %{public}s", GetEncryptAddr(callbackData->data->deviceAddr).c_str());
225 napi_create_object(callbackData->env, &result);
226 napi_value device = 0;
227 napi_create_string_utf8(
228 callbackData->env, callbackData->data->deviceAddr.c_str(), callbackData->data->deviceAddr.size(), &device);
229 napi_set_named_property(callbackData->env, result, "deviceId", device);
230 napi_value pinCode = 0;
231 std::string pinCodeStr = GetFormatPinCode(callbackData->data->pinType, callbackData->data->number);
232 napi_create_string_utf8(callbackData->env, pinCodeStr.c_str(), pinCodeStr.size(), &pinCode);
233 napi_set_named_property(callbackData->env, result, "pinCode", pinCode);
234 napi_value pinType = 0;
235 napi_create_int32(callbackData->env, callbackData->data->pinType, &pinType);
236 napi_set_named_property(callbackData->env, result, "pinType", pinType);
237
238 napi_get_reference_value(callbackData->env, callbackData->callback, &callback);
239 napi_call_function(callbackData->env, undefined, callback, ARGS_SIZE_ONE, &result, &callResult);
240 }
241
OnPairConfirmedCallBack(const std::shared_ptr<PairConfirmedCallBackInfo> & pairConfirmInfo)242 void NapiBluetoothConnectionObserver::OnPairConfirmedCallBack(
243 const std::shared_ptr<PairConfirmedCallBackInfo> &pairConfirmInfo)
244 {
245 HILOGI("start");
246 std::shared_ptr<BluetoothCallbackInfo> callbackInfo = GetCallback(REGISTER_PIN_REQUEST_TYPE);
247 if (callbackInfo == nullptr) {
248 HILOGI("This callback is not registered by ability.");
249 return;
250 }
251 uv_loop_s *loop = nullptr;
252 napi_get_uv_event_loop(callbackInfo->env_, &loop);
253 if (loop == nullptr) {
254 HILOGE("loop instance is nullptr");
255 return;
256 }
257
258 auto callbackData = new (std::nothrow) AfterWorkCallbackData<NapiBluetoothConnectionObserver,
259 decltype(&NapiBluetoothConnectionObserver::UvQueueWorkOnPairConfirmedCallBack),
260 std::shared_ptr<PairConfirmedCallBackInfo>>();
261 if (callbackData == nullptr) {
262 HILOGE("new callbackData failed");
263 return;
264 }
265
266 callbackData->object = this;
267 callbackData->function = &NapiBluetoothConnectionObserver::UvQueueWorkOnPairConfirmedCallBack;
268 callbackData->env = callbackInfo->env_;
269 callbackData->callback = callbackInfo->callback_;
270 callbackData->data = pairConfirmInfo;
271
272 uv_work_t *work = new (std::nothrow) uv_work_t;
273 if (work == nullptr) {
274 HILOGE("new work failed");
275 delete callbackData;
276 callbackData = nullptr;
277 return;
278 }
279
280 work->data = static_cast<void *>(callbackData);
281
282 int ret = uv_queue_work(loop, work, [](uv_work_t *work) {}, AfterWorkCallback<decltype(callbackData)>);
283 if (ret != 0) {
284 delete callbackData;
285 callbackData = nullptr;
286 delete work;
287 work = nullptr;
288 }
289 }
290 } // namespace Bluetooth
291 } // namespace OHOS
292