1 /*
2  * Copyright (C) 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 
16 #include "bluetooth_hid_host.h"
17 #include <unistd.h>
18 #include "bluetooth_device.h"
19 #include "bluetooth_host.h"
20 #include "bluetooth_profile_manager.h"
21 #include "bluetooth_log.h"
22 #include "bluetooth_observer_list.h"
23 #include "bluetooth_hid_host_observer_stub.h"
24 #include "bluetooth_utils.h"
25 #include "i_bluetooth_hid_host.h"
26 #include "i_bluetooth_host.h"
27 #include "iservice_registry.h"
28 #include "system_ability_definition.h"
29 
30 namespace OHOS {
31 namespace Bluetooth {
32 std::mutex g_hidProxyMutex;
33 class HidHostInnerObserver : public BluetoothHidHostObserverStub {
34 public:
HidHostInnerObserver(BluetoothObserverList<HidHostObserver> &observers)35     explicit HidHostInnerObserver(BluetoothObserverList<HidHostObserver> &observers) : observers_(observers)
36     {
37         HILOGD("Enter!");
38     }
39     ~HidHostInnerObserver() override
40     {
41         HILOGD("Enter!");
42     }
43 
44     ErrCode OnConnectionStateChanged(const BluetoothRawAddress &device, int32_t state, int32_t cause) override
45     {
46         HILOGD("hid conn state, device: %{public}s, state: %{public}s, cause: %{public}d",
47             GET_ENCRYPT_RAW_ADDR(device), GetProfileConnStateName(state).c_str(), cause);
48         BluetoothRemoteDevice remoteDevice(device.GetAddress(), 0);
49         observers_.ForEach([remoteDevice, state, cause](std::shared_ptr<HidHostObserver> observer) {
50             observer->OnConnectionStateChanged(remoteDevice, state, cause);
51         });
52         return NO_ERROR;
53     }
54 
55 private:
56     BluetoothObserverList<HidHostObserver> &observers_;
57     BLUETOOTH_DISALLOW_COPY_AND_ASSIGN(HidHostInnerObserver);
58 };
59 
60 struct HidHost::impl {
61     impl();
62     ~impl();
63 
GetDevicesByStatesOHOS::Bluetooth::HidHost::impl64     int32_t GetDevicesByStates(std::vector<int> states, std::vector<BluetoothRemoteDevice>& result)
65     {
66         HILOGI("Enter!");
67         std::vector<BluetoothRawAddress> rawDevices;
68         std::vector<int32_t> tmpStates;
69         for (int32_t state : states) {
70             tmpStates.push_back((int32_t)state);
71         }
72         sptr<IBluetoothHidHost> proxy = GetRemoteProxy<IBluetoothHidHost>(PROFILE_HID_HOST_SERVER);
73         CHECK_AND_RETURN_LOG_RET(proxy != nullptr, BT_ERR_SERVICE_DISCONNECTED, "failed: no proxy");
74         int32_t ret = proxy->GetDevicesByStates(tmpStates, rawDevices);
75         if (ret != BT_NO_ERROR) {
76             HILOGE("inner error.");
77             return ret;
78         }
79 
80         for (BluetoothRawAddress rawDevice : rawDevices) {
81             BluetoothRemoteDevice remoteDevice(rawDevice.GetAddress(), 1);
82             result.push_back(remoteDevice);
83         }
84 
85         return BT_NO_ERROR;
86     }
87 
GetDeviceStateOHOS::Bluetooth::HidHost::impl88     int32_t GetDeviceState(const BluetoothRemoteDevice &device, int32_t &state)
89     {
90         HILOGI("enter, device: %{public}s", GET_ENCRYPT_ADDR(device));
91         sptr<IBluetoothHidHost> proxy = GetRemoteProxy<IBluetoothHidHost>(PROFILE_HID_HOST_SERVER);
92         if (proxy == nullptr || !device.IsValidBluetoothRemoteDevice()) {
93             HILOGE("invalid param.");
94             return BT_ERR_INVALID_PARAM;
95         }
96 
97         return proxy->GetDeviceState(BluetoothRawAddress(device.GetDeviceAddr()), state);
98     }
99 
ConnectOHOS::Bluetooth::HidHost::impl100     int32_t Connect(const BluetoothRemoteDevice &device)
101     {
102         sptr<IBluetoothHidHost> proxy = GetRemoteProxy<IBluetoothHidHost>(PROFILE_HID_HOST_SERVER);
103         if (proxy == nullptr || !device.IsValidBluetoothRemoteDevice()) {
104             HILOGE("invalid param.");
105             return BT_ERR_INVALID_PARAM;
106         }
107         HILOGI("hid connect remote device: %{public}s", GET_ENCRYPT_ADDR(device));
108         return proxy->Connect(BluetoothRawAddress(device.GetDeviceAddr()));
109     }
110 
DisconnectOHOS::Bluetooth::HidHost::impl111     int32_t Disconnect(const BluetoothRemoteDevice &device)
112     {
113         HILOGI("hid disconnect remote device: %{public}s", GET_ENCRYPT_ADDR(device));
114         sptr<IBluetoothHidHost> proxy = GetRemoteProxy<IBluetoothHidHost>(PROFILE_HID_HOST_SERVER);
115         if (proxy == nullptr || !device.IsValidBluetoothRemoteDevice()) {
116             HILOGE("invalid param.");
117             return BT_ERR_INVALID_PARAM;
118         }
119 
120         return proxy->Disconnect(BluetoothRawAddress(device.GetDeviceAddr()));
121     }
122 
RegisterObserverOHOS::Bluetooth::HidHost::impl123     void RegisterObserver(std::shared_ptr<HidHostObserver> observer)
124     {
125         HILOGD("Enter!");
126         observers_.Register(observer);
127     }
128 
DeregisterObserverOHOS::Bluetooth::HidHost::impl129     void DeregisterObserver(std::shared_ptr<HidHostObserver> observer)
130     {
131         HILOGI("Enter!");
132         observers_.Deregister(observer);
133     }
134 
HidHostVCUnplugOHOS::Bluetooth::HidHost::impl135     void HidHostVCUnplug(std::string device, uint8_t id, uint16_t size, uint8_t type)
136     {
137         HILOGI("Enter!");
138         int result;
139         sptr<IBluetoothHidHost> proxy = GetRemoteProxy<IBluetoothHidHost>(PROFILE_HID_HOST_SERVER);
140         if (proxy != nullptr) {
141             proxy->HidHostVCUnplug(device, id, size, type, result);
142         }
143     }
144 
HidHostSendDataOHOS::Bluetooth::HidHost::impl145     void HidHostSendData(std::string device, uint8_t id, uint16_t size, uint8_t type)
146     {
147         HILOGI("Enter!");
148         int result;
149         sptr<IBluetoothHidHost> proxy = GetRemoteProxy<IBluetoothHidHost>(PROFILE_HID_HOST_SERVER);
150         if (proxy != nullptr) {
151             proxy->HidHostSendData(device, id, size, type, result);
152         }
153     }
154 
HidHostSetReportOHOS::Bluetooth::HidHost::impl155     void HidHostSetReport(std::string device, uint8_t type, std::string &report)
156     {
157         HILOGI("Enter!");
158         int result;
159         sptr<IBluetoothHidHost> proxy = GetRemoteProxy<IBluetoothHidHost>(PROFILE_HID_HOST_SERVER);
160         if (proxy != nullptr) {
161             proxy->HidHostSetReport(device, type, report, result);
162         }
163     }
164 
HidHostGetReportOHOS::Bluetooth::HidHost::impl165     void HidHostGetReport(std::string device, uint8_t id, uint16_t size, uint8_t type)
166     {
167         HILOGI("Enter!");
168         int result;
169         sptr<IBluetoothHidHost> proxy = GetRemoteProxy<IBluetoothHidHost>(PROFILE_HID_HOST_SERVER);
170         if (proxy != nullptr && IS_BT_ENABLED()) {
171             proxy->HidHostGetReport(device, id, size, type, result);
172         }
173     }
174 
SetConnectStrategyOHOS::Bluetooth::HidHost::impl175     int SetConnectStrategy(const BluetoothRemoteDevice &device, int strategy)
176     {
177         HILOGI("enter");
178         sptr<IBluetoothHidHost> proxy = GetRemoteProxy<IBluetoothHidHost>(PROFILE_HID_HOST_SERVER);
179         CHECK_AND_RETURN_LOG_RET(proxy != nullptr, BT_ERR_UNAVAILABLE_PROXY, "failed: no proxy");
180         return proxy->SetConnectStrategy(BluetoothRawAddress(device.GetDeviceAddr()), strategy);
181     }
182 
GetConnectStrategyOHOS::Bluetooth::HidHost::impl183     int GetConnectStrategy(const BluetoothRemoteDevice &device, int &strategy) const
184     {
185         HILOGI("enter");
186         sptr<IBluetoothHidHost> proxy = GetRemoteProxy<IBluetoothHidHost>(PROFILE_HID_HOST_SERVER);
187         CHECK_AND_RETURN_LOG_RET(proxy != nullptr, BT_ERR_UNAVAILABLE_PROXY, "failed: no proxy");
188         return proxy->GetConnectStrategy(BluetoothRawAddress(device.GetDeviceAddr()), strategy);
189     }
190 
191     int32_t profileRegisterId = 0;
192 private:
193     BluetoothObserverList<HidHostObserver> observers_;
194     sptr<HidHostInnerObserver> innerObserver_;
195 };
196 
impl()197 HidHost::impl::impl()
198 {
199     innerObserver_ = new HidHostInnerObserver(observers_);
200     profileRegisterId = BluetoothProfileManager::GetInstance().RegisterFunc(PROFILE_HID_HOST_SERVER,
201         [this](sptr<IRemoteObject> remote) {
202         sptr<IBluetoothHidHost> proxy = iface_cast<IBluetoothHidHost>(remote);
203         CHECK_AND_RETURN_LOG(proxy != nullptr, "failed: no proxy");
204         proxy->RegisterObserver(innerObserver_);
205     });
206 }
207 
~impl()208 HidHost::impl::~impl()
209 {
210     HILOGD("start");
211     BluetoothProfileManager::GetInstance().DeregisterFunc(profileRegisterId);
212     sptr<IBluetoothHidHost> proxy = GetRemoteProxy<IBluetoothHidHost>(PROFILE_HID_HOST_SERVER);
213     CHECK_AND_RETURN_LOG(proxy != nullptr, "failed: no proxy");
214     proxy->DeregisterObserver(innerObserver_);
215 }
216 
HidHost()217 HidHost::HidHost()
218 {
219     pimpl = std::make_unique<impl>();
220 }
221 
~HidHost()222 HidHost::~HidHost() {}
223 
GetProfile()224 HidHost *HidHost::GetProfile()
225 {
226 #ifdef DTFUZZ_TEST
227     static BluetoothNoDestructor<HidHost> instance;
228     return instance.get();
229 #else
230     static HidHost instance;
231     return &instance;
232 #endif
233 }
234 
GetDevicesByStates(std::vector<int> states, std::vector<BluetoothRemoteDevice> &result)235 int32_t HidHost::GetDevicesByStates(std::vector<int> states, std::vector<BluetoothRemoteDevice> &result)
236 {
237     if (!IS_BT_ENABLED()) {
238         HILOGE("bluetooth is off.");
239         return BT_ERR_INVALID_STATE;
240     }
241 
242     sptr<IBluetoothHidHost> proxy = GetRemoteProxy<IBluetoothHidHost>(PROFILE_HID_HOST_SERVER);
243     CHECK_AND_RETURN_LOG_RET(proxy != nullptr, BT_ERR_UNAVAILABLE_PROXY, "failed: no proxy");
244 
245     return pimpl->GetDevicesByStates(states, result);
246 }
247 
GetDeviceState(const BluetoothRemoteDevice &device, int32_t &state)248 int32_t HidHost::GetDeviceState(const BluetoothRemoteDevice &device, int32_t &state)
249 {
250     if (!IS_BT_ENABLED()) {
251         HILOGE("bluetooth is off.");
252         return BT_ERR_INVALID_STATE;
253     }
254 
255     sptr<IBluetoothHidHost> proxy = GetRemoteProxy<IBluetoothHidHost>(PROFILE_HID_HOST_SERVER);
256     CHECK_AND_RETURN_LOG_RET(proxy != nullptr, BT_ERR_UNAVAILABLE_PROXY, "failed: no proxy");
257 
258     return pimpl->GetDeviceState(device, state);
259 }
260 
Connect(const BluetoothRemoteDevice &device)261 int32_t HidHost::Connect(const BluetoothRemoteDevice &device)
262 {
263     if (!IS_BT_ENABLED()) {
264         HILOGE("bluetooth is off.");
265         return BT_ERR_INVALID_STATE;
266     }
267 
268     sptr<IBluetoothHidHost> proxy = GetRemoteProxy<IBluetoothHidHost>(PROFILE_HID_HOST_SERVER);
269     CHECK_AND_RETURN_LOG_RET(proxy != nullptr, BT_ERR_UNAVAILABLE_PROXY, "failed: no proxy");
270 
271     return pimpl->Connect(device);
272 }
273 
Disconnect(const BluetoothRemoteDevice &device)274 int32_t HidHost::Disconnect(const BluetoothRemoteDevice &device)
275 {
276     if (!IS_BT_ENABLED()) {
277         HILOGE("bluetooth is off.");
278         return BT_ERR_INVALID_STATE;
279     }
280 
281     sptr<IBluetoothHidHost> proxy = GetRemoteProxy<IBluetoothHidHost>(PROFILE_HID_HOST_SERVER);
282     CHECK_AND_RETURN_LOG_RET(proxy != nullptr, BT_ERR_UNAVAILABLE_PROXY, "failed: no proxy");
283 
284     return pimpl->Disconnect(device);
285 }
286 
SetConnectStrategy(const BluetoothRemoteDevice &device, int strategy)287 int HidHost::SetConnectStrategy(const BluetoothRemoteDevice &device, int strategy)
288 {
289     HILOGI("enter, device: %{public}s, strategy: %{public}d", GET_ENCRYPT_ADDR(device), strategy);
290     if (!IS_BT_ENABLED()) {
291         HILOGE("bluetooth is off.");
292         return BT_ERR_INVALID_STATE;
293     }
294 
295     sptr<IBluetoothHidHost> proxy = GetRemoteProxy<IBluetoothHidHost>(PROFILE_HID_HOST_SERVER);
296     CHECK_AND_RETURN_LOG_RET(proxy != nullptr, BT_ERR_UNAVAILABLE_PROXY, "failed: no proxy");
297 
298     if ((!device.IsValidBluetoothRemoteDevice()) || (
299         (strategy != static_cast<int>(BTStrategyType::CONNECTION_ALLOWED)) &&
300         (strategy != static_cast<int>(BTStrategyType::CONNECTION_FORBIDDEN)))) {
301         HILOGI("input parameter error.");
302         return BT_ERR_INVALID_PARAM;
303     }
304     return pimpl->SetConnectStrategy(device, strategy);
305 }
306 
GetConnectStrategy(const BluetoothRemoteDevice &device, int &strategy) const307 int HidHost::GetConnectStrategy(const BluetoothRemoteDevice &device, int &strategy) const
308 {
309     HILOGI("enter, device: %{public}s", GET_ENCRYPT_ADDR(device));
310     if (!IS_BT_ENABLED()) {
311         HILOGE("bluetooth is off.");
312         return BT_ERR_INVALID_STATE;
313     }
314 
315     sptr<IBluetoothHidHost> proxy = GetRemoteProxy<IBluetoothHidHost>(PROFILE_HID_HOST_SERVER);
316     CHECK_AND_RETURN_LOG_RET(proxy != nullptr, BT_ERR_UNAVAILABLE_PROXY, "failed: no proxy");
317 
318     if (!device.IsValidBluetoothRemoteDevice()) {
319         HILOGI("input parameter error.");
320         return BT_ERR_INVALID_PARAM;
321     }
322     return pimpl->GetConnectStrategy(device, strategy);
323 }
324 
RegisterObserver(std::shared_ptr<HidHostObserver> observer)325 void HidHost::RegisterObserver(std::shared_ptr<HidHostObserver> observer)
326 {
327     HILOGD("enter");
328     CHECK_AND_RETURN_LOG(pimpl != nullptr, "pimpl is null.");
329     pimpl->RegisterObserver(observer);
330 }
331 
DeregisterObserver(std::shared_ptr<HidHostObserver> observer)332 void HidHost::DeregisterObserver(std::shared_ptr<HidHostObserver> observer)
333 {
334     HILOGD("enter");
335     CHECK_AND_RETURN_LOG(pimpl != nullptr, "pimpl is null.");
336     pimpl->DeregisterObserver(observer);
337 }
338 
HidHostVCUnplug(std::string device, uint8_t id, uint16_t size, uint8_t type)339 void HidHost::HidHostVCUnplug(std::string device, uint8_t id, uint16_t size, uint8_t type)
340 {
341     if (!IS_BT_ENABLED()) {
342         HILOGE("bluetooth is off.");
343         return;
344     }
345     sptr<IBluetoothHidHost> proxy = GetRemoteProxy<IBluetoothHidHost>(PROFILE_HID_HOST_SERVER);
346     CHECK_AND_RETURN_LOG(proxy != nullptr, "failed: no proxy");
347 
348     return pimpl->HidHostVCUnplug(device, id, size, type);
349 }
350 
HidHostSendData(std::string device, uint8_t id, uint16_t size, uint8_t type)351 void HidHost::HidHostSendData(std::string device, uint8_t id, uint16_t size, uint8_t type)
352 {
353     if (!IS_BT_ENABLED()) {
354         HILOGE("bluetooth is off.");
355         return;
356     }
357     sptr<IBluetoothHidHost> proxy = GetRemoteProxy<IBluetoothHidHost>(PROFILE_HID_HOST_SERVER);
358     CHECK_AND_RETURN_LOG(proxy != nullptr, "failed: no proxy");
359 
360     return pimpl->HidHostSendData(device, id, size, type);
361 }
362 
HidHostSetReport(std::string device, uint8_t type, std::string &report)363 void HidHost::HidHostSetReport(std::string device, uint8_t type, std::string &report)
364 {
365     if (!IS_BT_ENABLED()) {
366         HILOGE("bluetooth is off.");
367         return;
368     }
369     sptr<IBluetoothHidHost> proxy = GetRemoteProxy<IBluetoothHidHost>(PROFILE_HID_HOST_SERVER);
370     CHECK_AND_RETURN_LOG(proxy != nullptr, "failed: no proxy");
371 
372     return pimpl->HidHostSetReport(device, type, report);
373 }
374 
HidHostGetReport(std::string device, uint8_t id, uint16_t size, uint8_t type)375 void HidHost::HidHostGetReport(std::string device, uint8_t id, uint16_t size, uint8_t type)
376 {
377     if (!IS_BT_ENABLED()) {
378         HILOGE("bluetooth is off.");
379         return;
380     }
381     sptr<IBluetoothHidHost> proxy = GetRemoteProxy<IBluetoothHidHost>(PROFILE_HID_HOST_SERVER);
382     CHECK_AND_RETURN_LOG(proxy != nullptr, "failed: no proxy");
383 
384     return pimpl->HidHostGetReport(device, id, size, type);
385 }
386 } // namespace Bluetooth
387 } // namespace OHOS