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("onEvent", On),
45 DECLARE_NAPI_FUNCTION("offEvent", Off),
46 DECLARE_NAPI_FUNCTION("sendFile", SendFile),
47 DECLARE_NAPI_FUNCTION("setIncomingFileConfirmation", SetIncomingFileConfirmation),
48 DECLARE_NAPI_FUNCTION("getCurrentTransferInformation", GetCurrentTransferInformation),
49 DECLARE_NAPI_FUNCTION("cancelTransfer", CancelTransfer),
50 DECLARE_NAPI_FUNCTION("getConnectionDevices", GetConnectionDevices),
51 DECLARE_NAPI_FUNCTION("getDeviceState", GetDeviceState),
52 };
53
54 napi_define_class(env, "NapiBluetoothOpp", NAPI_AUTO_LENGTH, OppConstructor, nullptr,
55 sizeof(properties) / sizeof(properties[0]), properties, &constructor);
56
57 DefineCreateProfile(env, exports);
58 napi_create_reference(env, constructor, 1, &g_consRef_);
59 }
60
DefineCreateProfile(napi_env env,napi_value exports)61 napi_value NapiBluetoothOpp::DefineCreateProfile(napi_env env, napi_value exports)
62 {
63 napi_property_descriptor properties[] = {
64 DECLARE_NAPI_FUNCTION("createOppServerProfile", CreateOppServerProfile),
65 };
66 HITRACE_METER_NAME(HITRACE_TAG_OHOS, "opp:napi_define_properties");
67 napi_define_properties(env, exports, sizeof(properties) / sizeof(properties[0]), properties);
68 return exports;
69 }
70
CreateOppServerProfile(napi_env env,napi_callback_info info)71 napi_value NapiBluetoothOpp::CreateOppServerProfile(napi_env env, napi_callback_info info)
72 {
73 napi_value napiProfile;
74 napi_value constructor = nullptr;
75 napi_get_reference_value(env, g_consRef_, &constructor);
76 napi_new_instance(env, constructor, 0, nullptr, &napiProfile);
77
78 Opp *profile = Opp::GetProfile();
79 profile->RegisterObserver(observer_);
80 return napiProfile;
81 }
82
OppConstructor(napi_env env,napi_callback_info info)83 napi_value NapiBluetoothOpp::OppConstructor(napi_env env, napi_callback_info info)
84 {
85 napi_value thisVar = nullptr;
86 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
87 return thisVar;
88 }
89
On(napi_env env,napi_callback_info info)90 napi_value NapiBluetoothOpp::On(napi_env env, napi_callback_info info)
91 {
92 if (observer_) {
93 auto status = observer_->eventSubscribe_.Register(env, info);
94 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
95 }
96 return NapiGetUndefinedRet(env);
97 }
98
Off(napi_env env,napi_callback_info info)99 napi_value NapiBluetoothOpp::Off(napi_env env, napi_callback_info info)
100 {
101 if (observer_) {
102 auto status = observer_->eventSubscribe_.Deregister(env, info);
103 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
104 }
105 return NapiGetUndefinedRet(env);
106 }
107
CheckSetIncomingFileConfirmation(napi_env env,napi_callback_info info,bool & accept)108 napi_status CheckSetIncomingFileConfirmation(napi_env env, napi_callback_info info, bool &accept)
109 {
110 size_t argc = ARGS_SIZE_ONE;
111 napi_value argv[ARGS_SIZE_ONE] = {nullptr};
112 NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
113 NAPI_BT_RETURN_IF(argc != ARGS_SIZE_ONE, "Require 1 arguments.", napi_invalid_arg);
114 NAPI_BT_CALL_RETURN(NapiParseBoolean(env, argv[PARAM0], accept));
115 return napi_ok;
116 }
117
CheckSendFileParam(napi_env env,napi_callback_info info,std::string & addr,std::vector<std::string> & filePaths,std::vector<std::string> & mimeTypes)118 napi_status CheckSendFileParam(napi_env env, napi_callback_info info, std::string &addr,
119 std::vector<std::string> &filePaths, std::vector<std::string> &mimeTypes)
120 {
121 size_t argc = ARGS_SIZE_THREE;
122 napi_value argv[ARGS_SIZE_THREE] = {nullptr};
123 NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
124 NAPI_BT_RETURN_IF(argc != ARGS_SIZE_THREE, "Require 3 arguments.", napi_invalid_arg);
125 NAPI_BT_CALL_RETURN(NapiParseBdAddr(env, argv[PARAM0], addr));
126 NAPI_BT_CALL_RETURN(NapiParseStringArray(env, argv[PARAM1], filePaths));
127 NAPI_BT_CALL_RETURN(NapiParseStringArray(env, argv[PARAM2], mimeTypes));
128 return napi_ok;
129 }
130
SendFile(napi_env env,napi_callback_info info)131 napi_value NapiBluetoothOpp::SendFile(napi_env env, napi_callback_info info)
132 {
133 HILOGI("enter");
134
135 std::string device {};
136 std::vector<std::string> filePaths;
137 std::vector<std::string> mimeTypes;
138
139 auto status = CheckSendFileParam(env, info, device, filePaths, mimeTypes);
140 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
141
142 auto func = [device, filePaths, mimeTypes]() {
143 Opp *profile = Opp::GetProfile();
144 bool result = false;
145 int32_t errorCode = profile->SendFile(device, filePaths, mimeTypes, result);
146 HILOGI("err: %{public}d result: %{public}d", errorCode, result);
147 return NapiAsyncWorkRet(errorCode);
148 };
149 auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NO_NEED_CALLBACK);
150 NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
151 asyncWork->Run();
152 return asyncWork->GetRet();
153 }
154
SetIncomingFileConfirmation(napi_env env,napi_callback_info info)155 napi_value NapiBluetoothOpp::SetIncomingFileConfirmation(napi_env env, napi_callback_info info)
156 {
157 HILOGI("enter");
158
159 bool accept = false;
160 auto status = CheckSetIncomingFileConfirmation(env, info, accept);
161 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
162
163 auto func = [accept]() {
164 Opp *profile = Opp::GetProfile();
165 int32_t errorCode = profile->SetIncomingFileConfirmation(accept);
166 HILOGI("err: %{public}d", errorCode);
167 return NapiAsyncWorkRet(errorCode);
168 };
169 auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NO_NEED_CALLBACK);
170 NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
171 asyncWork->Run();
172 return asyncWork->GetRet();
173 }
174
GetCurrentTransferInformation(napi_env env,napi_callback_info info)175 napi_value NapiBluetoothOpp::GetCurrentTransferInformation(napi_env env, napi_callback_info info)
176 {
177 HILOGI("enter");
178
179 napi_value ret = nullptr;
180 napi_create_object(env, &ret);
181 napi_status checkRet = CheckEmptyParam(env, info);
182 NAPI_BT_ASSERT_RETURN(env, checkRet == napi_ok, BT_ERR_INVALID_PARAM, ret);
183
184 Opp *profile = Opp::GetProfile();
185 BluetoothOppTransferInformation information;
186 int32_t errorCode = profile->GetCurrentTransferInformation(information);
187 HILOGI("GetCurrentTransferInformation errorCode is %{public}d", errorCode);
188 NAPI_BT_ASSERT_RETURN_UNDEF(env, errorCode == BT_NO_ERROR, errorCode);
189
190 auto status = ConvertOppTransferInformationToJS(env, ret, information);
191 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INTERNAL_ERROR);
192 return ret;
193 }
194
CancelTransfer(napi_env env,napi_callback_info info)195 napi_value NapiBluetoothOpp::CancelTransfer(napi_env env, napi_callback_info info)
196 {
197 HILOGI("enter");
198
199 napi_value ret = nullptr;
200 bool isOk = false;
201 napi_get_boolean(env, isOk, &ret);
202 napi_status checkRet = CheckEmptyParam(env, info);
203 NAPI_BT_ASSERT_RETURN(env, checkRet == napi_ok, BT_ERR_INVALID_PARAM, ret);
204
205 Opp *profile = Opp::GetProfile();
206 profile->CancelTransfer(isOk);
207 napi_get_boolean(env, isOk, &ret);
208 return ret;
209 }
210
GetConnectionDevices(napi_env env,napi_callback_info info)211 napi_value NapiBluetoothOpp::GetConnectionDevices(napi_env env, napi_callback_info info)
212 {
213 HILOGI("enter");
214
215 napi_value ret = nullptr;
216 napi_create_array(env, &ret);
217 napi_status checkRet = CheckEmptyParam(env, info);
218 NAPI_BT_ASSERT_RETURN(env, checkRet == napi_ok, BT_ERR_INVALID_PARAM, ret);
219
220 Opp *profile = Opp::GetProfile();
221 vector<int32_t> states = { static_cast<int32_t>(BTConnectState::CONNECTED) };
222 vector<BluetoothRemoteDevice> devices {};
223 int32_t errorCode = profile->GetDevicesByStates(states, devices);
224 NAPI_BT_ASSERT_RETURN(env, errorCode == BT_NO_ERROR, errorCode, ret);
225
226 vector<string> deviceVector;
227 for (auto &device : devices) {
228 deviceVector.push_back(device.GetDeviceAddr());
229 }
230 auto status = ConvertStringVectorToJS(env, ret, deviceVector);
231 NAPI_BT_ASSERT_RETURN(env, status == napi_ok, BT_ERR_INTERNAL_ERROR, ret);
232 return ret;
233 }
234
GetDeviceState(napi_env env,napi_callback_info info)235 napi_value NapiBluetoothOpp::GetDeviceState(napi_env env, napi_callback_info info)
236 {
237 HILOGI("enter");
238 std::string remoteAddr{};
239 bool checkRet = CheckDeivceIdParam(env, info, remoteAddr);
240 NAPI_BT_ASSERT_RETURN_UNDEF(env, checkRet, BT_ERR_INVALID_PARAM);
241
242 Opp *profile = Opp::GetProfile();
243 BluetoothRemoteDevice device(remoteAddr, BT_TRANSPORT_BREDR);
244 int32_t state = static_cast<int32_t>(BTConnectState::DISCONNECTED);
245 int32_t errorCode = profile->GetDeviceState(device, state);
246 HILOGD("errorCode:%{public}s", GetErrorCode(errorCode).c_str());
247 NAPI_BT_ASSERT_RETURN_UNDEF(env, errorCode == BT_NO_ERROR, errorCode);
248
249 napi_value result = nullptr;
250 int32_t profileState = GetProfileConnectionState(state);
251 napi_create_int32(env, profileState, &result);
252 return result;
253 }
254 } // namespace Bluetooth
255 } // namespace OHOS