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