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
16 #include "bluetooth_errorcode.h"
17 #include "bluetooth_pbap_pse.h"
18 #include "bluetooth_utils.h"
19 #include "napi_async_work.h"
20 #include "napi_bluetooth_event.h"
21 #include "napi_bluetooth_error.h"
22 #include "napi_bluetooth_pbap_pse.h"
23 #include "napi_bluetooth_profile.h"
24 #include "napi_bluetooth_utils.h"
25 #include "../parser/napi_parser_utils.h"
26 #include "hitrace_meter.h"
27
28 namespace OHOS {
29 namespace Bluetooth {
30 using namespace std;
31
32 enum ShareType {
33 SHARE_NAME_AND_PHONE_NUMBER = 0,
34 SHARE_ALL = 1,
35 SHARE_NOTHING = 2,
36 };
37
38 std::shared_ptr<NapiPbapPseObserver> NapiPbapServer::observer_ = std::make_shared<NapiPbapPseObserver>();
39 thread_local napi_ref g_consRef_ = nullptr;
40
DefinePbapServerJSClass(napi_env env,napi_value exports)41 void NapiPbapServer::DefinePbapServerJSClass(napi_env env, napi_value exports)
42 {
43 napi_value constructor;
44 PbapPropertyValueInit(env, exports);
45 napi_property_descriptor properties[] = {
46 DECLARE_NAPI_FUNCTION("on", On),
47 DECLARE_NAPI_FUNCTION("off", Off),
48 DECLARE_NAPI_FUNCTION("getConnectedDevices", GetConnectedDevices),
49 DECLARE_NAPI_FUNCTION("getConnectionState", GetConnectionState),
50 DECLARE_NAPI_FUNCTION("setConnectionStrategy", SetConnectionStrategy),
51 DECLARE_NAPI_FUNCTION("getConnectionStrategy", GetConnectionStrategy),
52 DECLARE_NAPI_FUNCTION("disconnect", Disconnect),
53 DECLARE_NAPI_FUNCTION("setShareType", SetShareType),
54 DECLARE_NAPI_FUNCTION("getShareType", GetShareType),
55 DECLARE_NAPI_FUNCTION("setPhoneBookAccessAuthorization", SetPhoneBookAccessAuthorization),
56 DECLARE_NAPI_FUNCTION("getPhoneBookAccessAuthorization", GetPhoneBookAccessAuthorization),
57 };
58
59 napi_define_class(env, "PbapPse", NAPI_AUTO_LENGTH, PbapServerConstructor, nullptr,
60 sizeof(properties) / sizeof(properties[0]), properties, &constructor);
61
62 DefineCreateProfile(env, exports);
63 napi_create_reference(env, constructor, 1, &g_consRef_);
64 }
65
DefineCreateProfile(napi_env env,napi_value exports)66 napi_value NapiPbapServer::DefineCreateProfile(napi_env env, napi_value exports)
67 {
68 napi_property_descriptor properties[] = {
69 DECLARE_NAPI_FUNCTION("createPbapServerProfile", CreatePbapServerProfile),
70 };
71 HITRACE_METER_NAME(HITRACE_TAG_OHOS, "pbappse:napi_define_properties");
72 napi_define_properties(env, exports, sizeof(properties) / sizeof(properties[0]), properties);
73 return exports;
74 }
75
CreatePbapServerProfile(napi_env env,napi_callback_info info)76 napi_value NapiPbapServer::CreatePbapServerProfile(napi_env env, napi_callback_info info)
77 {
78 napi_value napiProfile;
79 napi_value constructor = nullptr;
80 napi_get_reference_value(env, g_consRef_, &constructor);
81 napi_new_instance(env, constructor, 0, nullptr, &napiProfile);
82
83 PbapPse *profile = PbapPse::GetProfile();
84 profile->RegisterObserver(observer_);
85 return napiProfile;
86 }
87
PbapServerConstructor(napi_env env,napi_callback_info info)88 napi_value NapiPbapServer::PbapServerConstructor(napi_env env, napi_callback_info info)
89 {
90 napi_value thisVar = nullptr;
91 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
92 return thisVar;
93 }
94
PbapPropertyValueInit(napi_env env,napi_value exports)95 napi_value NapiPbapServer::PbapPropertyValueInit(napi_env env, napi_value exports)
96 {
97 HILOGI("enter");
98 napi_value shareTypeObj = ShareTypeInit(env);
99 napi_property_descriptor exportFuncs[] = {
100 DECLARE_NAPI_PROPERTY("ShareType", shareTypeObj),
101 };
102 HITRACE_METER_NAME(HITRACE_TAG_OHOS, "pbappse:napi_define_properties");
103 napi_define_properties(env, exports, sizeof(exportFuncs) / sizeof(*exportFuncs), exportFuncs);
104 return exports;
105 }
106
ShareTypeInit(napi_env env)107 napi_value NapiPbapServer::ShareTypeInit(napi_env env)
108 {
109 HILOGD("enter");
110 napi_value shareType = nullptr;
111 napi_create_object(env, &shareType);
112 SetNamedPropertyByInteger(env, shareType, ShareType::SHARE_NAME_AND_PHONE_NUMBER, "SHARE_NAME_AND_PHONE_NUMBER");
113 SetNamedPropertyByInteger(env, shareType, ShareType::SHARE_ALL, "SHARE_ALL");
114 SetNamedPropertyByInteger(env, shareType, ShareType::SHARE_NOTHING, "SHARE_NOTHING");
115 return shareType;
116 }
117
On(napi_env env,napi_callback_info info)118 napi_value NapiPbapServer::On(napi_env env, napi_callback_info info)
119 {
120 if (observer_) {
121 auto status = observer_->eventSubscribe_.Register(env, info);
122 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
123 }
124 return NapiGetUndefinedRet(env);
125 }
126
Off(napi_env env,napi_callback_info info)127 napi_value NapiPbapServer::Off(napi_env env, napi_callback_info info)
128 {
129 if (observer_) {
130 auto status = observer_->eventSubscribe_.Deregister(env, info);
131 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
132 }
133 return NapiGetUndefinedRet(env);
134 }
135
GetConnectedDevices(napi_env env,napi_callback_info info)136 napi_value NapiPbapServer::GetConnectedDevices(napi_env env, napi_callback_info info)
137 {
138 HILOGI("enter");
139 napi_value ret = nullptr;
140 napi_create_array(env, &ret);
141 napi_status checkRet = CheckEmptyParam(env, info);
142 NAPI_BT_ASSERT_RETURN(env, checkRet == napi_ok, BT_ERR_INVALID_PARAM, ret);
143
144 PbapPse *profile = PbapPse::GetProfile();
145 vector<int32_t> states = { static_cast<int32_t>(BTConnectState::CONNECTED) };
146 vector<BluetoothRemoteDevice> devices {};
147 int32_t errorCode = profile->GetDevicesByStates(states, devices);
148 NAPI_BT_ASSERT_RETURN(env, errorCode == BT_NO_ERROR, errorCode, ret);
149
150 vector<string> deviceVector;
151 for (auto &device : devices) {
152 deviceVector.push_back(device.GetDeviceAddr());
153 }
154
155 auto status = ConvertStringVectorToJS(env, ret, deviceVector);
156 NAPI_BT_ASSERT_RETURN(env, status == napi_ok, BT_ERR_INTERNAL_ERROR, ret);
157 return ret;
158 }
159
GetConnectionState(napi_env env,napi_callback_info info)160 napi_value NapiPbapServer::GetConnectionState(napi_env env, napi_callback_info info)
161 {
162 HILOGI("enter");
163 std::string remoteAddr{};
164 bool checkRet = CheckDeivceIdParam(env, info, remoteAddr);
165 NAPI_BT_ASSERT_RETURN_UNDEF(env, checkRet, BT_ERR_INVALID_PARAM);
166
167 PbapPse *profile = PbapPse::GetProfile();
168 BluetoothRemoteDevice device(remoteAddr, BT_TRANSPORT_BREDR);
169 int32_t state = static_cast<int32_t>(BTConnectState::DISCONNECTED);
170 int32_t errorCode = profile->GetDeviceState(device, state);
171 HILOGD("errorCode:%{public}s", GetErrorCode(errorCode).c_str());
172 NAPI_BT_ASSERT_RETURN_UNDEF(env, errorCode == BT_NO_ERROR, errorCode);
173
174 napi_value result = nullptr;
175 int32_t profileState = GetProfileConnectionState(state);
176 napi_create_int32(env, profileState, &result);
177 return result;
178 }
179
Disconnect(napi_env env,napi_callback_info info)180 napi_value NapiPbapServer::Disconnect(napi_env env, napi_callback_info info)
181 {
182 HILOGI("enter");
183 std::string remoteAddr{};
184 bool checkRet = CheckDeivceIdParam(env, info, remoteAddr);
185 NAPI_BT_ASSERT_RETURN_FALSE(env, checkRet, BT_ERR_INVALID_PARAM);
186
187 PbapPse *profile = PbapPse::GetProfile();
188 BluetoothRemoteDevice device(remoteAddr, BT_TRANSPORT_BREDR);
189 int32_t errorCode = profile->Disconnect(device);
190 HILOGD("errorCode:%{public}s", GetErrorCode(errorCode).c_str());
191 NAPI_BT_ASSERT_RETURN_FALSE(env, errorCode == BT_NO_ERROR, errorCode);
192 return NapiGetBooleanTrue(env);
193 }
194
SetConnectionStrategy(napi_env env,napi_callback_info info)195 napi_value NapiPbapServer::SetConnectionStrategy(napi_env env, napi_callback_info info)
196 {
197 HILOGI("enter");
198 std::string remoteAddr{};
199 int32_t strategy = 0;
200 auto status = CheckSetConnectStrategyParam(env, info, remoteAddr, strategy);
201 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
202
203 auto func = [remoteAddr, strategy]() {
204 BluetoothRemoteDevice remoteDevice(remoteAddr, BT_TRANSPORT_BREDR);
205 PbapPse *profile = PbapPse::GetProfile();
206 int32_t errorCode = profile->SetConnectionStrategy(remoteDevice, strategy);
207 HILOGI("err: %{public}d", errorCode);
208 return NapiAsyncWorkRet(errorCode);
209 };
210 auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NO_NEED_CALLBACK);
211 NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
212 asyncWork->Run();
213 return asyncWork->GetRet();
214 }
215
GetConnectionStrategy(napi_env env,napi_callback_info info)216 napi_value NapiPbapServer::GetConnectionStrategy(napi_env env, napi_callback_info info)
217 {
218 HILOGI("enter");
219 std::string remoteAddr{};
220 auto status = CheckDeviceAddressParam(env, info, remoteAddr);
221 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
222
223 auto func = [remoteAddr]() {
224 int32_t strategy = 0;
225 BluetoothRemoteDevice remoteDevice(remoteAddr, BT_TRANSPORT_BREDR);
226 PbapPse *profile = PbapPse::GetProfile();
227 int32_t errorCode = profile->GetConnectionStrategy(remoteDevice, strategy);
228 HILOGI("errorCode: %{public}d, deviceName: %{public}d", errorCode, strategy);
229 auto object = std::make_shared<NapiNativeInt>(strategy);
230 return NapiAsyncWorkRet(errorCode, object);
231 };
232 auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NO_NEED_CALLBACK);
233 NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
234 asyncWork->Run();
235 return asyncWork->GetRet();
236 }
237
IsShareTypeValid(int32_t shareType)238 bool IsShareTypeValid(int32_t shareType)
239 {
240 return shareType == static_cast<int32_t>(ShareType::SHARE_NAME_AND_PHONE_NUMBER) ||
241 shareType == static_cast<int32_t>(ShareType::SHARE_ALL) ||
242 shareType == static_cast<int32_t>(ShareType::SHARE_NOTHING);
243 }
244
CheckShareTypeParam(napi_env env,napi_callback_info info,std::string & addr,int32_t & shareType)245 napi_status CheckShareTypeParam(napi_env env, napi_callback_info info, std::string &addr, int32_t &shareType)
246 {
247 size_t argc = ARGS_SIZE_THREE;
248 napi_value argv[ARGS_SIZE_THREE] = {nullptr};
249 NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
250 NAPI_BT_RETURN_IF(argc != ARGS_SIZE_TWO && argc != ARGS_SIZE_THREE, "Requires 2 or 3 arguments.", napi_invalid_arg);
251 NAPI_BT_CALL_RETURN(NapiParseBdAddr(env, argv[PARAM0], addr));
252 NAPI_BT_RETURN_IF(!ParseInt32(env, shareType, argv[PARAM1]), "ParseInt failed", napi_invalid_arg);
253 NAPI_BT_RETURN_IF(!IsShareTypeValid(shareType), "Invalid shareType", napi_invalid_arg);
254 return napi_ok;
255 }
256
SetShareType(napi_env env,napi_callback_info info)257 napi_value NapiPbapServer::SetShareType(napi_env env, napi_callback_info info)
258 {
259 HILOGI("enter");
260 std::string remoteAddr{};
261 int32_t shareType = 0;
262 auto status = CheckShareTypeParam(env, info, remoteAddr, shareType);
263 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
264
265 auto func = [remoteAddr, shareType]() {
266 BluetoothRemoteDevice remoteDevice(remoteAddr, BT_TRANSPORT_BREDR);
267 PbapPse *profile = PbapPse::GetProfile();
268 int32_t errorCode = profile->SetShareType(remoteDevice, shareType);
269 HILOGI("errorCode: %{public}d", errorCode);
270 return NapiAsyncWorkRet(errorCode);
271 };
272 auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NO_NEED_CALLBACK);
273 NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
274 asyncWork->Run();
275 return asyncWork->GetRet();
276 }
277
GetShareType(napi_env env,napi_callback_info info)278 napi_value NapiPbapServer::GetShareType(napi_env env, napi_callback_info info)
279 {
280 HILOGI("enter");
281 std::string remoteAddr{};
282 auto status = CheckDeviceAddressParam(env, info, remoteAddr);
283 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
284
285 auto func = [remoteAddr]() {
286 int32_t shareType = 0;
287 BluetoothRemoteDevice remoteDevice(remoteAddr, BT_TRANSPORT_BREDR);
288 PbapPse *profile = PbapPse::GetProfile();
289 int32_t errorCode = profile->GetShareType(remoteDevice, shareType);
290 HILOGI("errorCode: %{public}d, shareType: %{public}d", errorCode, shareType);
291 auto object = std::make_shared<NapiNativeInt>(shareType);
292 return NapiAsyncWorkRet(errorCode, object);
293 };
294 auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NO_NEED_CALLBACK);
295 NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
296 asyncWork->Run();
297 return asyncWork->GetRet();
298 }
299
SetPhoneBookAccessAuthorization(napi_env env,napi_callback_info info)300 napi_value NapiPbapServer::SetPhoneBookAccessAuthorization(napi_env env, napi_callback_info info)
301 {
302 HILOGI("enter");
303 std::string remoteAddr{};
304 int32_t accessAuthorization = 0;
305 auto status = CheckAccessAuthorizationParam(env, info, remoteAddr, accessAuthorization);
306 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
307
308 auto func = [remoteAddr, accessAuthorization]() {
309 BluetoothRemoteDevice remoteDevice(remoteAddr, BT_TRANSPORT_BREDR);
310 PbapPse *profile = PbapPse::GetProfile();
311 int32_t errorCode = profile->SetPhoneBookAccessAuthorization(remoteDevice, accessAuthorization);
312 HILOGI("errorCode: %{public}d", errorCode);
313 return NapiAsyncWorkRet(errorCode);
314 };
315 auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NO_NEED_CALLBACK);
316 NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
317 asyncWork->Run();
318 return asyncWork->GetRet();
319 }
320
GetPhoneBookAccessAuthorization(napi_env env,napi_callback_info info)321 napi_value NapiPbapServer::GetPhoneBookAccessAuthorization(napi_env env, napi_callback_info info)
322 {
323 HILOGI("enter");
324 std::string remoteAddr{};
325 auto status = CheckDeviceAddressParam(env, info, remoteAddr);
326 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
327
328 auto func = [remoteAddr]() {
329 int32_t accessAuthorization = 0;
330 BluetoothRemoteDevice remoteDevice(remoteAddr, BT_TRANSPORT_BREDR);
331 PbapPse *profile = PbapPse::GetProfile();
332 int32_t errorCode = profile->GetPhoneBookAccessAuthorization(remoteDevice, accessAuthorization);
333 HILOGI("errorCode: %{public}d, accessAuthorization: %{public}d", errorCode, accessAuthorization);
334 auto object = std::make_shared<NapiNativeInt>(accessAuthorization);
335 return NapiAsyncWorkRet(errorCode, object);
336 };
337 auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NO_NEED_CALLBACK);
338 NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
339 asyncWork->Run();
340 return asyncWork->GetRet();
341 }
342
343 } // namespace Bluetooth
344 } // namespace OHOS