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 "napi_bluetooth_access.h"
17
18 #include "bluetooth_log.h"
19 #include "bluetooth_errorcode.h"
20 #include "bluetooth_host.h"
21
22 #include "napi_bluetooth_error.h"
23 #include "napi_bluetooth_access_observer.h"
24 #include "napi_bluetooth_utils.h"
25 #include "napi_bluetooth_spp_client.h"
26 #include "../parser/napi_parser_utils.h"
27
28 namespace OHOS {
29 namespace Bluetooth {
30 namespace {
31 std::shared_ptr<NapiBluetoothAccessObserver> g_bluetoothAccessObserver =
32 std::make_shared<NapiBluetoothAccessObserver>();
33 } // namespace
34
DefineAccessJSFunction(napi_env env,napi_value exports)35 napi_value NapiAccess::DefineAccessJSFunction(napi_env env, napi_value exports)
36 {
37 HILOGD("enter");
38 RegisterAccessObserverToHost();
39 AccessPropertyValueInit(env, exports);
40 napi_property_descriptor desc[] = {
41 DECLARE_NAPI_FUNCTION("getState", GetState),
42 DECLARE_NAPI_FUNCTION("enableBluetooth", EnableBluetooth),
43 DECLARE_NAPI_FUNCTION("disableBluetooth", DisableBluetooth),
44 #ifdef BLUETOOTH_API_SINCE_10
45 DECLARE_NAPI_FUNCTION("factoryReset", FactoryReset),
46 DECLARE_NAPI_FUNCTION("getLocalAddress", GetLocalAddress),
47 DECLARE_NAPI_FUNCTION("on", RegisterAccessObserver),
48 DECLARE_NAPI_FUNCTION("off", DeregisterAccessObserver),
49 #endif
50 };
51 napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
52 return exports;
53 }
54
RegisterAccessObserverToHost()55 void NapiAccess::RegisterAccessObserverToHost()
56 {
57 BluetoothHost *host = &BluetoothHost::GetDefaultHost();
58 host->RegisterObserver(g_bluetoothAccessObserver);
59 }
60
EnableBluetooth(napi_env env,napi_callback_info info)61 napi_value NapiAccess::EnableBluetooth(napi_env env, napi_callback_info info)
62 {
63 HILOGI("enter");
64 BluetoothHost *host = &BluetoothHost::GetDefaultHost();
65 int32_t ret = host->EnableBle();
66 NAPI_BT_ASSERT_RETURN_FALSE(env, ret == BT_NO_ERROR, ret);
67 return NapiGetBooleanTrue(env);
68 }
69
DisableBluetooth(napi_env env,napi_callback_info info)70 napi_value NapiAccess::DisableBluetooth(napi_env env, napi_callback_info info)
71 {
72 HILOGI("enter");
73 BluetoothHost *host = &BluetoothHost::GetDefaultHost();
74 int ret = host->DisableBt();
75 NAPI_BT_ASSERT_RETURN_FALSE(env, ret == BT_NO_ERROR, ret);
76 return NapiGetBooleanTrue(env);
77 }
78
GetState(napi_env env,napi_callback_info info)79 napi_value NapiAccess::GetState(napi_env env, napi_callback_info info)
80 {
81 HILOGD("enter");
82 BluetoothHost *host = &BluetoothHost::GetDefaultHost();
83 int32_t state = BTStateID::STATE_TURN_OFF;
84 int32_t err = host->GetBtState(state);
85 NAPI_BT_ASSERT_RETURN_FALSE(env, err == NO_ERROR, err);
86 int32_t status = static_cast<int32_t>(BluetoothState::STATE_OFF);
87 switch (state) {
88 case BTStateID::STATE_TURNING_ON:
89 HILOGI("STATE_TURNING_ON(1)");
90 status = static_cast<int32_t>(BluetoothState::STATE_TURNING_ON);
91 break;
92 case BTStateID::STATE_TURN_ON:
93 HILOGD("STATE_ON(2)");
94 status = static_cast<int32_t>(BluetoothState::STATE_ON);
95 break;
96 case BTStateID::STATE_TURNING_OFF:
97 HILOGI("STATE_TURNING_OFF(3)");
98 status = static_cast<int32_t>(BluetoothState::STATE_TURNING_OFF);
99 break;
100 case BTStateID::STATE_TURN_OFF:
101 HILOGI("STATE_OFF(0)");
102 status = static_cast<int32_t>(BluetoothState::STATE_OFF);
103 break;
104 default:
105 HILOGE("get state failed");
106 break;
107 }
108
109 bool enableBle = host->IsBleEnabled();
110 if (enableBle && (state == BTStateID::STATE_TURN_OFF)) {
111 HILOGI("BR off and BLE on, STATE_BLE_ON(5)");
112 status = static_cast<int32_t>(BluetoothState::STATE_BLE_ON);
113 } else if (!enableBle && (state == BTStateID::STATE_TURN_OFF)) {
114 status = static_cast<int32_t>(BluetoothState::STATE_OFF);
115 }
116
117 napi_value result = nullptr;
118 napi_create_int32(env, status, &result);
119 return result;
120 }
121
AccessPropertyValueInit(napi_env env,napi_value exports)122 napi_value NapiAccess::AccessPropertyValueInit(napi_env env, napi_value exports)
123 {
124 HILOGD("enter");
125 napi_value stateObj = StateChangeInit(env);
126 napi_property_descriptor exportFuncs[] = {
127 DECLARE_NAPI_PROPERTY("BluetoothState", stateObj),
128 };
129 napi_define_properties(env, exports, sizeof(exportFuncs) / sizeof(*exportFuncs), exportFuncs);
130 return exports;
131 }
132
StateChangeInit(napi_env env)133 napi_value NapiAccess::StateChangeInit(napi_env env)
134 {
135 HILOGD("enter");
136 napi_value state = nullptr;
137 napi_create_object(env, &state);
138 SetNamedPropertyByInteger(env, state, static_cast<int>(BluetoothState::STATE_OFF), "STATE_OFF");
139 SetNamedPropertyByInteger(env, state, static_cast<int>(BluetoothState::STATE_TURNING_ON), "STATE_TURNING_ON");
140 SetNamedPropertyByInteger(env, state, static_cast<int>(BluetoothState::STATE_ON), "STATE_ON");
141 SetNamedPropertyByInteger(env, state, static_cast<int>(BluetoothState::STATE_TURNING_OFF), "STATE_TURNING_OFF");
142 SetNamedPropertyByInteger(
143 env, state, static_cast<int>(BluetoothState::STATE_BLE_TURNING_ON), "STATE_BLE_TURNING_ON");
144 SetNamedPropertyByInteger(env, state, static_cast<int>(BluetoothState::STATE_BLE_ON), "STATE_BLE_ON");
145 SetNamedPropertyByInteger(
146 env, state, static_cast<int>(BluetoothState::STATE_BLE_TURNING_OFF), "STATE_BLE_TURNING_OFF");
147 return state;
148 }
149
IsValidObserverType(const std::string & outType)150 static bool IsValidObserverType(const std::string &outType)
151 {
152 return outType == REGISTER_STATE_CHANGE_TYPE;
153 }
154
NapiParseObserverType(napi_env env,napi_value value,std::string & outType)155 static napi_status NapiParseObserverType(napi_env env, napi_value value, std::string &outType)
156 {
157 std::string type{};
158 NAPI_BT_CALL_RETURN(NapiParseString(env, value, type));
159 HILOGI("type: %{public}s", type.c_str());
160 NAPI_BT_RETURN_IF(!IsValidObserverType(type), "Invalid type", napi_invalid_arg);
161 outType = std::move(type);
162 return napi_ok;
163 }
164
CheckAccessObserverParams(napi_env env,napi_callback_info info)165 static napi_status CheckAccessObserverParams(napi_env env, napi_callback_info info)
166 {
167 size_t argc = ARGS_SIZE_TWO;
168 napi_value argv[ARGS_SIZE_TWO] = {0};
169 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
170 NAPI_BT_RETURN_IF(argc != ARGS_SIZE_TWO, "Requires 2 arguments.", napi_invalid_arg);
171 std::string type;
172 NAPI_BT_CALL_RETURN(NapiParseObserverType(env, argv[PARAM0], type));
173 HILOGI("%{public}s is registered", type.c_str());
174
175 g_bluetoothAccessObserver->napiStateChangeCallback_ = std::make_shared<NapiCallback>(env, argv[PARAM1]);
176 return napi_ok;
177 }
178
RegisterAccessObserver(napi_env env,napi_callback_info info)179 napi_value NapiAccess::RegisterAccessObserver(napi_env env, napi_callback_info info)
180 {
181 auto status = CheckAccessObserverParams(env, info);
182 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
183 return NapiGetUndefinedRet(env);
184 }
185
CheckAccessDeregisterObserver(napi_env env,napi_callback_info info)186 static napi_status CheckAccessDeregisterObserver(napi_env env, napi_callback_info info)
187 {
188 size_t argc = ARGS_SIZE_TWO;
189 napi_value argv[ARGS_SIZE_TWO] = {0};
190 napi_value thisVar = nullptr;
191 NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr));
192 NAPI_BT_RETURN_IF(argc != ARGS_SIZE_ONE && argc != ARGS_SIZE_TWO, "Requires 1 or 2 arguments.", napi_invalid_arg);
193
194 std::string type;
195 NAPI_BT_CALL_RETURN(NapiParseObserverType(env, argv[PARAM0], type));
196 HILOGI("%{public}s is unregistered", type.c_str());
197
198 g_bluetoothAccessObserver->napiStateChangeCallback_ = nullptr;
199 return napi_ok;
200 }
201
DeregisterAccessObserver(napi_env env,napi_callback_info info)202 napi_value NapiAccess::DeregisterAccessObserver(napi_env env, napi_callback_info info)
203 {
204 HILOGI("enter");
205 auto status = CheckAccessDeregisterObserver(env, info);
206 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
207 return NapiGetUndefinedRet(env);
208 }
209
210 #ifdef BLUETOOTH_API_SINCE_10
FactoryReset(napi_env env,napi_callback_info info)211 napi_value NapiAccess::FactoryReset(napi_env env, napi_callback_info info)
212 {
213 HILOGD("enter");
214 auto func = []() {
215 int32_t ret = BluetoothHost::GetDefaultHost().BluetoothFactoryReset();
216 HILOGI("factoryReset ret: %{public}d", ret);
217 return NapiAsyncWorkRet(ret);
218 };
219 auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NO_NEED_CALLBACK);
220 NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
221 asyncWork->Run();
222 return asyncWork->GetRet();
223 }
224
GetLocalAddress(napi_env env,napi_callback_info info)225 napi_value NapiAccess::GetLocalAddress(napi_env env, napi_callback_info info)
226 {
227 napi_value result = nullptr;
228 HILOGI("enter");
229 BluetoothHost *host = &BluetoothHost::GetDefaultHost();
230 std::string localAddr = INVALID_MAC_ADDRESS;
231 int32_t err = host->GetLocalAddress(localAddr);
232 napi_create_string_utf8(env, localAddr.c_str(), localAddr.size(), &result);
233 NAPI_BT_ASSERT_RETURN(env, err == BT_NO_ERROR, err, result);
234 return result;
235 }
236 #endif
237 } // namespace Bluetooth
238 } // namespace OHOS
239