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_map_mse"
17 #endif
18 
19 #include "bluetooth_errorcode.h"
20 #include "bluetooth_map_mse.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_profile.h"
26 #include "napi_bluetooth_map_mse.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<NapiMapMseObserver> NapiMapMse::observer_ = std::make_shared<NapiMapMseObserver>();
36 thread_local napi_ref g_consRef_ = nullptr;
37 
DefineMapMseJSClass(napi_env env,napi_value exports)38 void NapiMapMse::DefineMapMseJSClass(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("getConnectedDevices", GetConnectedDevices),
45         DECLARE_NAPI_FUNCTION("getConnectionState", GetConnectionState),
46         DECLARE_NAPI_FUNCTION("setConnectionStrategy", SetConnectionStrategy),
47         DECLARE_NAPI_FUNCTION("getConnectionStrategy", GetConnectionStrategy),
48         DECLARE_NAPI_FUNCTION("disconnect", Disconnect),
49         DECLARE_NAPI_FUNCTION("setMessageAccessAuthorization", SetMessageAccessAuthorization),
50         DECLARE_NAPI_FUNCTION("getMessageAccessAuthorization", GetMessageAccessAuthorization),
51     };
52 
53     napi_define_class(env, "MapMse", NAPI_AUTO_LENGTH, MapMseConstructor, 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 NapiMapMse::DefineCreateProfile(napi_env env, napi_value exports)
61 {
62     napi_property_descriptor properties[] = {
63         DECLARE_NAPI_FUNCTION("createMapMseProfile", CreateMapMseProfile),
64     };
65     HITRACE_METER_NAME(HITRACE_TAG_OHOS, "mapmse:napi_define_properties");
66     napi_define_properties(env, exports, sizeof(properties) / sizeof(properties[0]), properties);
67     return exports;
68 }
69 
CreateMapMseProfile(napi_env env,napi_callback_info info)70 napi_value NapiMapMse::CreateMapMseProfile(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     MapMse *profile = MapMse::GetProfile();
78     profile->RegisterObserver(observer_);
79     return napiProfile;
80 }
81 
MapMseConstructor(napi_env env,napi_callback_info info)82 napi_value NapiMapMse::MapMseConstructor(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 NapiMapMse::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 NapiMapMse::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 
GetConnectedDevices(napi_env env,napi_callback_info info)107 napi_value NapiMapMse::GetConnectedDevices(napi_env env, napi_callback_info info)
108 {
109     HILOGI("enter");
110     napi_value ret = nullptr;
111     napi_create_array(env, &ret);
112     napi_status checkRet = CheckEmptyParam(env, info);
113     NAPI_BT_ASSERT_RETURN(env, checkRet == napi_ok, BT_ERR_INVALID_PARAM, ret);
114 
115     MapMse *profile = MapMse::GetProfile();
116     vector<int32_t> states = { static_cast<int32_t>(BTConnectState::CONNECTED) };
117     vector<BluetoothRemoteDevice> devices {};
118     int32_t errorCode = profile->GetDevicesByStates(states, devices);
119     NAPI_BT_ASSERT_RETURN(env, errorCode == BT_NO_ERROR, errorCode, ret);
120 
121     vector<string> deviceVector;
122     for (auto &device : devices) {
123         deviceVector.push_back(device.GetDeviceAddr());
124     }
125 
126     auto status = ConvertStringVectorToJS(env, ret, deviceVector);
127     NAPI_BT_ASSERT_RETURN(env, status == napi_ok, BT_ERR_INTERNAL_ERROR, ret);
128     return ret;
129 }
130 
GetConnectionState(napi_env env,napi_callback_info info)131 napi_value NapiMapMse::GetConnectionState(napi_env env, napi_callback_info info)
132 {
133     HILOGI("enter");
134     std::string remoteAddr {};
135     bool checkRet = CheckDeivceIdParam(env, info, remoteAddr);
136     NAPI_BT_ASSERT_RETURN_UNDEF(env, checkRet, BT_ERR_INVALID_PARAM);
137 
138     MapMse *profile = MapMse::GetProfile();
139     BluetoothRemoteDevice device(remoteAddr, BT_TRANSPORT_BREDR);
140     int32_t state = static_cast<int32_t>(BTConnectState::DISCONNECTED);
141     int32_t errorCode = profile->GetDeviceState(device, state);
142     HILOGI("errorCode:%{public}s", GetErrorCode(errorCode).c_str());
143     NAPI_BT_ASSERT_RETURN_UNDEF(env, errorCode == BT_NO_ERROR, errorCode);
144 
145     napi_value result = nullptr;
146     int32_t profileState = GetProfileConnectionState(state);
147     napi_create_int32(env, profileState, &result);
148     return result;
149 }
150 
Disconnect(napi_env env,napi_callback_info info)151 napi_value NapiMapMse::Disconnect(napi_env env, napi_callback_info info)
152 {
153     HILOGD("enter");
154     std::string remoteAddr{};
155     bool checkRet = CheckDeivceIdParam(env, info, remoteAddr);
156     NAPI_BT_ASSERT_RETURN_FALSE(env, checkRet, BT_ERR_INVALID_PARAM);
157 
158     MapMse *profile = MapMse::GetProfile();
159     BluetoothRemoteDevice device(remoteAddr, BT_TRANSPORT_BREDR);
160     int32_t errorCode = profile->Disconnect(device);
161     HILOGI("errorCode:%{public}s", GetErrorCode(errorCode).c_str());
162     NAPI_BT_ASSERT_RETURN_FALSE(env, errorCode == BT_NO_ERROR, errorCode);
163     return NapiGetBooleanTrue(env);
164 }
165 
SetConnectionStrategy(napi_env env,napi_callback_info info)166 napi_value NapiMapMse::SetConnectionStrategy(napi_env env, napi_callback_info info)
167 {
168     HILOGD("enter");
169     std::string remoteAddr{};
170     int32_t strategy = 0;
171     auto status = CheckSetConnectStrategyParam(env, info, remoteAddr, strategy);
172     NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
173 
174     auto func = [remoteAddr, strategy]() {
175         BluetoothRemoteDevice remoteDevice(remoteAddr, BT_TRANSPORT_BREDR);
176         MapMse *profile = MapMse::GetProfile();
177         int32_t errorCode = profile->SetConnectionStrategy(remoteDevice, strategy);
178         HILOGI("err: %{public}d", errorCode);
179         return NapiAsyncWorkRet(errorCode);
180     };
181     auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NO_NEED_CALLBACK);
182     NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
183     asyncWork->Run();
184     return asyncWork->GetRet();
185 }
186 
GetConnectionStrategy(napi_env env,napi_callback_info info)187 napi_value NapiMapMse::GetConnectionStrategy(napi_env env, napi_callback_info info)
188 {
189     HILOGD("enter");
190     std::string remoteAddr{};
191     auto status = CheckDeviceAddressParam(env, info, remoteAddr);
192     NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
193 
194     auto func = [remoteAddr]() {
195         int32_t strategy = 0;
196         BluetoothRemoteDevice remoteDevice(remoteAddr, BT_TRANSPORT_BREDR);
197         MapMse *profile = MapMse::GetProfile();
198         int32_t errorCode = profile->GetConnectionStrategy(remoteDevice, strategy);
199         HILOGI("errorCode: %{public}d, deviceName: %{public}d", errorCode, strategy);
200         auto object = std::make_shared<NapiNativeInt>(strategy);
201         return NapiAsyncWorkRet(errorCode, object);
202     };
203     auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NO_NEED_CALLBACK);
204     NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
205     asyncWork->Run();
206     return asyncWork->GetRet();
207 }
208 
SetMessageAccessAuthorization(napi_env env,napi_callback_info info)209 napi_value NapiMapMse::SetMessageAccessAuthorization(napi_env env, napi_callback_info info)
210 {
211     std::string remoteAddr{};
212     int32_t accessAuthorization = 0;
213     auto status = CheckAccessAuthorizationParam(env, info, remoteAddr, accessAuthorization);
214     NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
215 
216     auto func = [remoteAddr, accessAuthorization]() {
217         BluetoothRemoteDevice remoteDevice(remoteAddr, BT_TRANSPORT_BREDR);
218         MapMse *profile = MapMse::GetProfile();
219         int32_t errorCode = profile->SetMessageAccessAuthorization(remoteDevice, accessAuthorization);
220         HILOGI("errorCode: %{public}d", errorCode);
221         return NapiAsyncWorkRet(errorCode);
222     };
223     auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NO_NEED_CALLBACK);
224     NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
225     asyncWork->Run();
226     return asyncWork->GetRet();
227 }
228 
GetMessageAccessAuthorization(napi_env env,napi_callback_info info)229 napi_value NapiMapMse::GetMessageAccessAuthorization(napi_env env, napi_callback_info info)
230 {
231     std::string remoteAddr{};
232     auto status = CheckDeviceAddressParam(env, info, remoteAddr);
233     NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
234 
235     auto func = [remoteAddr]() {
236         int32_t accessAuthorization = 0;
237         BluetoothRemoteDevice remoteDevice(remoteAddr, BT_TRANSPORT_BREDR);
238         MapMse *profile = MapMse::GetProfile();
239         int32_t errorCode = profile->GetMessageAccessAuthorization(remoteDevice, accessAuthorization);
240         HILOGI("errorCode: %{public}d, accessAuthorization: %{public}d", errorCode, accessAuthorization);
241         auto object = std::make_shared<NapiNativeInt>(accessAuthorization);
242         return NapiAsyncWorkRet(errorCode, object);
243     };
244     auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NO_NEED_CALLBACK);
245     NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
246     asyncWork->Run();
247     return asyncWork->GetRet();
248 }
249 
250 }  // namespace Bluetooth
251 }  // namespace OHOS