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 #include "hitrace_meter.h"
28 
29 namespace OHOS {
30 namespace Bluetooth {
31 namespace {
32 std::shared_ptr<NapiBluetoothAccessObserver> g_bluetoothAccessObserver =
33     std::make_shared<NapiBluetoothAccessObserver>();
34 }  // namespace
35 
DefineAccessJSFunction(napi_env env, napi_value exports)36 napi_value NapiAccess::DefineAccessJSFunction(napi_env env, napi_value exports)
37 {
38     HILOGD("enter");
39     RegisterAccessObserverToHost();
40     AccessPropertyValueInit(env, exports);
41     napi_property_descriptor desc[] = {
42         DECLARE_NAPI_FUNCTION("getState", GetState),
43         DECLARE_NAPI_FUNCTION("enableBluetooth", EnableBluetooth),
44         DECLARE_NAPI_FUNCTION("disableBluetooth", DisableBluetooth),
45         DECLARE_NAPI_FUNCTION("restrictBluetooth", RestrictBluetooth),
46 #ifdef BLUETOOTH_API_SINCE_10
47         DECLARE_NAPI_FUNCTION("factoryReset", FactoryReset),
48         DECLARE_NAPI_FUNCTION("getLocalAddress", GetLocalAddress),
49         DECLARE_NAPI_FUNCTION("on", RegisterAccessObserver),
50         DECLARE_NAPI_FUNCTION("off", DeregisterAccessObserver),
51 #endif
52     };
53     HITRACE_METER_NAME(HITRACE_TAG_OHOS, "access:napi_define_properties");
54     napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
55     return exports;
56 }
57 
RegisterAccessObserverToHost()58 void NapiAccess::RegisterAccessObserverToHost()
59 {
60     BluetoothHost *host = &BluetoothHost::GetDefaultHost();
61     host->RegisterObserver(g_bluetoothAccessObserver);
62 }
63 
EnableBluetooth(napi_env env, napi_callback_info info)64 napi_value NapiAccess::EnableBluetooth(napi_env env, napi_callback_info info)
65 {
66     HILOGI("enter");
67     BluetoothHost *host = &BluetoothHost::GetDefaultHost();
68     int32_t ret = host->EnableBle();
69     NAPI_BT_ASSERT_RETURN_FALSE(env, ret == BT_NO_ERROR, ret);
70     return NapiGetBooleanTrue(env);
71 }
72 
RestrictBluetooth(napi_env env, napi_callback_info info)73 napi_value NapiAccess::RestrictBluetooth(napi_env env, napi_callback_info info)
74 {
75     HILOGI("enter");
76     BluetoothHost *host = &BluetoothHost::GetDefaultHost();
77     int32_t ret = host->RestrictBluetooth();
78     NAPI_BT_ASSERT_RETURN_FALSE(env, ret == BT_NO_ERROR, ret);
79     return NapiGetBooleanTrue(env);
80 }
81 
DisableBluetooth(napi_env env, napi_callback_info info)82 napi_value NapiAccess::DisableBluetooth(napi_env env, napi_callback_info info)
83 {
84     HILOGI("enter");
85     BluetoothHost *host = &BluetoothHost::GetDefaultHost();
86     int ret = host->DisableBt();
87     NAPI_BT_ASSERT_RETURN_FALSE(env, ret == BT_NO_ERROR, ret);
88     return NapiGetBooleanTrue(env);
89 }
90 
GetState(napi_env env, napi_callback_info info)91 napi_value NapiAccess::GetState(napi_env env, napi_callback_info info)
92 {
93     HILOGD("enter");
94     BluetoothHost *host = &BluetoothHost::GetDefaultHost();
95     int32_t state = BTStateID::STATE_TURN_OFF;
96     int32_t err = host->GetBtState(state);
97     NAPI_BT_ASSERT_RETURN_FALSE(env, err == NO_ERROR, err);
98     int32_t status = static_cast<int32_t>(BluetoothState::STATE_OFF);
99     switch (state) {
100         case BTStateID::STATE_TURNING_ON:
101             HILOGI("STATE_TURNING_ON(1)");
102             status = static_cast<int32_t>(BluetoothState::STATE_TURNING_ON);
103             break;
104         case BTStateID::STATE_TURN_ON:
105             HILOGD("STATE_ON(2)");
106             status = static_cast<int32_t>(BluetoothState::STATE_ON);
107             break;
108         case BTStateID::STATE_TURNING_OFF:
109             HILOGI("STATE_TURNING_OFF(3)");
110             status = static_cast<int32_t>(BluetoothState::STATE_TURNING_OFF);
111             break;
112         case BTStateID::STATE_TURN_OFF:
113             HILOGD("STATE_OFF(0)");
114             status = static_cast<int32_t>(BluetoothState::STATE_OFF);
115             break;
116         default:
117             HILOGE("get state failed");
118             break;
119     }
120 
121     bool enableBle = host->IsBleEnabled();
122     if (enableBle && (state == BTStateID::STATE_TURN_OFF)) {
123         HILOGD("BR off and BLE on, STATE_BLE_ON(5)");
124         status = static_cast<int32_t>(BluetoothState::STATE_BLE_ON);
125     } else if (!enableBle && (state == BTStateID::STATE_TURN_OFF)) {
126         status = static_cast<int32_t>(BluetoothState::STATE_OFF);
127     }
128 
129     napi_value result = nullptr;
130     napi_create_int32(env, status, &result);
131     return result;
132 }
133 
AccessPropertyValueInit(napi_env env, napi_value exports)134 napi_value NapiAccess::AccessPropertyValueInit(napi_env env, napi_value exports)
135 {
136     HILOGD("enter");
137     napi_value stateObj = StateChangeInit(env);
138     napi_property_descriptor exportFuncs[] = {
139         DECLARE_NAPI_PROPERTY("BluetoothState", stateObj),
140     };
141     HITRACE_METER_NAME(HITRACE_TAG_OHOS, "access:napi_define_properties");
142     napi_define_properties(env, exports, sizeof(exportFuncs) / sizeof(*exportFuncs), exportFuncs);
143     return exports;
144 }
145 
StateChangeInit(napi_env env)146 napi_value NapiAccess::StateChangeInit(napi_env env)
147 {
148     HILOGD("enter");
149     napi_value state = nullptr;
150     napi_create_object(env, &state);
151     SetNamedPropertyByInteger(env, state, static_cast<int>(BluetoothState::STATE_OFF), "STATE_OFF");
152     SetNamedPropertyByInteger(env, state, static_cast<int>(BluetoothState::STATE_TURNING_ON), "STATE_TURNING_ON");
153     SetNamedPropertyByInteger(env, state, static_cast<int>(BluetoothState::STATE_ON), "STATE_ON");
154     SetNamedPropertyByInteger(env, state, static_cast<int>(BluetoothState::STATE_TURNING_OFF), "STATE_TURNING_OFF");
155     SetNamedPropertyByInteger(
156         env, state, static_cast<int>(BluetoothState::STATE_BLE_TURNING_ON), "STATE_BLE_TURNING_ON");
157     SetNamedPropertyByInteger(env, state, static_cast<int>(BluetoothState::STATE_BLE_ON), "STATE_BLE_ON");
158     SetNamedPropertyByInteger(
159         env, state, static_cast<int>(BluetoothState::STATE_BLE_TURNING_OFF), "STATE_BLE_TURNING_OFF");
160     return state;
161 }
162 
RegisterAccessObserver(napi_env env, napi_callback_info info)163 napi_value NapiAccess::RegisterAccessObserver(napi_env env, napi_callback_info info)
164 {
165     if (g_bluetoothAccessObserver) {
166         auto status = g_bluetoothAccessObserver->eventSubscribe_.Register(env, info);
167         NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
168     }
169     return NapiGetUndefinedRet(env);
170 }
171 
DeregisterAccessObserver(napi_env env, napi_callback_info info)172 napi_value NapiAccess::DeregisterAccessObserver(napi_env env, napi_callback_info info)
173 {
174     if (g_bluetoothAccessObserver) {
175         auto status = g_bluetoothAccessObserver->eventSubscribe_.Deregister(env, info);
176         NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
177     }
178     return NapiGetUndefinedRet(env);
179 }
180 
181 #ifdef BLUETOOTH_API_SINCE_10
FactoryReset(napi_env env, napi_callback_info info)182 napi_value NapiAccess::FactoryReset(napi_env env, napi_callback_info info)
183 {
184     HILOGD("enter");
185     auto func = []() {
186         int32_t ret = BluetoothHost::GetDefaultHost().BluetoothFactoryReset();
187         HILOGI("factoryReset ret: %{public}d", ret);
188         return NapiAsyncWorkRet(ret);
189     };
190     auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NO_NEED_CALLBACK);
191     NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
192     asyncWork->Run();
193     return asyncWork->GetRet();
194 }
195 
GetLocalAddress(napi_env env, napi_callback_info info)196 napi_value NapiAccess::GetLocalAddress(napi_env env, napi_callback_info info)
197 {
198     napi_value result = nullptr;
199     HILOGI("enter");
200     BluetoothHost *host = &BluetoothHost::GetDefaultHost();
201     std::string localAddr = INVALID_MAC_ADDRESS;
202     int32_t err = host->GetLocalAddress(localAddr);
203     napi_create_string_utf8(env, localAddr.c_str(), localAddr.size(), &result);
204     NAPI_BT_ASSERT_RETURN(env, err == BT_NO_ERROR, err, result);
205     return result;
206 }
207 #endif
208 }  // namespace Bluetooth
209 }  // namespace OHOS
210