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