• 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 #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