1 /*
2 * Copyright (C) 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
16 #include "bluetooth_log.h"
17 #include "bluetooth_pan.h"
18 #include "bluetooth_utils.h"
19 #include "napi_bluetooth_error.h"
20 #include "napi_bluetooth_pan.h"
21 #include "napi_bluetooth_pan_observer.h"
22 #include "napi_bluetooth_profile.h"
23 #include "napi_bluetooth_utils.h"
24 #include "hitrace_meter.h"
25
26 namespace OHOS {
27 namespace Bluetooth {
28 using namespace std;
29 std::shared_ptr<NapiBluetoothPanObserver> NapiBluetoothPan::observer_ = std::make_shared<NapiBluetoothPanObserver>();
30 thread_local napi_ref NapiBluetoothPan::consRef_ = nullptr;
31
CreatePanProfile(napi_env env, napi_callback_info info)32 napi_value NapiBluetoothPan::CreatePanProfile(napi_env env, napi_callback_info info)
33 {
34 HILOGI("enter");
35 napi_value napiProfile;
36 napi_value constructor = nullptr;
37 napi_get_reference_value(env, consRef_, &constructor);
38 napi_new_instance(env, constructor, 0, nullptr, &napiProfile);
39 NapiProfile::SetProfile(env, ProfileId::PROFILE_PAN_NETWORK, napiProfile);
40 Pan *profile = Pan::GetProfile();
41 profile->RegisterObserver(NapiBluetoothPan::observer_);
42 HILOGI("finished");
43
44 return napiProfile;
45 }
46
DefinePanJSClass(napi_env env, napi_value exports)47 void NapiBluetoothPan::DefinePanJSClass(napi_env env, napi_value exports)
48 {
49 napi_value constructor;
50 napi_property_descriptor properties [] = {
51 DECLARE_NAPI_FUNCTION("on", NapiBluetoothPan::On),
52 DECLARE_NAPI_FUNCTION("off", NapiBluetoothPan::Off),
53 DECLARE_NAPI_FUNCTION("disconnect", NapiBluetoothPan::Disconnect),
54 DECLARE_NAPI_FUNCTION("setTethering", NapiBluetoothPan::SetTethering),
55 DECLARE_NAPI_FUNCTION("isTetheringOn", NapiBluetoothPan::IsTetheringOn),
56 #ifdef BLUETOOTH_API_SINCE_10
57 DECLARE_NAPI_FUNCTION("getConnectedDevices", NapiBluetoothPan::GetConnectedDevices),
58 DECLARE_NAPI_FUNCTION("getConnectionState", NapiBluetoothPan::GetConnectionState),
59 DECLARE_NAPI_FUNCTION("setConnectionStrategy", NapiBluetoothPan::SetConnectionStrategy),
60 DECLARE_NAPI_FUNCTION("getConnectionStrategy", NapiBluetoothPan::GetConnectionStrategy),
61 #else
62 DECLARE_NAPI_FUNCTION("getConnectionDevices", NapiBluetoothPan::GetConnectionDevices),
63 DECLARE_NAPI_FUNCTION("getDeviceState", NapiBluetoothPan::GetDeviceState),
64 #endif
65 };
66
67 napi_define_class(env, "NapiBluetoothPan", NAPI_AUTO_LENGTH, NapiBluetoothPan::PanConstructor, nullptr,
68 sizeof(properties) / sizeof(properties[0]), properties, &constructor);
69
70 #ifdef BLUETOOTH_API_SINCE_10
71 DefineCreateProfile(env, exports);
72 napi_create_reference(env, constructor, 1, &consRef_);
73 #else
74 napi_define_class(env, "NapiBluetoothPan", NAPI_AUTO_LENGTH, PanConstructor, nullptr,
75 sizeof(properties) / sizeof(properties[0]), properties, &constructor);
76 napi_value napiProfile;
77 napi_new_instance(env, constructor, 0, nullptr, &napiProfile);
78 NapiProfile::SetProfile(env, ProfileId::PROFILE_PAN_NETWORK, napiProfile);
79 Pan *profile = Pan::GetProfile();
80 profile->RegisterObserver(NapiBluetoothPan::observer_);
81 #endif
82 }
83
DefineCreateProfile(napi_env env, napi_value exports)84 napi_value NapiBluetoothPan::DefineCreateProfile(napi_env env, napi_value exports)
85 {
86 napi_property_descriptor properties [] = {
87 DECLARE_NAPI_FUNCTION("createPanProfile", NapiBluetoothPan::CreatePanProfile),
88 };
89 HITRACE_METER_NAME(HITRACE_TAG_OHOS, "pan:napi_define_properties");
90 napi_define_properties(env, exports, sizeof(properties) / sizeof(properties[0]), properties);
91 return exports;
92 }
93
SetConnectionStrategy(napi_env env, napi_callback_info info)94 napi_value NapiBluetoothPan::SetConnectionStrategy(napi_env env, napi_callback_info info)
95 {
96 HILOGI("enter");
97 NAPI_BT_ASSERT_RETURN_UNDEF(env, false, BT_ERR_API_NOT_SUPPORT);
98 return NapiGetUndefinedRet(env);
99 }
100
GetConnectionStrategy(napi_env env, napi_callback_info info)101 napi_value NapiBluetoothPan::GetConnectionStrategy(napi_env env, napi_callback_info info)
102 {
103 HILOGI("enter");
104 NAPI_BT_ASSERT_RETURN_UNDEF(env, false, BT_ERR_API_NOT_SUPPORT);
105 return NapiGetUndefinedRet(env);
106 }
107
PanConstructor(napi_env env, napi_callback_info info)108 napi_value NapiBluetoothPan::PanConstructor(napi_env env, napi_callback_info info)
109 {
110 napi_value thisVar = nullptr;
111 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
112 return thisVar;
113 }
114
On(napi_env env, napi_callback_info info)115 napi_value NapiBluetoothPan::On(napi_env env, napi_callback_info info)
116 {
117 if (observer_) {
118 auto status = observer_->eventSubscribe_.Register(env, info);
119 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
120 }
121 return NapiGetUndefinedRet(env);
122 }
123
Off(napi_env env, napi_callback_info info)124 napi_value NapiBluetoothPan::Off(napi_env env, napi_callback_info info)
125 {
126 if (observer_) {
127 auto status = observer_->eventSubscribe_.Deregister(env, info);
128 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
129 }
130 return NapiGetUndefinedRet(env);
131 }
132
GetConnectionDevices(napi_env env, napi_callback_info info)133 napi_value NapiBluetoothPan::GetConnectionDevices(napi_env env, napi_callback_info info)
134 {
135 HILOGI("enter");
136 napi_value ret = nullptr;
137 if (napi_create_array(env, &ret) != napi_ok) {
138 HILOGE("napi_create_array failed.");
139 }
140
141 napi_status checkRet = CheckEmptyParam(env, info);
142 NAPI_BT_ASSERT_RETURN(env, checkRet == napi_ok, BT_ERR_INVALID_PARAM, ret);
143
144 Pan *profile = Pan::GetProfile();
145 vector<int> states = { static_cast<int>(BTConnectState::CONNECTED) };
146 vector<BluetoothRemoteDevice> devices;
147 int errorCode = profile->GetDevicesByStates(states, devices);
148 HILOGI("errorCode:%{public}s, devices size:%{public}zu", GetErrorCode(errorCode).c_str(), devices.size());
149 NAPI_BT_ASSERT_RETURN(env, errorCode == BT_NO_ERROR, errorCode, ret);
150
151 vector<string> deviceVector;
152 for (auto &device : devices) {
153 deviceVector.push_back(device.GetDeviceAddr());
154 }
155 ConvertStringVectorToJS(env, ret, deviceVector);
156 return ret;
157 }
158
GetDeviceState(napi_env env, napi_callback_info info)159 napi_value NapiBluetoothPan::GetDeviceState(napi_env env, napi_callback_info info)
160 {
161 HILOGI("enter");
162 napi_value result = nullptr;
163 int32_t profileState = ProfileConnectionState::STATE_DISCONNECTED;
164 if (napi_create_int32(env, profileState, &result) != napi_ok) {
165 HILOGE("napi_create_int32 failed.");
166 }
167
168 std::string remoteAddr {};
169 bool checkRet = CheckDeivceIdParam(env, info, remoteAddr);
170 NAPI_BT_ASSERT_RETURN(env, checkRet, BT_ERR_INVALID_PARAM, result);
171
172 Pan *profile = Pan::GetProfile();
173 BluetoothRemoteDevice device(remoteAddr, BT_TRANSPORT_BREDR);
174 int32_t state = static_cast<int32_t>(BTConnectState::DISCONNECTED);
175 int32_t errorCode = profile->GetDeviceState(device, state);
176 HILOGI("errorCode:%{public}s", GetErrorCode(errorCode).c_str());
177 NAPI_BT_ASSERT_RETURN(env, errorCode == BT_NO_ERROR, errorCode, result);
178
179 profileState = GetProfileConnectionState(state);
180 if (napi_create_int32(env, profileState, &result) != napi_ok) {
181 HILOGE("napi_create_int32 failed.");
182 }
183 HILOGI("profileState: %{public}d", profileState);
184 return result;
185 }
186
GetConnectedDevices(napi_env env, napi_callback_info info)187 napi_value NapiBluetoothPan::GetConnectedDevices(napi_env env, napi_callback_info info)
188 {
189 HILOGI("enter");
190 napi_value ret = nullptr;
191 if (napi_create_array(env, &ret) != napi_ok) {
192 HILOGE("napi_create_array failed.");
193 }
194
195 napi_status checkRet = CheckEmptyParam(env, info);
196 NAPI_BT_ASSERT_RETURN(env, checkRet == napi_ok, BT_ERR_INVALID_PARAM, ret);
197
198 Pan *profile = Pan::GetProfile();
199 vector<int> states = { static_cast<int>(BTConnectState::CONNECTED) };
200 vector<BluetoothRemoteDevice> devices;
201 int errorCode = profile->GetDevicesByStates(states, devices);
202 HILOGI("errorCode:%{public}s, devices size:%{public}zu", GetErrorCode(errorCode).c_str(), devices.size());
203 NAPI_BT_ASSERT_RETURN(env, errorCode == BT_NO_ERROR, errorCode, ret);
204
205 vector<string> deviceVector;
206 for (auto &device : devices) {
207 deviceVector.push_back(device.GetDeviceAddr());
208 }
209 ConvertStringVectorToJS(env, ret, deviceVector);
210 return ret;
211 }
212
GetConnectionState(napi_env env, napi_callback_info info)213 napi_value NapiBluetoothPan::GetConnectionState(napi_env env, napi_callback_info info)
214 {
215 HILOGI("enter");
216 napi_value result = nullptr;
217 int32_t profileState = ProfileConnectionState::STATE_DISCONNECTED;
218 if (napi_create_int32(env, profileState, &result) != napi_ok) {
219 HILOGE("napi_create_int32 failed.");
220 }
221
222 std::string remoteAddr {};
223 bool checkRet = CheckDeivceIdParam(env, info, remoteAddr);
224 NAPI_BT_ASSERT_RETURN(env, checkRet, BT_ERR_INVALID_PARAM, result);
225
226 Pan *profile = Pan::GetProfile();
227 BluetoothRemoteDevice device(remoteAddr, BT_TRANSPORT_BREDR);
228 int32_t state = static_cast<int32_t>(BTConnectState::DISCONNECTED);
229 int32_t errorCode = profile->GetDeviceState(device, state);
230 HILOGI("errorCode:%{public}s", GetErrorCode(errorCode).c_str());
231 NAPI_BT_ASSERT_RETURN(env, errorCode == BT_NO_ERROR, errorCode, result);
232
233 profileState = GetProfileConnectionState(state);
234 if (napi_create_int32(env, profileState, &result) != napi_ok) {
235 HILOGE("napi_create_int32 failed.");
236 }
237 HILOGI("profileState: %{public}d", profileState);
238 return result;
239 }
240
Disconnect(napi_env env, napi_callback_info info)241 napi_value NapiBluetoothPan::Disconnect(napi_env env, napi_callback_info info)
242 {
243 HILOGI("enter");
244 std::string remoteAddr {};
245 bool checkRet = CheckDeivceIdParam(env, info, remoteAddr);
246 NAPI_BT_ASSERT_RETURN_FALSE(env, checkRet, BT_ERR_INVALID_PARAM);
247
248 Pan *profile = Pan::GetProfile();
249 BluetoothRemoteDevice device(remoteAddr, BT_TRANSPORT_BREDR);
250 int32_t errorCode = profile->Disconnect(device);
251 HILOGI("errorCode:%{public}s", GetErrorCode(errorCode).c_str());
252 NAPI_BT_ASSERT_RETURN_FALSE(env, errorCode == BT_NO_ERROR, errorCode);
253
254 return NapiGetBooleanTrue(env);
255 }
256
CheckSetTetheringParam(napi_env env, napi_callback_info info, bool &out)257 static bool CheckSetTetheringParam(napi_env env, napi_callback_info info, bool &out)
258 {
259 size_t argc = ARGS_SIZE_ONE;
260 napi_value argv[ARGS_SIZE_ONE] = {nullptr};
261 NAPI_BT_RETURN_IF(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr) != napi_ok, "call failed.", false);
262 NAPI_BT_RETURN_IF(argc != ARGS_SIZE_ONE, "Requires 1 argument.", false);
263 NAPI_BT_RETURN_IF(!ParseBool(env, out, argv[PARAM0]), "Bool expected.", false);
264 return true;
265 }
266
SetTethering(napi_env env, napi_callback_info info)267 napi_value NapiBluetoothPan::SetTethering(napi_env env, napi_callback_info info)
268 {
269 HILOGI("enter");
270 bool value = false;
271 bool checkRet = CheckSetTetheringParam(env, info, value);
272 NAPI_BT_ASSERT_RETURN_UNDEF(env, checkRet, BT_ERR_INVALID_PARAM);
273
274 Pan *profile = Pan::GetProfile();
275 int32_t errorCode = profile->SetTethering(value);
276 HILOGI("errorCode:%{public}s", GetErrorCode(errorCode).c_str());
277 NAPI_BT_ASSERT_RETURN_UNDEF(env, errorCode == BT_NO_ERROR, errorCode);
278
279 return NapiGetUndefinedRet(env);
280 }
281
IsTetheringOn(napi_env env, napi_callback_info info)282 napi_value NapiBluetoothPan::IsTetheringOn(napi_env env, napi_callback_info info)
283 {
284 HILOGI("enter");
285 napi_status checkRet = CheckEmptyParam(env, info);
286 NAPI_BT_ASSERT_RETURN_FALSE(env, checkRet == napi_ok, BT_ERR_INVALID_PARAM);
287
288 Pan *profile = Pan::GetProfile();
289 bool result = false;
290 int32_t errorCode = profile->IsTetheringOn(result);
291 HILOGI("errorCode:%{public}s", GetErrorCode(errorCode).c_str());
292 NAPI_BT_ASSERT_RETURN_FALSE(env, errorCode == BT_NO_ERROR, errorCode);
293
294 HILOGI("IsTetheringOn: %{public}d", result);
295 return NapiGetBooleanRet(env, result);
296 }
297 } // namespace Bluetooth
298 } // namespace OHOS