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_load_system_ability.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 HILOGI("Enter!");
38 }
~HidHostInnerObserver()39 ~HidHostInnerObserver() override
40 {
41 HILOGI("Enter!");
42 }
43
OnConnectionStateChanged(const BluetoothRawAddress & device,int32_t state)44 ErrCode OnConnectionStateChanged(const BluetoothRawAddress &device, int32_t state) override
45 {
46 HILOGD("hid conn state, device: %{public}s, state: %{public}s",
47 GetEncryptAddr((device).GetAddress()).c_str(), GetProfileConnStateName(state).c_str());
48 BluetoothRemoteDevice remoteDevice(device.GetAddress(), 0);
49 observers_.ForEach([remoteDevice, state](std::shared_ptr<HidHostObserver> observer) {
50 observer->OnConnectionStateChanged(remoteDevice, state);
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 bool InitHidHostProxy(void);
64
GetDevicesByStatesOHOS::Bluetooth::HidHost::impl65 int32_t GetDevicesByStates(std::vector<int> states, std::vector<BluetoothRemoteDevice>& result)
66 {
67 HILOGI("Enter!");
68 std::vector<BluetoothRawAddress> rawDevices;
69 std::vector<int32_t> tmpStates;
70 for (int32_t state : states) {
71 tmpStates.push_back((int32_t)state);
72 }
73
74 if (!proxy_) {
75 HILOGE("proxy_ is nullptr.");
76 return BT_ERR_SERVICE_DISCONNECTED;
77 }
78 int32_t ret = proxy_->GetDevicesByStates(tmpStates, rawDevices);
79 if (ret != BT_NO_ERROR) {
80 HILOGE("inner error.");
81 return ret;
82 }
83
84 for (BluetoothRawAddress rawDevice : rawDevices) {
85 BluetoothRemoteDevice remoteDevice(rawDevice.GetAddress(), 1);
86 result.push_back(remoteDevice);
87 }
88
89 return BT_NO_ERROR;
90 }
91
GetDeviceStateOHOS::Bluetooth::HidHost::impl92 int32_t GetDeviceState(const BluetoothRemoteDevice &device, int32_t &state)
93 {
94 HILOGI("enter, device: %{public}s", GET_ENCRYPT_ADDR(device));
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 if (proxy_ == nullptr || !device.IsValidBluetoothRemoteDevice()) {
106 HILOGE("invalid param.");
107 return BT_ERR_INVALID_PARAM;
108 }
109
110 int cod = 0;
111 int32_t err = device.GetDeviceClass(cod);
112 if (err != BT_NO_ERROR) {
113 HILOGE("GetDeviceClass Failed.");
114 return false;
115 }
116 BluetoothDeviceClass devClass = BluetoothDeviceClass(cod);
117 if (!devClass.IsProfileSupported(BluetoothDevice::PROFILE_HID)) {
118 HILOGE("hid connect failed. The remote device does not support HID service.");
119 return BT_ERR_PROFILE_DISABLED;
120 }
121 cod = devClass.GetClassOfDevice();
122 HILOGI("hid connect remote device: %{public}s, cod: %{public}d", GET_ENCRYPT_ADDR(device), cod);
123 return proxy_->Connect(BluetoothRawAddress(device.GetDeviceAddr()));
124 }
125
DisconnectOHOS::Bluetooth::HidHost::impl126 int32_t Disconnect(const BluetoothRemoteDevice &device)
127 {
128 HILOGI("hid disconnect remote device: %{public}s", GET_ENCRYPT_ADDR(device));
129 if (proxy_ == nullptr || !device.IsValidBluetoothRemoteDevice()) {
130 HILOGE("invalid param.");
131 return BT_ERR_INVALID_PARAM;
132 }
133
134 return proxy_->Disconnect(BluetoothRawAddress(device.GetDeviceAddr()));
135 }
136
RegisterObserverOHOS::Bluetooth::HidHost::impl137 void RegisterObserver(std::shared_ptr<HidHostObserver> observer)
138 {
139 HILOGI("Enter!");
140 observers_.Register(observer);
141 }
142
DeregisterObserverOHOS::Bluetooth::HidHost::impl143 void DeregisterObserver(std::shared_ptr<HidHostObserver> observer)
144 {
145 HILOGI("Enter!");
146 observers_.Deregister(observer);
147 }
148
HidHostVCUnplugOHOS::Bluetooth::HidHost::impl149 void HidHostVCUnplug(std::string device, uint8_t id, uint16_t size, uint8_t type)
150 {
151 HILOGI("Enter!");
152 int result;
153 if (proxy_ != nullptr) {
154 proxy_->HidHostVCUnplug(device, id, size, type, result);
155 }
156 }
157
HidHostSendDataOHOS::Bluetooth::HidHost::impl158 void HidHostSendData(std::string device, uint8_t id, uint16_t size, uint8_t type)
159 {
160 HILOGI("Enter!");
161 int result;
162 if (proxy_ != nullptr) {
163 proxy_->HidHostSendData(device, id, size, type, result);
164 }
165 }
166
HidHostSetReportOHOS::Bluetooth::HidHost::impl167 void HidHostSetReport(std::string device, uint8_t type, uint16_t size, uint8_t report)
168 {
169 HILOGI("Enter!");
170 int result;
171 if (proxy_ != nullptr) {
172 proxy_->HidHostSetReport(device, type, size, report, result);
173 }
174 }
175
HidHostGetReportOHOS::Bluetooth::HidHost::impl176 void HidHostGetReport(std::string device, uint8_t id, uint16_t size, uint8_t type)
177 {
178 HILOGI("Enter!");
179 int result;
180 if (proxy_ != nullptr && IS_BT_ENABLED()) {
181 proxy_->HidHostGetReport(device, id, size, type, result);
182 }
183 }
184
SetConnectStrategyOHOS::Bluetooth::HidHost::impl185 int SetConnectStrategy(const BluetoothRemoteDevice &device, int strategy)
186 {
187 HILOGI("enter");
188 return proxy_->SetConnectStrategy(BluetoothRawAddress(device.GetDeviceAddr()), strategy);
189 }
190
GetConnectStrategyOHOS::Bluetooth::HidHost::impl191 int GetConnectStrategy(const BluetoothRemoteDevice &device, int &strategy) const
192 {
193 HILOGI("enter");
194 return proxy_->GetConnectStrategy(BluetoothRawAddress(device.GetDeviceAddr()), strategy);
195 }
196
197 sptr<IBluetoothHidHost> proxy_;
198 private:
199 BluetoothObserverList<HidHostObserver> observers_;
200 sptr<HidHostInnerObserver> innerObserver_;
201 class HidHostDeathRecipient;
202 sptr<HidHostDeathRecipient> deathRecipient_;
203 };
204
205 class HidHost::impl::HidHostDeathRecipient final : public IRemoteObject::DeathRecipient {
206 public:
HidHostDeathRecipient(HidHost::impl & impl)207 explicit HidHostDeathRecipient(HidHost::impl &impl) : impl_(impl)
208 {};
209 ~HidHostDeathRecipient() final = default;
210 BLUETOOTH_DISALLOW_COPY_AND_ASSIGN(HidHostDeathRecipient);
211
OnRemoteDied(const wptr<IRemoteObject> & remote)212 void OnRemoteDied(const wptr<IRemoteObject> &remote) final
213 {
214 HILOGI("starts");
215 std::lock_guard<std::mutex> lock(g_hidProxyMutex);
216 if (!impl_.proxy_) {
217 return;
218 }
219 impl_.proxy_ = nullptr;
220 }
221
222 private:
223 HidHost::impl &impl_;
224 };
225
impl()226 HidHost::impl::impl()
227 {
228 if (proxy_) {
229 return;
230 }
231 BluetootLoadSystemAbility::GetInstance().RegisterNotifyMsg(PROFILE_ID_HID_HOST_SERVER);
232 if (!BluetootLoadSystemAbility::GetInstance().HasSubscribedBluetoothSystemAbility()) {
233 BluetootLoadSystemAbility::GetInstance().SubScribeBluetoothSystemAbility();
234 return;
235 }
236 InitHidHostProxy();
237 }
238
~impl()239 HidHost::impl::~impl()
240 {
241 HILOGI("Enter!");
242 if (proxy_ != nullptr) {
243 proxy_->DeregisterObserver(innerObserver_);
244 proxy_->AsObject()->RemoveDeathRecipient(deathRecipient_);
245 }
246 }
247
InitHidHostProxy(void)248 bool HidHost::impl::InitHidHostProxy(void)
249 {
250 HILOGI("enter");
251 std::lock_guard<std::mutex> lock(g_hidProxyMutex);
252 if (proxy_) {
253 return true;
254 }
255 proxy_ = GetRemoteProxy<IBluetoothHidHost>(PROFILE_HID_HOST_SERVER);
256 if (!proxy_) {
257 HILOGE("get HidHost proxy fail");
258 return false;
259 }
260
261 innerObserver_ = new HidHostInnerObserver(observers_);
262 if (innerObserver_ != nullptr) {
263 proxy_->RegisterObserver(innerObserver_);
264 }
265
266 deathRecipient_ = new HidHostDeathRecipient(*this);
267 if (deathRecipient_ != nullptr) {
268 proxy_->AsObject()->AddDeathRecipient(deathRecipient_);
269 }
270 return true;
271 }
272
HidHost()273 HidHost::HidHost()
274 {
275 pimpl = std::make_unique<impl>();
276 }
277
~HidHost()278 HidHost::~HidHost() {}
279
Init()280 void HidHost::Init()
281 {
282 if (!pimpl) {
283 HILOGE("fails: no pimpl");
284 return;
285 }
286 if (!pimpl->InitHidHostProxy()) {
287 HILOGE("HidHost proxy is nullptr");
288 return;
289 }
290 }
291
GetProfile()292 HidHost *HidHost::GetProfile()
293 {
294 static HidHost instance;
295 return &instance;
296 }
297
GetDevicesByStates(std::vector<int> states,std::vector<BluetoothRemoteDevice> & result)298 int32_t HidHost::GetDevicesByStates(std::vector<int> states, std::vector<BluetoothRemoteDevice> &result)
299 {
300 if (!IS_BT_ENABLED()) {
301 HILOGE("bluetooth is off.");
302 return BT_ERR_INVALID_STATE;
303 }
304
305 if (pimpl == nullptr || !pimpl->proxy_) {
306 HILOGE("pimpl or hidHost proxy is nullptr");
307 return BT_ERR_UNAVAILABLE_PROXY;
308 }
309
310 return pimpl->GetDevicesByStates(states, result);
311 }
312
GetDeviceState(const BluetoothRemoteDevice & device,int32_t & state)313 int32_t HidHost::GetDeviceState(const BluetoothRemoteDevice &device, int32_t &state)
314 {
315 if (!IS_BT_ENABLED()) {
316 HILOGE("bluetooth is off.");
317 return BT_ERR_INVALID_STATE;
318 }
319
320 if (pimpl == nullptr || !pimpl->proxy_) {
321 HILOGE("pimpl or hidHost proxy is nullptr");
322 return BT_ERR_UNAVAILABLE_PROXY;
323 }
324
325 return pimpl->GetDeviceState(device, state);
326 }
327
Connect(const BluetoothRemoteDevice & device)328 int32_t HidHost::Connect(const BluetoothRemoteDevice &device)
329 {
330 if (!IS_BT_ENABLED()) {
331 HILOGE("bluetooth is off.");
332 return BT_ERR_INVALID_STATE;
333 }
334
335 if (pimpl == nullptr || !pimpl->proxy_) {
336 HILOGE("pimpl or hidHost proxy is nullptr");
337 return BT_ERR_UNAVAILABLE_PROXY;
338 }
339
340 return pimpl->Connect(device);
341 }
342
Disconnect(const BluetoothRemoteDevice & device)343 int32_t HidHost::Disconnect(const BluetoothRemoteDevice &device)
344 {
345 if (!IS_BT_ENABLED()) {
346 HILOGE("bluetooth is off.");
347 return BT_ERR_INVALID_STATE;
348 }
349
350 if (pimpl == nullptr || !pimpl->proxy_) {
351 HILOGE("pimpl or hidHost proxy is nullptr");
352 return BT_ERR_UNAVAILABLE_PROXY;
353 }
354
355 return pimpl->Disconnect(device);
356 }
357
SetConnectStrategy(const BluetoothRemoteDevice & device,int strategy)358 int HidHost::SetConnectStrategy(const BluetoothRemoteDevice &device, int strategy)
359 {
360 HILOGI("enter, device: %{public}s, strategy: %{public}d", GET_ENCRYPT_ADDR(device), strategy);
361 if (!IS_BT_ENABLED()) {
362 HILOGE("bluetooth is off.");
363 return BT_ERR_INVALID_STATE;
364 }
365
366 if (pimpl == nullptr || !pimpl->proxy_) {
367 HILOGE("pimpl or hidHost proxy is nullptr");
368 return BT_ERR_UNAVAILABLE_PROXY;
369 }
370
371 if ((!device.IsValidBluetoothRemoteDevice()) || (
372 (strategy != static_cast<int>(BTStrategyType::CONNECTION_ALLOWED)) &&
373 (strategy != static_cast<int>(BTStrategyType::CONNECTION_FORBIDDEN)))) {
374 HILOGI("input parameter error.");
375 return BT_ERR_INVALID_PARAM;
376 }
377 return pimpl->SetConnectStrategy(device, strategy);
378 }
379
GetConnectStrategy(const BluetoothRemoteDevice & device,int & strategy) const380 int HidHost::GetConnectStrategy(const BluetoothRemoteDevice &device, int &strategy) const
381 {
382 HILOGI("enter, device: %{public}s", GET_ENCRYPT_ADDR(device));
383 if (!IS_BT_ENABLED()) {
384 HILOGE("bluetooth is off.");
385 return BT_ERR_INVALID_STATE;
386 }
387
388 if (pimpl == nullptr || !pimpl->proxy_) {
389 HILOGE("pimpl or hidHost proxy is nullptr");
390 return BT_ERR_UNAVAILABLE_PROXY;
391 }
392
393 if (!device.IsValidBluetoothRemoteDevice()) {
394 HILOGI("input parameter error.");
395 return BT_ERR_INVALID_PARAM;
396 }
397 return pimpl->GetConnectStrategy(device, strategy);
398 }
399
RegisterObserver(HidHostObserver * observer)400 void HidHost::RegisterObserver(HidHostObserver *observer)
401 {
402 std::shared_ptr<HidHostObserver> observerPtr(observer, [](HidHostObserver *) {});
403 return pimpl->RegisterObserver(observerPtr);
404 }
405
DeregisterObserver(HidHostObserver * observer)406 void HidHost::DeregisterObserver(HidHostObserver *observer)
407 {
408 std::shared_ptr<HidHostObserver> observerPtr(observer, [](HidHostObserver *) {});
409 return pimpl->DeregisterObserver(observerPtr);
410 }
411
HidHostVCUnplug(std::string device,uint8_t id,uint16_t size,uint8_t type)412 void HidHost::HidHostVCUnplug(std::string device, uint8_t id, uint16_t size, uint8_t type)
413 {
414 if (!IS_BT_ENABLED()) {
415 HILOGE("bluetooth is off.");
416 return;
417 }
418
419 if (pimpl == nullptr || !pimpl->proxy_) {
420 HILOGE("pimpl or hidHost proxy is nullptr");
421 return;
422 }
423
424 return pimpl->HidHostVCUnplug(device, id, size, type);
425 }
426
HidHostSendData(std::string device,uint8_t id,uint16_t size,uint8_t type)427 void HidHost::HidHostSendData(std::string device, uint8_t id, uint16_t size, uint8_t type)
428 {
429 if (!IS_BT_ENABLED()) {
430 HILOGE("bluetooth is off.");
431 return;
432 }
433
434 if (pimpl == nullptr || !pimpl->proxy_) {
435 HILOGE("pimpl or hidHost proxy is nullptr");
436 return;
437 }
438
439 return pimpl->HidHostSendData(device, id, size, type);
440 }
441
HidHostSetReport(std::string device,uint8_t type,uint16_t size,uint8_t report)442 void HidHost::HidHostSetReport(std::string device, uint8_t type, uint16_t size, uint8_t report)
443 {
444 if (!IS_BT_ENABLED()) {
445 HILOGE("bluetooth is off.");
446 return;
447 }
448
449 if (pimpl == nullptr || !pimpl->proxy_) {
450 HILOGE("pimpl or hidHost proxy is nullptr");
451 return;
452 }
453
454 return pimpl->HidHostSetReport(device, type, size, report);
455 }
456
HidHostGetReport(std::string device,uint8_t id,uint16_t size,uint8_t type)457 void HidHost::HidHostGetReport(std::string device, uint8_t id, uint16_t size, uint8_t type)
458 {
459 if (!IS_BT_ENABLED()) {
460 HILOGE("bluetooth is off.");
461 return;
462 }
463
464 if (pimpl == nullptr || !pimpl->proxy_) {
465 HILOGE("pimpl or hidHost proxy is nullptr");
466 return;
467 }
468
469 return pimpl->HidHostGetReport(device, id, size, type);
470 }
471 } // namespace Bluetooth
472 } // namespace OHOS