1 /*
2  * Copyright (C) 2021-2022 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_avrcp_tg"
17 #endif
18 
19 #include "bluetooth_avrcp_tg.h"
20 #include "bluetooth_errorcode.h"
21 #include "napi_bluetooth_avrcp_tg.h"
22 #include "napi_bluetooth_profile.h"
23 #include "napi_bluetooth_event.h"
24 #include "napi_bluetooth_error.h"
25 #include "napi_event_subscribe_module.h"
26 
27 namespace OHOS {
28 namespace Bluetooth {
29 using namespace std;
30 
31 std::shared_ptr<NapiAvrcpTargetObserver> NapiAvrcpTarget::observer_ = std::make_shared<NapiAvrcpTargetObserver>();
32 bool NapiAvrcpTarget::isRegistered_ = false;
33 
DefineAvrcpTargetJSClass(napi_env env)34 void NapiAvrcpTarget::DefineAvrcpTargetJSClass(napi_env env)
35 {
36     napi_value constructor;
37     napi_property_descriptor properties[] = {
38         DECLARE_NAPI_FUNCTION("connect", Connect),
39         DECLARE_NAPI_FUNCTION("disconnect", Disconnect),
40         DECLARE_NAPI_FUNCTION("on", On),
41         DECLARE_NAPI_FUNCTION("off", Off),
42         DECLARE_NAPI_FUNCTION("getConnectionDevices", GetConnectionDevices),
43         DECLARE_NAPI_FUNCTION("getDeviceState", GetDeviceState),
44     };
45 
46     napi_define_class(env, "AvrcpTarget", NAPI_AUTO_LENGTH, AvrcpTargetConstructor, nullptr,
47         sizeof(properties) / sizeof(properties[0]), properties, &constructor);
48     napi_value napiProfile;
49     napi_new_instance(env, constructor, 0, nullptr, &napiProfile);
50     NapiProfile::SetProfile(env, ProfileId::PROFILE_AVRCP_TG, napiProfile);
51 }
52 
AvrcpTargetConstructor(napi_env env,napi_callback_info info)53 napi_value NapiAvrcpTarget::AvrcpTargetConstructor(napi_env env, napi_callback_info info)
54 {
55     napi_value thisVar = nullptr;
56     napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
57     return thisVar;
58 }
59 
On(napi_env env,napi_callback_info info)60 napi_value NapiAvrcpTarget::On(napi_env env, napi_callback_info info)
61 {
62     if (observer_) {
63         auto status = observer_->eventSubscribe_.Register(env, info);
64         NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
65     }
66 
67     if (!isRegistered_) {
68         AvrcpTarget *profile = AvrcpTarget::GetProfile();
69         profile->RegisterObserver(observer_);
70         isRegistered_ = true;
71     }
72     HILOGI("Napi Avrcp Target is registered");
73     return NapiGetUndefinedRet(env);
74 }
75 
Off(napi_env env,napi_callback_info info)76 napi_value NapiAvrcpTarget::Off(napi_env env, napi_callback_info info)
77 {
78     if (observer_) {
79         auto status = observer_->eventSubscribe_.Deregister(env, info);
80         NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
81     }
82     return NapiGetUndefinedRet(env);
83 }
84 
GetConnectionDevices(napi_env env,napi_callback_info info)85 napi_value NapiAvrcpTarget::GetConnectionDevices(napi_env env, napi_callback_info info)
86 {
87     HILOGI("enter");
88     napi_value ret = nullptr;
89     napi_create_array(env, &ret);
90     AvrcpTarget *profile = AvrcpTarget::GetProfile();
91     vector<int> states;
92     states.push_back(1);
93     vector<BluetoothRemoteDevice> devices = profile->GetDevicesByStates(states);
94     vector<string> deviceVector;
95     for (auto &device: devices) {
96         deviceVector.push_back(device.GetDeviceAddr());
97     }
98     ConvertStringVectorToJS(env, ret, deviceVector);
99     return ret;
100 }
101 
GetDeviceState(napi_env env,napi_callback_info info)102 napi_value NapiAvrcpTarget::GetDeviceState(napi_env env, napi_callback_info info)
103 {
104     HILOGI("enter");
105     size_t expectedArgsCount = ARGS_SIZE_ONE;
106     size_t argc = expectedArgsCount;
107     napi_value argv[ARGS_SIZE_ONE] = {0};
108     napi_value thisVar = nullptr;
109 
110     napi_value ret = nullptr;
111     napi_get_undefined(env, &ret);
112 
113     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
114     if (argc != expectedArgsCount) {
115         HILOGE("Requires 1 argument.");
116         return ret;
117     }
118     string deviceId;
119     if (!ParseString(env, deviceId, argv[PARAM0])) {
120         HILOGE("string expected.");
121         return ret;
122     }
123 
124     AvrcpTarget *profile = AvrcpTarget::GetProfile();
125     BluetoothRemoteDevice device(deviceId, 1);
126     int state = profile->GetDeviceState(device);
127     napi_value result = nullptr;
128     int status = GetProfileConnectionState(state);
129     napi_create_int32(env, status, &result);
130     HILOGI("status: %{public}d", status);
131     return result;
132 }
133 
Connect(napi_env env,napi_callback_info info)134 napi_value NapiAvrcpTarget::Connect(napi_env env, napi_callback_info info)
135 {
136     HILOGI("enter");
137     size_t expectedArgsCount = ARGS_SIZE_ONE;
138     size_t argc = expectedArgsCount;
139     napi_value argv[ARGS_SIZE_ONE] = {0};
140     napi_value thisVar = nullptr;
141 
142     napi_value ret = nullptr;
143     napi_get_undefined(env, &ret);
144 
145     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
146     if (argc != expectedArgsCount) {
147         HILOGE("Requires 1 argument.");
148         return ret;
149     }
150     string deviceId;
151     if (!ParseString(env, deviceId, argv[PARAM0])) {
152         HILOGE("string expected.");
153         return ret;
154     }
155 
156     AvrcpTarget *profile = AvrcpTarget::GetProfile();
157     BluetoothRemoteDevice device(deviceId, 1);
158     bool res = profile->Connect(device);
159 
160     napi_value result = nullptr;
161     napi_get_boolean(env, res, &result);
162     HILOGI("res: %{public}d", res);
163     return result;
164 }
165 
Disconnect(napi_env env,napi_callback_info info)166 napi_value NapiAvrcpTarget::Disconnect(napi_env env, napi_callback_info info)
167 {
168     HILOGI("enter");
169     size_t expectedArgsCount = ARGS_SIZE_ONE;
170     size_t argc = expectedArgsCount;
171     napi_value argv[ARGS_SIZE_ONE] = {0};
172     napi_value thisVar = nullptr;
173 
174     napi_value ret = nullptr;
175     napi_get_undefined(env, &ret);
176 
177     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
178     if (argc != expectedArgsCount) {
179         HILOGE("Requires 1 argument.");
180         return ret;
181     }
182     string deviceId;
183     if (!ParseString(env, deviceId, argv[PARAM0])) {
184         HILOGE("string expected.");
185         return ret;
186     }
187 
188     AvrcpTarget *profile = AvrcpTarget::GetProfile();
189     BluetoothRemoteDevice device(deviceId, 1);
190     bool res = profile->Disconnect(device);
191 
192     napi_value result = nullptr;
193     napi_get_boolean(env, res, &result);
194     HILOGI("res: %{public}d", res);
195     return result;
196 }
197 
198 } // namespace Bluetooth
199 } // namespace OHOS
200