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_log.h"
21 #include "bluetooth_observer_list.h"
22 #include "bluetooth_hid_host_observer_stub.h"
23 #include "bluetooth_utils.h"
24 #include "i_bluetooth_hid_host.h"
25 #include "i_bluetooth_host.h"
26 #include "iservice_registry.h"
27 #include "system_ability_definition.h"
28
29 namespace OHOS {
30 namespace Bluetooth {
31 class HidHostInnerObserver : public BluetoothHidHostObserverStub {
32 public:
HidHostInnerObserver(BluetoothObserverList<HidHostObserver> & observers)33 explicit HidHostInnerObserver(BluetoothObserverList<HidHostObserver> &observers) : observers_(observers)
34 {
35 HILOGI("Enter!");
36 }
~HidHostInnerObserver()37 ~HidHostInnerObserver() override
38 {
39 HILOGI("Enter!");
40 }
41
OnConnectionStateChanged(const BluetoothRawAddress & device,int32_t state)42 ErrCode OnConnectionStateChanged(const BluetoothRawAddress &device, int32_t state) override
43 {
44 HILOGI("hid conn state, device: %{public}s, state: %{public}s",
45 GetEncryptAddr((device).GetAddress()).c_str(), GetProfileConnStateName(state).c_str());
46 BluetoothRemoteDevice remoteDevice(device.GetAddress(), 0);
47 observers_.ForEach([remoteDevice, state](std::shared_ptr<HidHostObserver> observer) {
48 observer->OnConnectionStateChanged(remoteDevice, state);
49 });
50 return NO_ERROR;
51 }
52
53 private:
54 BluetoothObserverList<HidHostObserver> &observers_;
55 BLUETOOTH_DISALLOW_COPY_AND_ASSIGN(HidHostInnerObserver);
56 };
57
58 struct HidHost::impl {
59 impl();
60 ~impl();
GetDevicesByStatesOHOS::Bluetooth::HidHost::impl61 int32_t GetDevicesByStates(std::vector<int> states, std::vector<BluetoothRemoteDevice>& result)
62 {
63 HILOGI("Enter!");
64 if (!proxy_) {
65 HILOGE("proxy_ is nullptr.");
66 return BT_ERR_SERVICE_DISCONNECTED;
67 }
68 if (!IS_BT_ENABLED()) {
69 HILOGE("bluetooth is off.");
70 return BT_ERR_INVALID_STATE;
71 }
72
73 std::vector<BluetoothRawAddress> rawDevices;
74 std::vector<int32_t> tmpStates;
75 for (int32_t state : states) {
76 tmpStates.push_back((int32_t)state);
77 }
78
79 int32_t ret = proxy_->GetDevicesByStates(tmpStates, rawDevices);
80 if (ret != BT_SUCCESS) {
81 HILOGE("inner error.");
82 return ret;
83 }
84
85 for (BluetoothRawAddress rawDevice : rawDevices) {
86 BluetoothRemoteDevice remoteDevice(rawDevice.GetAddress(), 1);
87 result.push_back(remoteDevice);
88 }
89
90 return BT_SUCCESS;
91 }
92
GetDeviceStateOHOS::Bluetooth::HidHost::impl93 int32_t GetDeviceState(const BluetoothRemoteDevice &device, int32_t &state)
94 {
95 HILOGI("enter, device: %{public}s", GET_ENCRYPT_ADDR(device));
96 if (proxy_ == nullptr || !device.IsValidBluetoothRemoteDevice()) {
97 HILOGE("invalid param.");
98 return BT_ERR_INVALID_PARAM;
99 }
100 if (!IS_BT_ENABLED()) {
101 HILOGE("bluetooth is off.");
102 return BT_ERR_INVALID_STATE;
103 }
104 return proxy_->GetDeviceState(BluetoothRawAddress(device.GetDeviceAddr()), state);
105 }
106
ConnectOHOS::Bluetooth::HidHost::impl107 int32_t Connect(const BluetoothRemoteDevice &device)
108 {
109 if (proxy_ == nullptr || !device.IsValidBluetoothRemoteDevice()) {
110 HILOGE("invalid param.");
111 return BT_ERR_INVALID_PARAM;
112 }
113 if (!IS_BT_ENABLED()) {
114 HILOGE("bluetooth is off.");
115 return BT_ERR_INVALID_STATE;
116 }
117
118 int cod = 0;
119 int32_t err = device.GetDeviceClass(cod);
120 if (err != BT_SUCCESS) {
121 HILOGE("GetDeviceClass Failed.");
122 return false;
123 }
124 BluetoothDeviceClass devClass = BluetoothDeviceClass(cod);
125 if (!devClass.IsProfileSupported(BluetoothDevice::PROFILE_HID)) {
126 HILOGE("hid connect failed. The remote device does not support HID service.");
127 return BT_ERR_PROFILE_DISABLED;
128 }
129 cod = devClass.GetClassOfDevice();
130 HILOGI("hid connect remote device: %{public}s, cod: %{public}d", GET_ENCRYPT_ADDR(device), cod);
131 return proxy_->Connect(BluetoothRawAddress(device.GetDeviceAddr()));
132 }
133
DisconnectOHOS::Bluetooth::HidHost::impl134 int32_t Disconnect(const BluetoothRemoteDevice &device)
135 {
136 HILOGI("hid disconnect remote device: %{public}s", GET_ENCRYPT_ADDR(device));
137 if (proxy_ == nullptr || !device.IsValidBluetoothRemoteDevice()) {
138 HILOGE("invalid param.");
139 return BT_ERR_INVALID_PARAM;
140 }
141 if (!IS_BT_ENABLED()) {
142 HILOGE("bluetooth is off.");
143 return BT_ERR_INVALID_STATE;
144 }
145 return proxy_->Disconnect(BluetoothRawAddress(device.GetDeviceAddr()));
146 }
147
RegisterObserverOHOS::Bluetooth::HidHost::impl148 void RegisterObserver(std::shared_ptr<HidHostObserver> observer)
149 {
150 HILOGI("Enter!");
151 observers_.Register(observer);
152 }
153
DeregisterObserverOHOS::Bluetooth::HidHost::impl154 void DeregisterObserver(std::shared_ptr<HidHostObserver> observer)
155 {
156 HILOGI("Enter!");
157 observers_.Deregister(observer);
158 }
159
HidHostVCUnplugOHOS::Bluetooth::HidHost::impl160 void HidHostVCUnplug(std::string device, uint8_t id, uint16_t size, uint8_t type)
161 {
162 HILOGI("Enter!");
163 int result;
164 if (proxy_ != nullptr && IS_BT_ENABLED()) {
165 proxy_->HidHostVCUnplug(device, id, size, type, result);
166 }
167 }
168
HidHostSendDataOHOS::Bluetooth::HidHost::impl169 void HidHostSendData(std::string device, uint8_t id, uint16_t size, uint8_t type)
170 {
171 HILOGI("Enter!");
172 int result;
173 if (proxy_ != nullptr && IS_BT_ENABLED()) {
174 proxy_->HidHostSendData(device, id, size, type, result);
175 }
176 }
177
HidHostSetReportOHOS::Bluetooth::HidHost::impl178 void HidHostSetReport(std::string device, uint8_t type, uint16_t size, uint8_t report)
179 {
180 HILOGI("Enter!");
181 int result;
182 if (proxy_ != nullptr && IS_BT_ENABLED()) {
183 proxy_->HidHostSetReport(device, type, size, report, result);
184 }
185 }
186
HidHostGetReportOHOS::Bluetooth::HidHost::impl187 void HidHostGetReport(std::string device, uint8_t id, uint16_t size, uint8_t type)
188 {
189 HILOGI("Enter!");
190 int result;
191 if (proxy_ != nullptr && IS_BT_ENABLED()) {
192 proxy_->HidHostGetReport(device, id, size, type, result);
193 }
194 }
195
196 private:
197 BluetoothObserverList<HidHostObserver> observers_;
198 sptr<HidHostInnerObserver> innerObserver_;
199 sptr<IBluetoothHidHost> proxy_;
200 class HidHostDeathRecipient;
201 sptr<HidHostDeathRecipient> deathRecipient_;
GetHidProxyOHOS::Bluetooth::HidHost::impl202 void GetHidProxy()
203 {
204 sptr<ISystemAbilityManager> samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
205 if (samgr == nullptr) {
206 HILOGE("error: no samgr");
207 return;
208 }
209 sptr<IRemoteObject> hostRemote = samgr->GetSystemAbility(BLUETOOTH_HOST_SYS_ABILITY_ID);
210 if (hostRemote == nullptr) {
211 HILOGE("failed: no hostRemote");
212 return;
213 }
214
215 sptr<IBluetoothHost> hostProxy = iface_cast<IBluetoothHost>(hostRemote);
216 if (hostProxy == nullptr) {
217 HILOGE("error: host no proxy");
218 return;
219 }
220
221 sptr<IRemoteObject> remote = hostProxy->GetProfile(PROFILE_HID_HOST_SERVER);
222 if (remote == nullptr) {
223 HILOGE("failed: no remote");
224 return;
225 }
226
227 proxy_ = iface_cast<IBluetoothHidHost>(remote);
228 if (proxy_ == nullptr) {
229 HILOGE("error: no proxy");
230 return;
231 }
232 }
233 };
234
235 class HidHost::impl::HidHostDeathRecipient final : public IRemoteObject::DeathRecipient {
236 public:
HidHostDeathRecipient(HidHost::impl & impl)237 HidHostDeathRecipient(HidHost::impl &impl) : impl_(impl)
238 {};
239 ~HidHostDeathRecipient() final = default;
240 BLUETOOTH_DISALLOW_COPY_AND_ASSIGN(HidHostDeathRecipient);
241
OnRemoteDied(const wptr<IRemoteObject> & remote)242 void OnRemoteDied(const wptr<IRemoteObject> &remote) final
243 {
244 HILOGI("starts");
245 impl_.proxy_->AsObject()->RemoveDeathRecipient(impl_.deathRecipient_);
246 impl_.proxy_ = nullptr;
247
248 // Re-obtain the proxy and register the observer.
249 sleep(GET_PROXY_SLEEP_SEC);
250 impl_.GetHidProxy();
251 if (impl_.proxy_ == nullptr) {
252 HILOGE("proxy reset failed");
253 return;
254 }
255 if (impl_.innerObserver_ == nullptr || impl_.deathRecipient_ == nullptr) {
256 HILOGE("innerObserver_ or deathRecipient_ is null");
257 return;
258 }
259 impl_.proxy_->RegisterObserver(impl_.innerObserver_);
260 impl_.proxy_->AsObject()->AddDeathRecipient(impl_.deathRecipient_);
261 }
262
263 private:
264 HidHost::impl &impl_;
265 };
266
impl()267 HidHost::impl::impl()
268 {
269 HILOGI("Enter!");
270 GetHidProxy();
271 if (proxy_ == nullptr) {
272 HILOGI("get proxy_ failed");
273 return;
274 }
275
276 innerObserver_ = new HidHostInnerObserver(observers_);
277 if (innerObserver_ == nullptr) {
278 HILOGE("innerObserver_ is null");
279 return;
280 }
281 proxy_->RegisterObserver(innerObserver_);
282
283 deathRecipient_ = new HidHostDeathRecipient(*this);
284 if (deathRecipient_ == nullptr) {
285 HILOGE("deathRecipient_ is null");
286 return;
287 }
288 proxy_->AsObject()->AddDeathRecipient(deathRecipient_);
289 }
290
~impl()291 HidHost::impl::~impl()
292 {
293 HILOGI("Enter!");
294 if (proxy_ != nullptr) {
295 proxy_->DeregisterObserver(innerObserver_);
296 }
297 proxy_->AsObject()->RemoveDeathRecipient(deathRecipient_);
298 }
299
HidHost()300 HidHost::HidHost()
301 {
302 pimpl = std::make_unique<impl>();
303 }
304
~HidHost()305 HidHost::~HidHost()
306 {}
307
GetProfile()308 HidHost *HidHost::GetProfile()
309 {
310 static HidHost instance;
311 return &instance;
312 }
313
GetDevicesByStates(std::vector<int> states,std::vector<BluetoothRemoteDevice> & result)314 int32_t HidHost::GetDevicesByStates(std::vector<int> states, std::vector<BluetoothRemoteDevice> &result)
315 {
316 return pimpl->GetDevicesByStates(states, result);
317 }
318
GetDeviceState(const BluetoothRemoteDevice & device,int32_t & state)319 int32_t HidHost::GetDeviceState(const BluetoothRemoteDevice &device, int32_t &state)
320 {
321 return pimpl->GetDeviceState(device, state);
322 }
323
Connect(const BluetoothRemoteDevice & device)324 int32_t HidHost::Connect(const BluetoothRemoteDevice &device)
325 {
326 return pimpl->Connect(device);
327 }
328
Disconnect(const BluetoothRemoteDevice & device)329 int32_t HidHost::Disconnect(const BluetoothRemoteDevice &device)
330 {
331 return pimpl->Disconnect(device);
332 }
333
RegisterObserver(HidHostObserver * observer)334 void HidHost::RegisterObserver(HidHostObserver *observer)
335 {
336 std::shared_ptr<HidHostObserver> observerPtr(observer, [](HidHostObserver *) {});
337 return pimpl->RegisterObserver(observerPtr);
338 }
339
DeregisterObserver(HidHostObserver * observer)340 void HidHost::DeregisterObserver(HidHostObserver *observer)
341 {
342 std::shared_ptr<HidHostObserver> observerPtr(observer, [](HidHostObserver *) {});
343 return pimpl->DeregisterObserver(observerPtr);
344 }
345
HidHostVCUnplug(std::string device,uint8_t id,uint16_t size,uint8_t type)346 void HidHost::HidHostVCUnplug(std::string device, uint8_t id, uint16_t size, uint8_t type)
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 return pimpl->HidHostSendData(device, id, size, type);
354 }
355
HidHostSetReport(std::string device,uint8_t type,uint16_t size,uint8_t report)356 void HidHost::HidHostSetReport(std::string device, uint8_t type, uint16_t size, uint8_t report)
357 {
358 return pimpl->HidHostSetReport(device, type, size, report);
359 }
360
HidHostGetReport(std::string device,uint8_t id,uint16_t size,uint8_t type)361 void HidHost::HidHostGetReport(std::string device, uint8_t id, uint16_t size, uint8_t type)
362 {
363 return pimpl->HidHostGetReport(device, id, size, type);
364 }
365 } // namespace Bluetooth
366 } // namespace OHOS