• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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