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_opp"
17 #endif
18
19 #include "bluetooth_errorcode.h"
20 #include "bluetooth_opp.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_opp.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 std::shared_ptr<NapiBluetoothOppObserver> NapiBluetoothOpp::observer_ = std::make_shared<NapiBluetoothOppObserver>();
36 thread_local napi_ref g_consRef_ = nullptr;
37
DefineOppJSClass(napi_env env,napi_value exports)38 void NapiBluetoothOpp::DefineOppJSClass(napi_env env, napi_value exports)
39 {
40 napi_value constructor;
41 napi_property_descriptor properties[] = {
42 DECLARE_NAPI_FUNCTION("on", On),
43 DECLARE_NAPI_FUNCTION("off", Off),
44 DECLARE_NAPI_FUNCTION("sendFile", SendFile),
45 DECLARE_NAPI_FUNCTION("setIncomingFileConfirmation", SetIncomingFileConfirmation),
46 DECLARE_NAPI_FUNCTION("getCurrentTransferInformation", GetCurrentTransferInformation),
47 DECLARE_NAPI_FUNCTION("cancelTransfer", CancelTransfer),
48 DECLARE_NAPI_FUNCTION("getConnectionDevices", GetConnectionDevices),
49 DECLARE_NAPI_FUNCTION("getDeviceState", GetDeviceState),
50 DECLARE_NAPI_FUNCTION("setLastReceivedFileUri", SetLastReceivedFileUri),
51 };
52
53 napi_define_class(env, "NapiBluetoothOpp", NAPI_AUTO_LENGTH, OppConstructor, nullptr,
54 sizeof(properties) / sizeof(properties[0]), properties, &constructor);
55
56 DefineCreateProfile(env, exports);
57 napi_create_reference(env, constructor, 1, &g_consRef_);
58 }
59
DefineCreateProfile(napi_env env,napi_value exports)60 napi_value NapiBluetoothOpp::DefineCreateProfile(napi_env env, napi_value exports)
61 {
62 napi_property_descriptor properties[] = {
63 DECLARE_NAPI_FUNCTION("createOppServerProfile", CreateOppServerProfile),
64 };
65 HITRACE_METER_NAME(HITRACE_TAG_OHOS, "opp:napi_define_properties");
66 napi_define_properties(env, exports, sizeof(properties) / sizeof(properties[0]), properties);
67 return exports;
68 }
69
CreateOppServerProfile(napi_env env,napi_callback_info info)70 napi_value NapiBluetoothOpp::CreateOppServerProfile(napi_env env, napi_callback_info info)
71 {
72 napi_value napiProfile;
73 napi_value constructor = nullptr;
74 napi_get_reference_value(env, g_consRef_, &constructor);
75 napi_new_instance(env, constructor, 0, nullptr, &napiProfile);
76
77 Opp *profile = Opp::GetProfile();
78 profile->RegisterObserver(observer_);
79 return napiProfile;
80 }
81
OppConstructor(napi_env env,napi_callback_info info)82 napi_value NapiBluetoothOpp::OppConstructor(napi_env env, napi_callback_info info)
83 {
84 napi_value thisVar = nullptr;
85 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
86 return thisVar;
87 }
88
On(napi_env env,napi_callback_info info)89 napi_value NapiBluetoothOpp::On(napi_env env, napi_callback_info info)
90 {
91 if (observer_) {
92 auto status = observer_->eventSubscribe_.Register(env, info);
93 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
94 }
95 return NapiGetUndefinedRet(env);
96 }
97
Off(napi_env env,napi_callback_info info)98 napi_value NapiBluetoothOpp::Off(napi_env env, napi_callback_info info)
99 {
100 if (observer_) {
101 auto status = observer_->eventSubscribe_.Deregister(env, info);
102 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
103 }
104 return NapiGetUndefinedRet(env);
105 }
106
CheckSetIncomingFileConfirmation(napi_env env,napi_callback_info info,bool & accept,int & fileFd)107 napi_status CheckSetIncomingFileConfirmation(napi_env env, napi_callback_info info, bool &accept, int &fileFd)
108 {
109 size_t argc = ARGS_SIZE_TWO;
110 napi_value argv[ARGS_SIZE_TWO] = {nullptr};
111 NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
112 NAPI_BT_RETURN_IF(argc != ARGS_SIZE_TWO, "Require 2 arguments.", napi_invalid_arg);
113 NAPI_BT_CALL_RETURN(NapiParseBoolean(env, argv[PARAM0], accept));
114 NAPI_BT_CALL_RETURN(NapiParseInt32(env, argv[PARAM1], fileFd));
115 return napi_ok;
116 }
117
CheckSendFileParam(napi_env env,napi_callback_info info,std::string & addr,std::vector<FileHolder> & fileHolders)118 napi_status CheckSendFileParam(napi_env env, napi_callback_info info, std::string &addr,
119 std::vector<FileHolder> &fileHolders)
120 {
121 size_t argc = ARGS_SIZE_TWO;
122 napi_value argv[ARGS_SIZE_TWO] = {nullptr};
123 NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
124 NAPI_BT_RETURN_IF(argc != ARGS_SIZE_TWO, "Require 2 arguments.", napi_invalid_arg);
125 NAPI_BT_CALL_RETURN(NapiParseBdAddr(env, argv[PARAM0], addr));
126 NAPI_BT_CALL_RETURN(NapiParseFileHolderArray(env, argv[PARAM1], fileHolders));
127 return napi_ok;
128 }
129
SendFile(napi_env env,napi_callback_info info)130 napi_value NapiBluetoothOpp::SendFile(napi_env env, napi_callback_info info)
131 {
132 HILOGI("enter");
133
134 std::string device {};
135 std::vector<FileHolder> fileHolders;
136
137 auto status = CheckSendFileParam(env, info, device, fileHolders);
138 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
139 HILOGI("fileHolders size is %{public}zu", fileHolders.size());
140
141 auto func = [device, fileHolders]() {
142 Opp *profile = Opp::GetProfile();
143 bool result = false;
144 std::vector<BluetoothOppFileHolder> oppFileHolders;
145 for (FileHolder fileHolder : fileHolders) {
146 oppFileHolders.push_back(BluetoothOppFileHolder(fileHolder.filePath,
147 fileHolder.fileSize, fileHolder.fileFd));
148 }
149 HILOGI("oppFileHolders size is %{public}zu", oppFileHolders.size());
150 int32_t errorCode = profile->SendFile(device, oppFileHolders, result);
151 HILOGI("err: %{public}d result: %{public}d", errorCode, result);
152 return NapiAsyncWorkRet(errorCode);
153 };
154 auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NO_NEED_CALLBACK);
155 NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
156 asyncWork->Run();
157 return asyncWork->GetRet();
158 }
159
SetIncomingFileConfirmation(napi_env env,napi_callback_info info)160 napi_value NapiBluetoothOpp::SetIncomingFileConfirmation(napi_env env, napi_callback_info info)
161 {
162 HILOGI("enter");
163
164 bool accept = false;
165 int32_t fileFd = -1;
166 auto status = CheckSetIncomingFileConfirmation(env, info, accept, fileFd);
167 HILOGI("fileFd is %{public}d", fileFd);
168 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
169
170 auto func = [accept, fileFd]() {
171 Opp *profile = Opp::GetProfile();
172 int32_t errorCode = profile->SetIncomingFileConfirmation(accept, fileFd);
173 HILOGI("err: %{public}d", errorCode);
174 return NapiAsyncWorkRet(errorCode);
175 };
176 auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NO_NEED_CALLBACK);
177 NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
178 asyncWork->Run();
179 return asyncWork->GetRet();
180 }
181
GetCurrentTransferInformation(napi_env env,napi_callback_info info)182 napi_value NapiBluetoothOpp::GetCurrentTransferInformation(napi_env env, napi_callback_info info)
183 {
184 HILOGI("enter");
185
186 napi_value ret = nullptr;
187 napi_create_object(env, &ret);
188 napi_status checkRet = CheckEmptyParam(env, info);
189 NAPI_BT_ASSERT_RETURN(env, checkRet == napi_ok, BT_ERR_INVALID_PARAM, ret);
190
191 Opp *profile = Opp::GetProfile();
192 BluetoothOppTransferInformation information;
193 int32_t errorCode = profile->GetCurrentTransferInformation(information);
194 HILOGI("GetCurrentTransferInformation errorCode is %{public}d", errorCode);
195 NAPI_BT_ASSERT_RETURN_UNDEF(env, errorCode == BT_NO_ERROR, errorCode);
196
197 auto status = ConvertOppTransferInformationToJS(env, ret, information);
198 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INTERNAL_ERROR);
199 return ret;
200 }
201
CheckLastReceivedFileUri(napi_env env,napi_callback_info info,std::string & uri)202 napi_status CheckLastReceivedFileUri(napi_env env, napi_callback_info info, std::string &uri)
203 {
204 size_t argc = ARGS_SIZE_ONE;
205 napi_value argv[ARGS_SIZE_ONE] = {nullptr};
206 NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
207 NAPI_BT_RETURN_IF(argc != ARGS_SIZE_ONE, "Require 1 arguments.", napi_invalid_arg);
208 NAPI_BT_CALL_RETURN(NapiParseString(env, argv[PARAM0], uri));
209 return napi_ok;
210 }
211
SetLastReceivedFileUri(napi_env env,napi_callback_info info)212 napi_value NapiBluetoothOpp::SetLastReceivedFileUri(napi_env env, napi_callback_info info)
213 {
214 HILOGI("enter");
215
216 std::string uri {};
217
218 auto status = CheckLastReceivedFileUri(env, info, uri);
219 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
220
221 auto func = [uri]() {
222 Opp *profile = Opp::GetProfile();
223 bool result = false;
224 int32_t errorCode = profile->SetLastReceivedFileUri(uri);
225 HILOGI("err: %{public}d result: %{public}d", errorCode, result);
226 return NapiAsyncWorkRet(errorCode);
227 };
228 auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NO_NEED_CALLBACK);
229 NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
230 asyncWork->Run();
231 return asyncWork->GetRet();
232 }
233
CancelTransfer(napi_env env,napi_callback_info info)234 napi_value NapiBluetoothOpp::CancelTransfer(napi_env env, napi_callback_info info)
235 {
236 HILOGI("enter");
237
238 napi_value ret = nullptr;
239 bool isOk = false;
240 napi_get_boolean(env, isOk, &ret);
241 napi_status checkRet = CheckEmptyParam(env, info);
242 NAPI_BT_ASSERT_RETURN(env, checkRet == napi_ok, BT_ERR_INVALID_PARAM, ret);
243
244 Opp *profile = Opp::GetProfile();
245 profile->CancelTransfer(isOk);
246 napi_get_boolean(env, isOk, &ret);
247 return ret;
248 }
249
GetConnectionDevices(napi_env env,napi_callback_info info)250 napi_value NapiBluetoothOpp::GetConnectionDevices(napi_env env, napi_callback_info info)
251 {
252 HILOGI("enter");
253
254 napi_value ret = nullptr;
255 napi_create_array(env, &ret);
256 napi_status checkRet = CheckEmptyParam(env, info);
257 NAPI_BT_ASSERT_RETURN(env, checkRet == napi_ok, BT_ERR_INVALID_PARAM, ret);
258
259 Opp *profile = Opp::GetProfile();
260 vector<int32_t> states = { static_cast<int32_t>(BTConnectState::CONNECTED) };
261 vector<BluetoothRemoteDevice> devices {};
262 int32_t errorCode = profile->GetDevicesByStates(states, devices);
263 NAPI_BT_ASSERT_RETURN(env, errorCode == BT_NO_ERROR, errorCode, ret);
264
265 vector<string> deviceVector;
266 for (auto &device : devices) {
267 deviceVector.push_back(device.GetDeviceAddr());
268 }
269 auto status = ConvertStringVectorToJS(env, ret, deviceVector);
270 NAPI_BT_ASSERT_RETURN(env, status == napi_ok, BT_ERR_INTERNAL_ERROR, ret);
271 return ret;
272 }
273
GetDeviceState(napi_env env,napi_callback_info info)274 napi_value NapiBluetoothOpp::GetDeviceState(napi_env env, napi_callback_info info)
275 {
276 HILOGI("enter");
277 std::string remoteAddr{};
278 bool checkRet = CheckDeivceIdParam(env, info, remoteAddr);
279 NAPI_BT_ASSERT_RETURN_UNDEF(env, checkRet, BT_ERR_INVALID_PARAM);
280
281 Opp *profile = Opp::GetProfile();
282 BluetoothRemoteDevice device(remoteAddr, BT_TRANSPORT_BREDR);
283 int32_t state = static_cast<int32_t>(BTConnectState::DISCONNECTED);
284 int32_t errorCode = profile->GetDeviceState(device, state);
285 HILOGD("errorCode:%{public}s", GetErrorCode(errorCode).c_str());
286 NAPI_BT_ASSERT_RETURN_UNDEF(env, errorCode == BT_NO_ERROR, errorCode);
287
288 napi_value result = nullptr;
289 int32_t profileState = GetProfileConnectionState(state);
290 napi_create_int32(env, profileState, &result);
291 return result;
292 }
293 } // namespace Bluetooth
294 } // namespace OHOS