• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2025 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 
16 #include "bluetooth_scan_result_callback_napi.h"
17 
18 #include "ipc_object_stub.h"
19 #include "ipc_skeleton.h"
20 #include "js_native_api.h"
21 #include "message_option.h"
22 #include "message_parcel.h"
23 #include "napi/native_common.h"
24 #include "uv.h"
25 
26 #include "constant_definition.h"
27 #include "napi_util.h"
28 
29 namespace OHOS {
30 namespace Location {
31 static std::mutex g_regCallbackMutex;
32 static std::vector<napi_ref> g_registerCallbacks;
BluetoothScanResultCallbackNapi()33 BluetoothScanResultCallbackNapi::BluetoothScanResultCallbackNapi()
34 {
35     env_ = nullptr;
36     handlerCb_ = nullptr;
37 }
38 
~BluetoothScanResultCallbackNapi()39 BluetoothScanResultCallbackNapi::~BluetoothScanResultCallbackNapi()
40 {
41 }
42 
OnRemoteRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)43 int BluetoothScanResultCallbackNapi::OnRemoteRequest(
44     uint32_t code, MessageParcel& data, MessageParcel& reply, MessageOption& option)
45 {
46     LBSLOGD(BLUETOOTH_CALLBACK, "BluetoothScanResultCallbackNapi::OnRemoteRequest!");
47     if (data.ReadInterfaceToken() != GetDescriptor()) {
48         LBSLOGE(BLUETOOTH_CALLBACK, "invalid token.");
49         return -1;
50     }
51     switch (code) {
52         case RECEIVE_INFO_EVENT: {
53             std::unique_ptr<BluetoothScanResult> res = BluetoothScanResult::Unmarshalling(data);
54             OnBluetoothScanResultChange(res);
55             break;
56         }
57         default: {
58             IPCObjectStub::OnRemoteRequest(code, data, reply, option);
59             break;
60         }
61     }
62     return 0;
63 }
64 
GetEnv()65 napi_env BluetoothScanResultCallbackNapi::GetEnv()
66 {
67     std::unique_lock<std::mutex> guard(mutex_);
68     return env_;
69 }
70 
SetEnv(const napi_env & env)71 void BluetoothScanResultCallbackNapi::SetEnv(const napi_env& env)
72 {
73     std::unique_lock<std::mutex> guard(mutex_);
74     env_ = env;
75 }
76 
GetHandleCb()77 napi_ref BluetoothScanResultCallbackNapi::GetHandleCb()
78 {
79     std::unique_lock<std::mutex> guard(mutex_);
80     return handlerCb_;
81 }
82 
SetHandleCb(const napi_ref & handlerCb)83 void BluetoothScanResultCallbackNapi::SetHandleCb(const napi_ref& handlerCb)
84 {
85     {
86         std::unique_lock<std::mutex> guard(mutex_);
87         handlerCb_ = handlerCb;
88     }
89     std::unique_lock<std::mutex> guard(g_regCallbackMutex);
90     g_registerCallbacks.emplace_back(handlerCb);
91 }
92 
FindBlueToothCallback(napi_ref cb)93 bool FindBlueToothCallback(napi_ref cb)
94 {
95     std::unique_lock<std::mutex> guard(g_regCallbackMutex);
96     auto iter = std::find(g_registerCallbacks.begin(), g_registerCallbacks.end(), cb);
97     if (iter == g_registerCallbacks.end()) {
98         return false;
99     }
100     return true;
101 }
102 
DeleteBlueToothCallback(napi_ref cb)103 void DeleteBlueToothCallback(napi_ref cb)
104 {
105     std::unique_lock<std::mutex> guard(g_regCallbackMutex);
106     for (auto iter = g_registerCallbacks.begin(); iter != g_registerCallbacks.end(); iter++) {
107         if (*iter == cb) {
108             iter = g_registerCallbacks.erase(iter);
109             break;
110         }
111     }
112 }
113 
DoSendWork(uv_loop_s * & loop,uv_work_t * & work)114 void BluetoothScanResultCallbackNapi::DoSendWork(uv_loop_s*& loop, uv_work_t*& work)
115 {
116     uv_queue_work(loop, work, [](uv_work_t* work) {}, [](uv_work_t* work, int status) {
117         if (work == nullptr) {
118             return;
119         }
120         napi_handle_scope scope = nullptr;
121         auto context = static_cast<BluetoothScanResultAsyncContext*>(work->data);
122         if (context == nullptr) {
123             LBSLOGE(BLUETOOTH_CALLBACK, "context == nullptr");
124             delete work;
125             return;
126         }
127         if (context->env == nullptr || context->bluetoothScanResult == nullptr) {
128             LBSLOGE(BLUETOOTH_CALLBACK, "bluetoothScanResult == nullptr");
129             delete context;
130             delete work;
131             return;
132         }
133         if (!FindBlueToothCallback(context->callback[0])) {
134             LBSLOGE(BLUETOOTH_CALLBACK, "no valid callback");
135             delete context;
136             delete work;
137             return;
138         }
139         napi_open_handle_scope(context->env, &scope);
140         if (scope == nullptr) {
141             LBSLOGE(BLUETOOTH_CALLBACK, "scope == nullptr");
142             DELETE_SCOPE_CONTEXT_WORK(context->env, scope, context, work);
143             return;
144         }
145         napi_value jsEvent = nullptr;
146         CHK_NAPI_ERR_CLOSE_SCOPE(context->env, napi_create_object(context->env, &jsEvent), scope, context, work);
147         BluetoothScanResultToJs(context->env, context->bluetoothScanResult, jsEvent);
148         if (context->callback[0] != nullptr) {
149             napi_value undefine = nullptr;
150             napi_value handler = nullptr;
151             CHK_NAPI_ERR_CLOSE_SCOPE(context->env, napi_get_undefined(context->env, &undefine),
152                 scope, context, work);
153             CHK_NAPI_ERR_CLOSE_SCOPE(context->env,
154                 napi_get_reference_value(context->env, context->callback[0], &handler), scope, context, work);
155             if (napi_call_function(context->env, nullptr, handler, 1, &jsEvent, &undefine) != napi_ok) {
156                 LBSLOGE(BLUETOOTH_CALLBACK, "Report location failed");
157             }
158         }
159         NAPI_CALL_RETURN_VOID(context->env, napi_close_handle_scope(context->env, scope));
160         delete context;
161         delete work;
162     });
163 }
164 
OnBluetoothScanResultChange(const std::unique_ptr<BluetoothScanResult> & bluetoothScanResult)165 void BluetoothScanResultCallbackNapi::OnBluetoothScanResultChange(
166     const std::unique_ptr<BluetoothScanResult>& bluetoothScanResult)
167 {
168     std::unique_lock<std::mutex> guard(mutex_);
169     uv_loop_s *loop = nullptr;
170     if (env_ == nullptr) {
171         LBSLOGD(BLUETOOTH_CALLBACK, "env_ is nullptr.");
172         return;
173     }
174     if (handlerCb_ == nullptr) {
175         LBSLOGE(BLUETOOTH_CALLBACK, "handler is nullptr.");
176         return;
177     }
178     NAPI_CALL_RETURN_VOID(env_, napi_get_uv_event_loop(env_, &loop));
179     if (loop == nullptr) {
180         LBSLOGE(BLUETOOTH_CALLBACK, "loop == nullptr.");
181         return;
182     }
183     uv_work_t *work = new (std::nothrow) uv_work_t;
184     if (work == nullptr) {
185         LBSLOGE(BLUETOOTH_CALLBACK, "work == nullptr.");
186         return;
187     }
188     auto context = new (std::nothrow) BluetoothScanResultAsyncContext(env_);
189     if (context == nullptr) {
190         LBSLOGE(BLUETOOTH_CALLBACK, "context == nullptr.");
191         delete work;
192         return;
193     }
194     if (!InitContext(context)) {
195         LBSLOGE(BLUETOOTH_CALLBACK, "InitContext fail");
196         delete work;
197         delete context;
198         return;
199     }
200     context->bluetoothScanResult = std::make_unique<BluetoothScanResult>(*bluetoothScanResult);
201     work->data = context;
202     DoSendWork(loop, work);
203 }
204 
DeleteHandler()205 void BluetoothScanResultCallbackNapi::DeleteHandler()
206 {
207     LBSLOGD(BLUETOOTH_CALLBACK, "before DeleteHandler");
208     std::unique_lock<std::mutex> guard(mutex_);
209     if (env_ == nullptr) {
210         LBSLOGE(BLUETOOTH_CALLBACK, "env is nullptr.");
211         return;
212     }
213     DeleteBlueToothCallback(handlerCb_);
214     if (handlerCb_ != nullptr) {
215         NAPI_CALL_RETURN_VOID(env_, napi_delete_reference(env_, handlerCb_));
216         handlerCb_ = nullptr;
217     }
218 }
219 } // namespace Location
220 } // namespace OHOS
221