• 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 #ifndef LOG_TAG
16 #define LOG_TAG "bt_napi_ble_scanner"
17 #endif
18 
19 #include "napi_bluetooth_ble_scanner.h"
20 #include "bluetooth_log.h"
21 #include "bluetooth_errorcode.h"
22 #include "napi_bluetooth_utils.h"
23 #include "napi_bluetooth_error.h"
24 #include "napi_ha_event_utils.h"
25 
26 namespace OHOS {
27 namespace Bluetooth {
28 
29 thread_local napi_ref NapiBleScanner::consRef_ = nullptr;
30 
DefineBleScannerJSClass(napi_env env)31 void NapiBleScanner::DefineBleScannerJSClass(napi_env env)
32 {
33     napi_property_descriptor properties[] = {
34         DECLARE_NAPI_FUNCTION("startScan", StartScan),
35         DECLARE_NAPI_FUNCTION("stopScan", StopScan),
36         DECLARE_NAPI_FUNCTION("on", On),
37         DECLARE_NAPI_FUNCTION("off", Off),
38     };
39 
40     napi_value constructor = nullptr;
41     napi_define_class(env, "BleScanner", NAPI_AUTO_LENGTH, BleScannerConstructor, nullptr,
42         sizeof(properties) / sizeof(properties[0]), properties, &constructor);
43     napi_create_reference(env, constructor, 1, &consRef_);
44 }
45 
BleScannerConstructor(napi_env env,napi_callback_info info)46 napi_value NapiBleScanner::BleScannerConstructor(napi_env env, napi_callback_info info)
47 {
48     napi_value thisVar = nullptr;
49     napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
50     NapiBleScanner* bleScanner = new NapiBleScanner();
51 
52     auto status = napi_wrap(
53         env, thisVar, bleScanner,
54         [](napi_env env, void* data, void* hint) {
55             NapiBleScanner* scanner = static_cast<NapiBleScanner*>(data);
56             if (scanner) {
57                 delete scanner;
58                 scanner = nullptr;
59             }
60         },
61         nullptr,
62         nullptr);
63     if (status != napi_ok) {
64         HILOGE("napi_wrap failed");
65         delete bleScanner;
66         bleScanner = nullptr;
67     }
68 
69     return thisVar;
70 }
71 
CreateBleScanner(napi_env env,napi_callback_info info)72 napi_value NapiBleScanner::CreateBleScanner(napi_env env, napi_callback_info info)
73 {
74     HILOGI("enter");
75     napi_value result;
76     napi_value constructor = nullptr;
77     napi_get_reference_value(env, consRef_, &constructor);
78     napi_new_instance(env, constructor, 0, nullptr, &result);
79     return result;
80 }
81 
NapiGetBleScanner(napi_env env,napi_callback_info info)82 static NapiBleScanner *NapiGetBleScanner(napi_env env, napi_callback_info info)
83 {
84     size_t argc = 0;
85     napi_value thisVar = nullptr;
86     if (napi_get_cb_info(env, info, &argc, nullptr, &thisVar, nullptr) != napi_ok) {
87         return nullptr;
88     }
89 
90     NapiBleScanner *bleScanner = nullptr;
91     auto status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&bleScanner));
92     if (status != napi_ok) {
93         return nullptr;
94     }
95     return bleScanner;
96 }
97 
StartScan(napi_env env,napi_callback_info info)98 napi_value NapiBleScanner::StartScan(napi_env env, napi_callback_info info)
99 {
100     HILOGI("enter");
101     std::shared_ptr<NapiHaEventUtils> haUtils = std::make_shared<NapiHaEventUtils>(env, "ble.BleScanner.StartScan");
102     std::vector<BleScanFilter> scanFilters;
103     BleScanSettings settings;
104     auto status = CheckBleScanParams(env, info, scanFilters, settings);
105     NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
106 
107     NapiBleScanner *napiBleScanner = NapiGetBleScanner(env, info);
108     NAPI_BT_ASSERT_RETURN_UNDEF(env, napiBleScanner != nullptr, BT_ERR_INVALID_PARAM);
109     NAPI_BT_ASSERT_RETURN_UNDEF(env, napiBleScanner->GetBleCentralManager() != nullptr, BT_ERR_INVALID_PARAM);
110     NAPI_BT_ASSERT_RETURN_UNDEF(env, napiBleScanner->GetCallback() != nullptr, BT_ERR_INVALID_PARAM);
111 
112     auto func = [napiBleScanner, settings, scanFilters]() {
113         napiBleScanner->GetBleCentralManager()->SetNewApiFlag();
114         // When apps like aibase are in frozen state, enabling flight mode and then turning on Bluetooth can cause the
115         // scannerId to become invalid. The C++ interface's scannerId is reset every time scanning is turned off, so
116         // the JS interface should check the scannerId's validity before each scan.
117         napiBleScanner->GetBleCentralManager()->CheckValidScannerId();
118         int ret = napiBleScanner->GetBleCentralManager()->StartScan(settings, scanFilters);
119         return NapiAsyncWorkRet(ret);
120     };
121 
122     auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NEED_CALLBACK, haUtils);
123     NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
124     bool success =
125         napiBleScanner->GetCallback()->asyncWorkMap_.TryPush(NapiAsyncType::BLE_START_SCAN, asyncWork);
126     NAPI_BT_ASSERT_RETURN_UNDEF(env, success, BT_ERR_INTERNAL_ERROR);
127 
128     asyncWork->Run();
129     return asyncWork->GetRet();
130 }
131 
StopScan(napi_env env,napi_callback_info info)132 napi_value NapiBleScanner::StopScan(napi_env env, napi_callback_info info)
133 {
134     HILOGI("enter");
135     std::shared_ptr<NapiHaEventUtils> haUtils = std::make_shared<NapiHaEventUtils>(env, "ble.BleScanner.StopScan");
136     auto status = CheckEmptyParam(env, info);
137     NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
138 
139     NapiBleScanner *napiBleScanner = NapiGetBleScanner(env, info);
140     NAPI_BT_ASSERT_RETURN_UNDEF(env, napiBleScanner != nullptr, BT_ERR_INVALID_PARAM);
141     NAPI_BT_ASSERT_RETURN_UNDEF(env, napiBleScanner->GetBleCentralManager() != nullptr, BT_ERR_INVALID_PARAM);
142     NAPI_BT_ASSERT_RETURN_UNDEF(env, napiBleScanner->GetCallback() != nullptr, BT_ERR_INVALID_PARAM);
143 
144     auto func = [napiBleScanner]() {
145         // When apps like aibase are in frozen state, enabling flight mode and then turning on Bluetooth can cause the
146         // scannerId to become invalid. The C++ interface's scannerId is reset every time scanning is turned off, so
147         // the JS interface should check the scannerId's validity before each scan.
148         napiBleScanner->GetBleCentralManager()->CheckValidScannerId();
149         int ret = napiBleScanner->GetBleCentralManager()->StopScan();
150         return NapiAsyncWorkRet(ret);
151     };
152 
153     auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NEED_CALLBACK, haUtils);
154     NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
155     bool success =
156         napiBleScanner->GetCallback()->asyncWorkMap_.TryPush(NapiAsyncType::BLE_STOP_SCAN, asyncWork);
157     NAPI_BT_ASSERT_RETURN_UNDEF(env, success, BT_ERR_INTERNAL_ERROR);
158 
159     asyncWork->Run();
160     return asyncWork->GetRet();
161 }
162 
On(napi_env env,napi_callback_info info)163 napi_value NapiBleScanner::On(napi_env env, napi_callback_info info)
164 {
165     NapiBleScanner *napiBleScanner = NapiGetBleScanner(env, info);
166     if (napiBleScanner && napiBleScanner->GetCallback()) {
167         auto status = napiBleScanner->GetCallback()->eventSubscribe_.Register(env, info);
168         NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
169     }
170     return NapiGetUndefinedRet(env);
171 }
172 
Off(napi_env env,napi_callback_info info)173 napi_value NapiBleScanner::Off(napi_env env, napi_callback_info info)
174 {
175     NapiBleScanner *napiBleScanner = NapiGetBleScanner(env, info);
176     if (napiBleScanner && napiBleScanner->GetCallback()) {
177         auto status = napiBleScanner->GetCallback()->eventSubscribe_.Deregister(env, info);
178         NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
179     }
180     return NapiGetUndefinedRet(env);
181 }
182 } // namespace Bluetooth
183 } // namespace OHOS