• 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 #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