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
16 #include <condition_variable>
17 #include <memory>
18 #include <set>
19
20 #include "bluetooth_def.h"
21 #include "bluetooth_gatt_client.h"
22 #include "bluetooth_gatt_client_proxy.h"
23 #include "bluetooth_gatt_client_callback_stub.h"
24 #include "bluetooth_host.h"
25 #include "bluetooth_host_proxy.h"
26 #include "bluetooth_log.h"
27 #include "bluetooth_utils.h"
28 #include "gatt_data.h"
29 #include "i_bluetooth_gatt_client.h"
30 #include "iservice_registry.h"
31 #include "raw_address.h"
32 #include "system_ability_definition.h"
33 #include "bluetooth_profile_manager.h"
34
35 namespace OHOS {
36 namespace Bluetooth {
37 #define WPTR_GATT_CBACK(cbWptr, func, ...) \
38 do { \
39 auto cbSptr = (cbWptr).lock(); \
40 if (cbSptr) { \
41 cbSptr->func(__VA_ARGS__); \
42 } else { \
43 HILOGE(#cbWptr ": callback is nullptr"); \
44 } \
45 } while (0)
46
47 constexpr uint8_t REQUEST_TYPE_CHARACTERISTICS_READ = 0x00;
48 constexpr uint8_t REQUEST_TYPE_CHARACTERISTICS_WRITE = 0x01;
49 constexpr uint8_t REQUEST_TYPE_DESCRIPTOR_READ = 0x02;
50 constexpr uint8_t REQUEST_TYPE_DESCRIPTOR_WRITE = 0x03;
51 constexpr uint8_t REQUEST_TYPE_SET_NOTIFY_CHARACTERISTICS = 0x04;
52 constexpr uint8_t REQUEST_TYPE_READ_REMOTE_RSSI_VALUE = 0x05;
53
54 constexpr const int WAIT_TIMEOUT = 10; // 10s
55 std::mutex g_gattClientProxyMutex;
56 struct DiscoverInfomation {
57 struct Characteristics {
58 bool isDiscoverDescCompleted_;
CharacteristicsOHOS::Bluetooth::DiscoverInfomation::Characteristics59 Characteristics() : isDiscoverDescCompleted_(false)
60 {}
61 };
62
63 struct Service {
64 bool isDiscoverCompleted_;
65 bool isDiscoverCharacteristicCompleted_;
66 bool isDiscoverIncludeSvcCompleted_;
67 uint16_t endHandle_;
68 std::map<uint16_t, Characteristics> characteristics_;
ServiceOHOS::Bluetooth::DiscoverInfomation::Service69 Service(uint16_t endHandle)
70 : isDiscoverCompleted_(false),
71 isDiscoverCharacteristicCompleted_(false),
72 isDiscoverIncludeSvcCompleted_(false),
73 endHandle_(endHandle)
74 {}
75 };
76 bool isDiscovering_;
77 bool needNotify_;
78 std::mutex mutex_;
79 std::condition_variable condition_;
80 std::map<uint16_t, Service> service_;
DiscoverInfomationOHOS::Bluetooth::DiscoverInfomation81 DiscoverInfomation() : isDiscovering_(false), needNotify_(false)
82 {}
83 };
84
85 struct RequestInformation {
86 bool doing_;
87 uint8_t type_ = 0;
88 union {
89 GattCharacteristic *characteristic_;
90 GattDescriptor *descriptor_;
91 } context_;
92 std::mutex mutex_;
RequestInformationOHOS::Bluetooth::RequestInformation93 RequestInformation() : doing_(false)
94 {}
95 };
96
97 struct GattClient::impl {
98 class BluetoothGattClientCallbackStubImpl;
99
100 bool isGetServiceYet_;
101 bool isRegisterSucceeded_;
102 std::weak_ptr<GattClientCallback> callback_;
103 int applicationId_;
104 int connectionState_;
105 BluetoothRemoteDevice device_;
106 sptr<IBluetoothGattClient> proxy;
107 sptr<BluetoothGattClientCallbackStubImpl> clientCallback_;
108 std::vector<GattService> gattServices_;
109 std::mutex connStateMutex_;
110 RequestInformation requestInformation_;
111 DiscoverInfomation discoverInformation_;
112
113 explicit impl(const BluetoothRemoteDevice &device);
114 ~impl();
115
116 bool Init(std::weak_ptr<GattClient> client);
117
118 int DiscoverStart();
119 void DiscoverComplete(int state);
120 void BuildServiceList(const std::vector<BluetoothGattService> &src);
121 GattService *FindService(uint16_t handle);
122 void GetServices();
123 void CleanConnectionInfo();
124 };
125
126 class GattClient::impl::BluetoothGattClientCallbackStubImpl : public BluetoothGattClientCallbackStub {
127 public:
OnServicesChanged(std::vector<BluetoothGattService> & service)128 void OnServicesChanged(std::vector<BluetoothGattService> &service) override
129 {
130 HILOGI("enter");
131 std::shared_ptr<GattClient> clientSptr = (client_).lock();
132 if (!clientSptr) {
133 HILOGE("callback client is nullptr");
134 return;
135 }
136 clientSptr->pimpl->DiscoverStart();
137 }
138
OnConnectionStateChanged(int32_t state,int32_t newState)139 void OnConnectionStateChanged(int32_t state, int32_t newState) override
140 {
141 HILOGD("gattClient conn state, status: %{public}d, newState: %{public}s",
142 state, GetProfileConnStateName(newState).c_str());
143 std::shared_ptr<GattClient> clientSptr = (client_).lock();
144 if (!clientSptr) {
145 HILOGE("callback client is nullptr");
146 return;
147 }
148 if (newState == static_cast<int>(BTConnectState::DISCONNECTED)) {
149 clientSptr->pimpl->CleanConnectionInfo();
150 }
151
152 {
153 std::lock_guard<std::mutex> lck(clientSptr->pimpl->connStateMutex_);
154 clientSptr->pimpl->connectionState_ = newState;
155 }
156 WPTR_GATT_CBACK(clientSptr->pimpl->callback_, OnConnectionStateChanged, newState, state);
157 }
158
OnCharacteristicChanged(const BluetoothGattCharacteristic & characteristic)159 void OnCharacteristicChanged(const BluetoothGattCharacteristic &characteristic) override
160 {
161 HILOGD("recv notification, length:%{public}zu", characteristic.length_);
162 std::shared_ptr<GattClient> clientSptr = (client_).lock();
163 if (!clientSptr) {
164 HILOGE("callback client is nullptr");
165 return;
166 }
167 for (auto &svc : clientSptr->pimpl->gattServices_) {
168 for (auto &character : svc.GetCharacteristics()) {
169 if (character.GetHandle() == characteristic.handle_) {
170 character.SetValue(characteristic.value_.get(), characteristic.length_);
171 WPTR_GATT_CBACK(clientSptr->pimpl->callback_, OnCharacteristicChanged, character);
172 return;
173 }
174 }
175 }
176 HILOGE("recv notification failed, characteristic is not exist.");
177 }
178
OnCharacteristicRead(int32_t ret,const BluetoothGattCharacteristic & characteristic)179 void OnCharacteristicRead(int32_t ret, const BluetoothGattCharacteristic &characteristic) override
180 {
181 HILOGI("ret:%{public}d, length:%{public}zu", ret, characteristic.length_);
182 std::shared_ptr<GattClient> clientSptr = (client_).lock();
183 if (!clientSptr) {
184 HILOGE("callback client is nullptr");
185 return;
186 }
187 std::lock_guard<std::mutex> lock(clientSptr->pimpl->requestInformation_.mutex_);
188 clientSptr->pimpl->requestInformation_.doing_ = false;
189 auto ptr = clientSptr->pimpl->requestInformation_.context_.characteristic_;
190 if (clientSptr->pimpl->requestInformation_.type_ != REQUEST_TYPE_CHARACTERISTICS_READ) {
191 HILOGE("Unexpected call!");
192 }
193 if (ret == GattStatus::GATT_SUCCESS) {
194 ptr->SetValue(characteristic.value_.get(), characteristic.length_);
195 }
196 WPTR_GATT_CBACK(clientSptr->pimpl->callback_, OnCharacteristicReadResult, *ptr, ret);
197 }
198
OnCharacteristicWrite(int32_t ret,const BluetoothGattCharacteristic & characteristic)199 void OnCharacteristicWrite(int32_t ret, const BluetoothGattCharacteristic &characteristic) override
200 {
201 HILOGI("ret:%{public}d, length:%{public}zu", ret, characteristic.length_);
202 std::shared_ptr<GattClient> clientSptr = (client_).lock();
203 if (!clientSptr) {
204 HILOGE("callback client is nullptr");
205 return;
206 }
207 std::lock_guard<std::mutex> lock(clientSptr->pimpl->requestInformation_.mutex_);
208 clientSptr->pimpl->requestInformation_.doing_ = false;
209 auto ptr = clientSptr->pimpl->requestInformation_.context_.characteristic_;
210 if (clientSptr->pimpl->requestInformation_.type_ != REQUEST_TYPE_CHARACTERISTICS_WRITE) {
211 HILOGE("Unexpected call!");
212 }
213 WPTR_GATT_CBACK(clientSptr->pimpl->callback_, OnCharacteristicWriteResult, *ptr, ret);
214 }
215
OnDescriptorRead(int32_t ret,const BluetoothGattDescriptor & descriptor)216 void OnDescriptorRead(int32_t ret, const BluetoothGattDescriptor &descriptor) override
217 {
218 HILOGI("ret:%{public}d, length:%{public}zu", ret, descriptor.length_);
219 std::shared_ptr<GattClient> clientSptr = (client_).lock();
220 if (!clientSptr) {
221 HILOGE("callback client is nullptr");
222 return;
223 }
224 std::lock_guard<std::mutex> lock(clientSptr->pimpl->requestInformation_.mutex_);
225 clientSptr->pimpl->requestInformation_.doing_ = false;
226 auto ptr = clientSptr->pimpl->requestInformation_.context_.descriptor_;
227 if (clientSptr->pimpl->requestInformation_.type_ != REQUEST_TYPE_DESCRIPTOR_READ) {
228 HILOGE("Unexpected call!");
229 }
230 if (ret == GattStatus::GATT_SUCCESS) {
231 ptr->SetValue(descriptor.value_.get(), descriptor.length_);
232 }
233 WPTR_GATT_CBACK(clientSptr->pimpl->callback_, OnDescriptorReadResult, *ptr, ret);
234 }
235
OnDescriptorWrite(int32_t ret,const BluetoothGattDescriptor & descriptor)236 void OnDescriptorWrite(int32_t ret, const BluetoothGattDescriptor &descriptor) override
237 {
238 HILOGI("ret:%{public}d, length:%{public}zu", ret, descriptor.length_);
239 std::shared_ptr<GattClient> clientSptr = (client_).lock();
240 if (!clientSptr) {
241 HILOGE("callback client is nullptr");
242 return;
243 }
244 std::lock_guard<std::mutex> lock(clientSptr->pimpl->requestInformation_.mutex_);
245 clientSptr->pimpl->requestInformation_.doing_ = false;
246 auto ptr = clientSptr->pimpl->requestInformation_.context_.descriptor_;
247 if (clientSptr->pimpl->requestInformation_.type_ == REQUEST_TYPE_DESCRIPTOR_WRITE) {
248 WPTR_GATT_CBACK(clientSptr->pimpl->callback_, OnDescriptorWriteResult, *ptr, ret);
249 } else if (clientSptr->pimpl->requestInformation_.type_ == REQUEST_TYPE_SET_NOTIFY_CHARACTERISTICS) {
250 auto characterPtr = clientSptr->pimpl->requestInformation_.context_.characteristic_;
251 WPTR_GATT_CBACK(clientSptr->pimpl->callback_, OnSetNotifyCharacteristic, *characterPtr, ret);
252 } else {
253 HILOGE("Unexpected call!");
254 }
255 }
256
OnMtuChanged(int32_t state,int32_t mtu)257 void OnMtuChanged(int32_t state, int32_t mtu) override
258 {
259 HILOGI("state: %{public}d, mtu: %{public}d", state, mtu);
260 std::shared_ptr<GattClient> clientSptr = (client_).lock();
261 if (!clientSptr) {
262 HILOGE("callback client is nullptr");
263 return;
264 }
265 WPTR_GATT_CBACK(clientSptr->pimpl->callback_, OnMtuUpdate, mtu, state);
266 }
267
OnServicesDiscovered(int32_t status)268 void OnServicesDiscovered(int32_t status) override
269 {
270 HILOGI("status: %{public}d", status);
271 std::shared_ptr<GattClient> clientSptr = (client_).lock();
272 if (!clientSptr) {
273 HILOGE("callback client is nullptr");
274 return;
275 }
276 clientSptr->pimpl->DiscoverComplete(status);
277 }
278
OnConnectionParameterChanged(int32_t interval,int32_t latency,int32_t timeout,int32_t status)279 void OnConnectionParameterChanged(int32_t interval, int32_t latency, int32_t timeout, int32_t status) override
280 {
281 HILOGI("interval: %{public}d, latency: %{public}d, timeout: %{public}d, status: %{public}d",
282 interval, latency, timeout, status);
283 std::shared_ptr<GattClient> clientSptr = (client_).lock();
284 if (!clientSptr) {
285 HILOGE("callback client is nullptr");
286 return;
287 }
288
289 WPTR_GATT_CBACK(clientSptr->pimpl->callback_, OnConnectionParameterChanged, interval, latency, timeout, status);
290 }
291
OnReadRemoteRssiValue(const bluetooth::RawAddress & addr,int32_t rssi,int32_t status)292 void OnReadRemoteRssiValue(const bluetooth::RawAddress &addr, int32_t rssi, int32_t status) override
293 {
294 HILOGI("rssi: %{public}d, status: %{public}d", rssi, status);
295 std::shared_ptr<GattClient> clientSptr = (client_).lock();
296 if (!clientSptr) {
297 HILOGE("callback client is nullptr");
298 return;
299 }
300 std::lock_guard<std::mutex> lock(clientSptr->pimpl->requestInformation_.mutex_);
301 clientSptr->pimpl->requestInformation_.doing_ = false;
302 if (clientSptr->pimpl->requestInformation_.type_ != REQUEST_TYPE_READ_REMOTE_RSSI_VALUE) {
303 HILOGE("Unexpected call!");
304 }
305 WPTR_GATT_CBACK(clientSptr->pimpl->callback_, OnReadRemoteRssiValueResult, rssi, status);
306 }
307
BluetoothGattClientCallbackStubImpl(std::weak_ptr<GattClient> client)308 explicit BluetoothGattClientCallbackStubImpl(std::weak_ptr<GattClient> client) : client_(client)
309 {}
~BluetoothGattClientCallbackStubImpl()310 ~BluetoothGattClientCallbackStubImpl() override
311 {}
312
313 private:
314 std::weak_ptr<GattClient> client_;
315 };
316
Init(std::weak_ptr<GattClient> client)317 bool GattClient::impl::Init(std::weak_ptr<GattClient> client)
318 {
319 if (clientCallback_ != nullptr) {
320 return true;
321 }
322 clientCallback_ = new BluetoothGattClientCallbackStubImpl(client);
323 return true;
324 }
325
impl(const BluetoothRemoteDevice & device)326 GattClient::impl::impl(const BluetoothRemoteDevice &device)
327 : isGetServiceYet_(false),
328 isRegisterSucceeded_(false),
329 applicationId_(0),
330 connectionState_(static_cast<int>(BTConnectState::DISCONNECTED)),
331 device_(device)
332 {
333 }
334
~impl()335 GattClient::impl::~impl()
336 {
337 HILOGI("GattClient ~impl");
338 }
339
DiscoverStart()340 int GattClient::impl::DiscoverStart()
341 {
342 if (!IS_BLE_ENABLED()) {
343 HILOGE("bluetooth is off.");
344 return BT_ERR_INVALID_STATE;
345 }
346
347 {
348 std::unique_lock<std::mutex> lock(discoverInformation_.mutex_);
349 while (discoverInformation_.isDiscovering_) {
350 auto ret = discoverInformation_.condition_.wait_for(lock, std::chrono::seconds(WAIT_TIMEOUT));
351 if (ret == std::cv_status::timeout) {
352 HILOGE("timeout");
353 return BT_ERR_INTERNAL_ERROR;
354 }
355 }
356 discoverInformation_.isDiscovering_ = true;
357 }
358
359 if (!isRegisterSucceeded_) {
360 return BT_ERR_INTERNAL_ERROR;
361 }
362 int result = BT_ERR_INTERNAL_ERROR;
363 sptr<IBluetoothGattClient> proxy = GetRemoteProxy<IBluetoothGattClient>(PROFILE_GATT_CLIENT);
364 if (!proxy) {
365 HILOGE("proxy is null");
366 } else {
367 result = proxy->DiscoveryServices(applicationId_);
368 if (result != BT_NO_ERROR) {
369 DiscoverComplete(BT_ERR_INTERNAL_ERROR);
370 }
371 }
372 return result;
373 }
374
DiscoverComplete(int state)375 void GattClient::impl::DiscoverComplete(int state)
376 {
377 bool ret = false;
378 {
379 std::unique_lock<std::mutex> lock(discoverInformation_.mutex_);
380 if (discoverInformation_.isDiscovering_) {
381 discoverInformation_.isDiscovering_ = false;
382 isGetServiceYet_ = false;
383 discoverInformation_.condition_.notify_all();
384 ret = true;
385 }
386 }
387 if (ret) {
388 std::shared_ptr<GattClientCallback> clientSptr = (callback_).lock();
389 clientSptr->OnServicesDiscovered(state);
390 }
391 }
392
BuildServiceList(const std::vector<BluetoothGattService> & src)393 void GattClient::impl::BuildServiceList(const std::vector<BluetoothGattService> &src)
394 {
395 HILOGI("enter");
396 for (auto &svc : src) {
397 GattService svcTmp(UUID::ConvertFrom128Bits(svc.uuid_.ConvertTo128Bits()),
398 svc.handle_,
399 svc.endHandle_,
400 svc.isPrimary_ ? GattServiceType::PRIMARY : GattServiceType::SECONDARY);
401 for (auto &character : svc.characteristics_) {
402 GattCharacteristic characterTmp(UUID::ConvertFrom128Bits(character.uuid_.ConvertTo128Bits()),
403 character.handle_,
404 character.permissions_,
405 character.properties_);
406 for (auto &desc : character.descriptors_) {
407 characterTmp.AddDescriptor(GattDescriptor(
408 UUID::ConvertFrom128Bits(desc.uuid_.ConvertTo128Bits()), desc.handle_, desc.permissions_));
409 }
410 svcTmp.AddCharacteristic(std::move(characterTmp));
411 }
412 gattServices_.emplace_back(std::move(svcTmp));
413 }
414 for (auto &svc : src) {
415 GattService *ptr = FindService(svc.handle_);
416 if (ptr == NULL) {
417 return;
418 }
419 for (auto &isvc : svc.includeServices_) {
420 GattService *iptr = FindService(isvc.startHandle_);
421 ptr->AddService(*iptr);
422 }
423 }
424 }
425
FindService(uint16_t handle)426 GattService *GattClient::impl::FindService(uint16_t handle)
427 {
428 for (auto &item : gattServices_) {
429 if (item.GetHandle() == handle) {
430 return &item;
431 }
432 }
433 return nullptr;
434 }
435
GetServices()436 void GattClient::impl::GetServices()
437 {
438 HILOGD("enter");
439 if (!IS_BLE_ENABLED()) {
440 HILOGE("bluetooth is off.");
441 return;
442 }
443
444 std::unique_lock<std::mutex> lock(discoverInformation_.mutex_);
445 while (discoverInformation_.isDiscovering_) {
446 auto ret = discoverInformation_.condition_.wait_for(lock, std::chrono::seconds(WAIT_TIMEOUT));
447 if (ret == std::cv_status::timeout) {
448 HILOGE("timeout");
449 return;
450 }
451 }
452 if (isGetServiceYet_) {
453 HILOGE("isGetServiceYet_ is true");
454 return;
455 }
456 if (!isRegisterSucceeded_) {
457 HILOGE("isRegisterSucceeded_ is false");
458 return;
459 }
460 gattServices_.clear();
461 std::vector<BluetoothGattService> result;
462 sptr<IBluetoothGattClient> proxy = GetRemoteProxy<IBluetoothGattClient>(PROFILE_GATT_CLIENT);
463 if (!proxy) {
464 HILOGE("proxy is null");
465 } else {
466 proxy->GetServices(applicationId_, result);
467 BuildServiceList(result);
468 isGetServiceYet_ = true;
469 }
470 }
471
CleanConnectionInfo()472 void GattClient::impl::CleanConnectionInfo()
473 {
474 DiscoverComplete(GattStatus::GATT_FAILURE);
475 std::lock_guard<std::mutex> lock(requestInformation_.mutex_);
476 requestInformation_.doing_ = false;
477 }
478
GattClient(const BluetoothRemoteDevice & device)479 GattClient::GattClient(const BluetoothRemoteDevice &device) : pimpl(new GattClient::impl(device))
480 {
481 HILOGI("enter");
482 }
483
Init()484 bool GattClient::Init()
485 {
486 HILOGI("GattClient Init");
487 return pimpl->Init(weak_from_this());
488 }
489
~GattClient()490 GattClient::~GattClient()
491 {
492 HILOGI("~GattClient");
493 sptr<IBluetoothGattClient> proxy = GetRemoteProxy<IBluetoothGattClient>(PROFILE_GATT_CLIENT);
494 CHECK_AND_RETURN_LOG(proxy != nullptr, "failed: no proxy");
495 if (pimpl->isRegisterSucceeded_) {
496 proxy->DeregisterApplication(pimpl->applicationId_);
497 }
498 }
499
Connect(std::weak_ptr<GattClientCallback> callback,bool isAutoConnect,int transport)500 int GattClient::Connect(std::weak_ptr<GattClientCallback> callback, bool isAutoConnect, int transport)
501 {
502 HILOGI("enter, isAutoConnect: %{public}d, transport: %{public}d", isAutoConnect, transport);
503 if (!IS_BLE_ENABLED()) {
504 HILOGE("bluetooth is off.");
505 return BT_ERR_INVALID_STATE;
506 }
507
508 if (pimpl == nullptr || !pimpl->Init(weak_from_this())) {
509 HILOGE("pimpl or gatt client proxy is nullptr");
510 return BT_ERR_INTERNAL_ERROR;
511 }
512
513 std::lock_guard<std::mutex> lock(pimpl->connStateMutex_);
514 if (pimpl->connectionState_ == static_cast<int>(BTConnectState::CONNECTED)) {
515 HILOGE("Already connected");
516 return BT_ERR_INTERNAL_ERROR;
517 }
518 HILOGI("isRegisterSucceeded: %{public}d", pimpl->isRegisterSucceeded_);
519 sptr<IBluetoothGattClient> proxy = GetRemoteProxy<IBluetoothGattClient>(PROFILE_GATT_CLIENT);
520 CHECK_AND_RETURN_LOG_RET(proxy != nullptr, BT_ERR_INTERNAL_ERROR, "failed: no proxy");
521 if (pimpl->isRegisterSucceeded_) {
522 return proxy->Connect(pimpl->applicationId_, isAutoConnect);
523 }
524 pimpl->callback_ = callback;
525 if ((transport == GATT_TRANSPORT_TYPE_LE && !IS_BLE_ENABLED()) ||
526 (transport == GATT_TRANSPORT_TYPE_CLASSIC && !IS_BT_ENABLED())) {
527 HILOGE("Unsupported mode");
528 return BT_ERR_INTERNAL_ERROR;
529 }
530 if (transport == GATT_TRANSPORT_TYPE_CLASSIC && isAutoConnect) {
531 HILOGE("Unsupported mode");
532 return BT_ERR_INTERNAL_ERROR;
533 }
534 if (!pimpl->device_.IsValidBluetoothRemoteDevice()) {
535 HILOGE("Invalid remote device");
536 return BT_ERR_INTERNAL_ERROR;
537 }
538
539 int appId = 0;
540 int32_t result = proxy->RegisterApplication(
541 pimpl->clientCallback_, bluetooth::RawAddress(pimpl->device_.GetDeviceAddr()), transport, appId);
542 HILOGI("Proxy register application : %{public}d", appId);
543 if (result != BT_NO_ERROR) {
544 HILOGE("register application fail");
545 return result;
546 }
547 if (appId > 0) {
548 pimpl->applicationId_ = appId;
549 pimpl->isRegisterSucceeded_ = true;
550 result = proxy->Connect(pimpl->applicationId_, isAutoConnect);
551 }
552 return result;
553 }
554
Disconnect()555 int GattClient::Disconnect()
556 {
557 HILOGI("enter");
558 if (!IS_BLE_ENABLED()) {
559 HILOGE("bluetooth is off.");
560 return BT_ERR_INVALID_STATE;
561 }
562
563 if (pimpl == nullptr || !pimpl->Init(weak_from_this())) {
564 HILOGE("pimpl or gatt client proxy is nullptr");
565 return BT_ERR_INTERNAL_ERROR;
566 }
567
568 std::lock_guard<std::mutex> lock(pimpl->connStateMutex_);
569 if (pimpl->connectionState_ != static_cast<int>(BTConnectState::CONNECTED) || !pimpl->isRegisterSucceeded_) {
570 HILOGE("Request not supported");
571 return BT_ERR_INTERNAL_ERROR;
572 }
573 int result = BT_ERR_INTERNAL_ERROR;
574 sptr<IBluetoothGattClient> proxy = GetRemoteProxy<IBluetoothGattClient>(PROFILE_GATT_CLIENT);
575 CHECK_AND_RETURN_LOG_RET(proxy != nullptr, BT_ERR_INTERNAL_ERROR, "failed: no proxy");
576 result = proxy->Disconnect(pimpl->applicationId_);
577 return result;
578 }
579
Close()580 int GattClient::Close()
581 {
582 HILOGI("enter");
583 if (!IS_BLE_ENABLED()) {
584 HILOGE("bluetooth is off.");
585 return BT_ERR_INVALID_STATE;
586 }
587 if (pimpl == nullptr || !pimpl->Init(weak_from_this())) {
588 HILOGE("pimpl or gatt client proxy is nullptr");
589 return BT_ERR_INTERNAL_ERROR;
590 }
591
592 sptr<IBluetoothGattClient> proxy = GetRemoteProxy<IBluetoothGattClient>(PROFILE_GATT_CLIENT);
593 CHECK_AND_RETURN_LOG_RET(proxy != nullptr, BT_ERR_INTERNAL_ERROR, "failed: no proxy");
594 if (pimpl->isRegisterSucceeded_) {
595 int32_t result = proxy->DeregisterApplication(pimpl->applicationId_);
596 HILOGI("result: %{public}d", result);
597 if (result == BT_NO_ERROR) {
598 pimpl->isRegisterSucceeded_ = false;
599 }
600 return result;
601 }
602 HILOGI("isRegisterSucceeded_ is false");
603 return BT_NO_ERROR;
604 }
605
DiscoverServices()606 int GattClient::DiscoverServices()
607 {
608 HILOGI("enter");
609 if (!IS_BLE_ENABLED()) {
610 HILOGE("bluetooth is off.");
611 return BT_ERR_INVALID_STATE;
612 }
613
614 if (pimpl == nullptr || !pimpl->Init(weak_from_this())) {
615 HILOGE("pimpl or gatt client proxy is nullptr");
616 return BT_ERR_INTERNAL_ERROR;
617 }
618
619 std::lock_guard<std::mutex> lck(pimpl->connStateMutex_);
620 if (pimpl->connectionState_ != static_cast<int>(BTConnectState::CONNECTED)) {
621 HILOGE("Request not supported");
622 return BT_ERR_INTERNAL_ERROR;
623 }
624 return pimpl->DiscoverStart();
625 }
626
GetService(const UUID & uuid)627 std::optional<std::reference_wrapper<GattService>> GattClient::GetService(const UUID &uuid)
628 {
629 HILOGD("enter");
630 if (!IS_BLE_ENABLED()) {
631 HILOGE("bluetooth is off.");
632 return std::nullopt;
633 }
634
635 if (pimpl == nullptr || !pimpl->Init(weak_from_this())) {
636 HILOGE("pimpl or gatt client proxy is nullptr");
637 return std::nullopt;
638 }
639
640 pimpl->GetServices();
641 for (auto &svc : pimpl->gattServices_) {
642 if (svc.GetUuid().Equals(uuid)) {
643 HILOGD("successful");
644 return svc;
645 }
646 }
647 HILOGE("failed");
648 return std::nullopt;
649 }
650
GetService()651 std::vector<GattService> &GattClient::GetService()
652 {
653 HILOGI("enter");
654 if (!IS_BLE_ENABLED()) {
655 HILOGE("bluetooth is off.");
656 return pimpl->gattServices_;
657 }
658
659 if (pimpl == nullptr || !pimpl->Init(weak_from_this())) {
660 HILOGE("pimpl or gatt client proxy is nullptr");
661 return pimpl->gattServices_;
662 }
663
664 pimpl->GetServices();
665 return pimpl->gattServices_;
666 }
667
ReadCharacteristic(GattCharacteristic & characteristic)668 int GattClient::ReadCharacteristic(GattCharacteristic &characteristic)
669 {
670 HILOGI("enter");
671 if (!IS_BLE_ENABLED()) {
672 HILOGE("bluetooth is off.");
673 return BT_ERR_INVALID_STATE;
674 }
675
676 if (pimpl == nullptr || !pimpl->Init(weak_from_this())) {
677 HILOGE("pimpl or gatt client proxy is nullptr");
678 return BT_ERR_INTERNAL_ERROR;
679 }
680
681 std::lock_guard<std::mutex> lock(pimpl->connStateMutex_);
682 if (pimpl->connectionState_ != static_cast<int>(BTConnectState::CONNECTED) || !pimpl->isRegisterSucceeded_) {
683 HILOGE("Request not supported");
684 return BT_ERR_INTERNAL_ERROR;
685 }
686 std::lock_guard<std::mutex> lck(pimpl->requestInformation_.mutex_);
687 if (pimpl->requestInformation_.doing_) {
688 HILOGE("Remote device busy");
689 return BT_ERR_INTERNAL_ERROR;
690 }
691 int result = GattStatus::GATT_FAILURE;
692 HILOGI("applicationId: %{public}d, handle: 0x%{public}04X", pimpl->applicationId_, characteristic.GetHandle());
693 sptr<IBluetoothGattClient> proxy = GetRemoteProxy<IBluetoothGattClient>(PROFILE_GATT_CLIENT);
694 CHECK_AND_RETURN_LOG_RET(proxy != nullptr, BT_ERR_INTERNAL_ERROR, "failed: no proxy");
695 result = proxy->ReadCharacteristic(
696 pimpl->applicationId_, (BluetoothGattCharacteristic)bluetooth::Characteristic(characteristic.GetHandle()));
697 HILOGI("result: %{public}d", result);
698 if (result == BT_NO_ERROR) {
699 pimpl->requestInformation_.doing_ = true;
700 pimpl->requestInformation_.type_ = REQUEST_TYPE_CHARACTERISTICS_READ;
701 pimpl->requestInformation_.context_.characteristic_ = &characteristic;
702 }
703 return result;
704 }
705
ReadDescriptor(GattDescriptor & descriptor)706 int GattClient::ReadDescriptor(GattDescriptor &descriptor)
707 {
708 HILOGI("enter");
709 if (!IS_BLE_ENABLED()) {
710 HILOGE("bluetooth is off.");
711 return BT_ERR_INVALID_STATE;
712 }
713
714 if (pimpl == nullptr || !pimpl->Init(weak_from_this())) {
715 HILOGE("pimpl or gatt client proxy is nullptr");
716 return BT_ERR_INTERNAL_ERROR;
717 }
718
719 std::lock_guard<std::mutex> lck(pimpl->connStateMutex_);
720 if (pimpl->connectionState_ != static_cast<int>(BTConnectState::CONNECTED) || !pimpl->isRegisterSucceeded_) {
721 HILOGE("Request not supported");
722 return BT_ERR_INTERNAL_ERROR;
723 }
724 std::lock_guard<std::mutex> lock(pimpl->requestInformation_.mutex_);
725 if (pimpl->requestInformation_.doing_) {
726 HILOGE("Remote device busy");
727 return BT_ERR_INTERNAL_ERROR;
728 }
729 int result = BT_ERR_INTERNAL_ERROR;
730 HILOGI("applicationId: %{public}d, handle: 0x%{public}04X", pimpl->applicationId_, descriptor.GetHandle());
731 sptr<IBluetoothGattClient> proxy = GetRemoteProxy<IBluetoothGattClient>(PROFILE_GATT_CLIENT);
732 CHECK_AND_RETURN_LOG_RET(proxy != nullptr, BT_ERR_INTERNAL_ERROR, "failed: no proxy");
733 result = proxy->ReadDescriptor(
734 pimpl->applicationId_, (BluetoothGattDescriptor)bluetooth::Descriptor(descriptor.GetHandle()));
735 HILOGI("result: %{public}d", result);
736 if (result == BT_NO_ERROR) {
737 pimpl->requestInformation_.doing_ = true;
738 pimpl->requestInformation_.type_ = REQUEST_TYPE_DESCRIPTOR_READ;
739 pimpl->requestInformation_.context_.descriptor_ = &descriptor;
740 }
741 return result;
742 }
743
RequestBleMtuSize(int mtu)744 int GattClient::RequestBleMtuSize(int mtu)
745 {
746 HILOGD("enter");
747 if (!IS_BLE_ENABLED()) {
748 HILOGE("bluetooth is off.");
749 return BT_ERR_INVALID_STATE;
750 }
751
752 if (pimpl == nullptr || !pimpl->Init(weak_from_this())) {
753 HILOGE("pimpl or gatt client proxy is nullptr");
754 return BT_ERR_INTERNAL_ERROR;
755 }
756
757 std::lock_guard<std::mutex> lck(pimpl->connStateMutex_);
758 if (pimpl->connectionState_ != static_cast<int>(BTConnectState::CONNECTED) || !pimpl->isRegisterSucceeded_) {
759 HILOGE("Request not supported");
760 return BT_ERR_INTERNAL_ERROR;
761 }
762 int result = BT_ERR_INTERNAL_ERROR;
763 HILOGI("applicationId: %{public}d, mtu: %{public}d", pimpl->applicationId_, mtu);
764 sptr<IBluetoothGattClient> proxy = GetRemoteProxy<IBluetoothGattClient>(PROFILE_GATT_CLIENT);
765 CHECK_AND_RETURN_LOG_RET(proxy != nullptr, BT_ERR_INTERNAL_ERROR, "failed: no proxy");
766 result = proxy->RequestExchangeMtu(pimpl->applicationId_, mtu);
767 HILOGI("result: %{public}d", result);
768 return result;
769 }
770
SetNotifyCharacteristicInner(GattCharacteristic & characteristic,bool enable,const std::vector<uint8_t> & descriptorValue)771 int GattClient::SetNotifyCharacteristicInner(GattCharacteristic &characteristic, bool enable,
772 const std::vector<uint8_t> &descriptorValue)
773 {
774 if (!IS_BLE_ENABLED()) {
775 HILOGE("bluetooth is off.");
776 return BT_ERR_INVALID_STATE;
777 }
778
779 if (pimpl == nullptr || !pimpl->Init(weak_from_this())) {
780 HILOGE("pimpl or gatt client proxy is nullptr");
781 return BT_ERR_INTERNAL_ERROR;
782 }
783
784 std::lock_guard<std::mutex> lockConn(pimpl->connStateMutex_);
785 if (pimpl->connectionState_ != static_cast<int>(BTConnectState::CONNECTED)) {
786 HILOGE("Request not supported");
787 return BT_ERR_INTERNAL_ERROR;
788 }
789 std::lock_guard<std::mutex> lock(pimpl->requestInformation_.mutex_);
790 if (pimpl->requestInformation_.doing_) {
791 HILOGI("Remote device busy");
792 return BT_ERR_INTERNAL_ERROR;
793 }
794 sptr<IBluetoothGattClient> proxy = GetRemoteProxy<IBluetoothGattClient>(PROFILE_GATT_CLIENT);
795 CHECK_AND_RETURN_LOG_RET(proxy != nullptr, BT_ERR_INTERNAL_ERROR, "failed: no proxy");
796 int ret = proxy->RequestNotification(pimpl->applicationId_, characteristic.GetHandle(), enable);
797 if (ret != BT_NO_ERROR) {
798 return ret;
799 }
800 auto descriptor = characteristic.GetDescriptor(UUID::FromString("00002902-0000-1000-8000-00805F9B34FB"));
801 if (descriptor == nullptr) {
802 HILOGE("descriptor not exist.");
803 return ret;
804 }
805 BluetoothGattDescriptor desc(bluetooth::Descriptor(
806 descriptor->GetHandle(), descriptorValue.data(), descriptorValue.size()));
807 int result = GattStatus::GATT_FAILURE;
808 HILOGD("applicationId: %{public}d", pimpl->applicationId_);
809 result = proxy->WriteDescriptor(pimpl->applicationId_, &desc);
810 HILOGI("result: %{public}d", result);
811 if (result == BT_NO_ERROR) {
812 pimpl->requestInformation_.type_ = REQUEST_TYPE_SET_NOTIFY_CHARACTERISTICS;
813 pimpl->requestInformation_.context_.characteristic_ = &characteristic;
814 pimpl->requestInformation_.doing_ = true;
815 }
816 return result;
817 }
818
SetNotifyCharacteristic(GattCharacteristic & characteristic,bool enable)819 int GattClient::SetNotifyCharacteristic(GattCharacteristic &characteristic, bool enable)
820 {
821 HILOGI("handle: 0x%{public}04X, enable: %{public}d", characteristic.GetHandle(), enable);
822 std::vector<uint8_t> enableNotifyValue = {1, 0};
823 std::vector<uint8_t> disableValue = {0, 0};
824 return SetNotifyCharacteristicInner(characteristic, enable, (enable ? enableNotifyValue : disableValue));
825 }
826
SetIndicateCharacteristic(GattCharacteristic & characteristic,bool enable)827 int GattClient::SetIndicateCharacteristic(GattCharacteristic &characteristic, bool enable)
828 {
829 HILOGI("handle: 0x%{public}04X, enable: %{public}d", characteristic.GetHandle(), enable);
830 std::vector<uint8_t> enableIndicateValue = {2, 0};
831 std::vector<uint8_t> disableValue = {0, 0};
832 return SetNotifyCharacteristicInner(characteristic, enable, (enable ? enableIndicateValue : disableValue));
833 }
834
WriteCharacteristic(GattCharacteristic & characteristic)835 int GattClient::WriteCharacteristic(GattCharacteristic &characteristic)
836 {
837 size_t length = 0;
838 const uint8_t *pData = characteristic.GetValue(&length).get();
839 std::vector<uint8_t> value(pData, pData + length);
840 return WriteCharacteristic(characteristic, std::move(value));
841 }
842
WriteCharacteristic(GattCharacteristic & characteristic,std::vector<uint8_t> value)843 int GattClient::WriteCharacteristic(GattCharacteristic &characteristic, std::vector<uint8_t> value)
844 {
845 HILOGD("enter");
846 if (!IS_BLE_ENABLED()) {
847 HILOGE("bluetooth is off.");
848 return BT_ERR_INVALID_STATE;
849 }
850
851 if (pimpl == nullptr || !pimpl->Init(weak_from_this())) {
852 HILOGE("pimpl or gatt client proxy is nullptr");
853 return BT_ERR_INTERNAL_ERROR;
854 }
855
856 std::lock_guard<std::mutex> lockConn(pimpl->connStateMutex_);
857 if (pimpl->connectionState_ != static_cast<int>(BTConnectState::CONNECTED)) {
858 HILOGE("Request not supported");
859 return BT_ERR_INTERNAL_ERROR;
860 }
861 size_t length = value.size();
862 HILOGD("length:%{public}zu", length);
863 if (length == 0) {
864 HILOGE("Invalid parameters");
865 return BT_ERR_INTERNAL_ERROR;
866 }
867 std::lock_guard<std::mutex> lock(pimpl->requestInformation_.mutex_);
868 if (pimpl->requestInformation_.doing_) {
869 HILOGE("Remote device busy");
870 return BT_ERR_INTERNAL_ERROR;
871 }
872 BluetoothGattCharacteristic character(
873 bluetooth::Characteristic(characteristic.GetHandle(), value.data(), length));
874 int result = BT_ERR_INTERNAL_ERROR;
875 bool withoutRespond = true;
876 sptr<IBluetoothGattClient> proxy = GetRemoteProxy<IBluetoothGattClient>(PROFILE_GATT_CLIENT);
877 CHECK_AND_RETURN_LOG_RET(proxy != nullptr, BT_ERR_INTERNAL_ERROR, "failed: no proxy");
878 if (characteristic.GetWriteType() == static_cast<int>(GattCharacteristic::WriteType::SIGNED)) {
879 HILOGI("Signed write");
880 result = proxy->SignedWriteCharacteristic(pimpl->applicationId_, &character);
881 } else {
882 withoutRespond = ((characteristic.GetWriteType() ==
883 static_cast<int>(GattCharacteristic::WriteType::DEFAULT)) ? false : true);
884 HILOGD("Write without response");
885 result = proxy->WriteCharacteristic(pimpl->applicationId_, &character, withoutRespond);
886 }
887 if (result == GattStatus::GATT_SUCCESS && !withoutRespond) {
888 HILOGI("successful");
889 pimpl->requestInformation_.type_ = REQUEST_TYPE_CHARACTERISTICS_WRITE;
890 pimpl->requestInformation_.context_.characteristic_ = &characteristic;
891 pimpl->requestInformation_.doing_ = true;
892 } else {
893 HILOGD("result: %{public}d", result);
894 }
895 return result;
896 }
897
WriteDescriptor(GattDescriptor & descriptor)898 int GattClient::WriteDescriptor(GattDescriptor &descriptor)
899 {
900 HILOGI("enter");
901 if (!IS_BLE_ENABLED()) {
902 HILOGE("bluetooth is off.");
903 return BT_ERR_INVALID_STATE;
904 }
905
906 if (pimpl == nullptr || !pimpl->Init(weak_from_this())) {
907 HILOGE("pimpl or gatt client proxy is nullptr");
908 return BT_ERR_INTERNAL_ERROR;
909 }
910
911 std::lock_guard<std::mutex> lck(pimpl->connStateMutex_);
912 if (pimpl->connectionState_ != static_cast<int>(BTConnectState::CONNECTED) || !pimpl->isRegisterSucceeded_) {
913 HILOGE("Request not supported");
914 return BT_ERR_INTERNAL_ERROR;
915 }
916 size_t length = 0;
917 auto &characterValue = descriptor.GetValue(&length);
918 if (characterValue == nullptr || length == 0) {
919 HILOGE("Invalid parameters");
920 return BT_ERR_INTERNAL_ERROR;
921 }
922 std::lock_guard<std::mutex> lock(pimpl->requestInformation_.mutex_);
923 if (pimpl->requestInformation_.doing_) {
924 HILOGE("Remote device busy");
925 return BT_ERR_INTERNAL_ERROR;
926 }
927 int result = BT_ERR_INTERNAL_ERROR;
928 sptr<IBluetoothGattClient> proxy = GetRemoteProxy<IBluetoothGattClient>(PROFILE_GATT_CLIENT);
929 CHECK_AND_RETURN_LOG_RET(proxy != nullptr, BT_ERR_INTERNAL_ERROR, "failed: no proxy");
930 BluetoothGattDescriptor desc(bluetooth::Descriptor(descriptor.GetHandle(), characterValue.get(), length));
931 result = proxy->WriteDescriptor(pimpl->applicationId_, &desc);
932 HILOGI("result: %{public}d", result);
933 if (result == BT_NO_ERROR) {
934 pimpl->requestInformation_.doing_ = true;
935 pimpl->requestInformation_.type_ = REQUEST_TYPE_DESCRIPTOR_WRITE;
936 pimpl->requestInformation_.context_.descriptor_ = &descriptor;
937 }
938 return result;
939 }
940
RequestConnectionPriority(int connPriority)941 int GattClient::RequestConnectionPriority(int connPriority)
942 {
943 if (!IS_BLE_ENABLED()) {
944 HILOGE("bluetooth is off.");
945 return BT_ERR_INVALID_STATE;
946 }
947
948 if (pimpl == nullptr || !pimpl->Init(weak_from_this())) {
949 HILOGE("pimpl or gatt client proxy is nullptr");
950 return BT_ERR_INTERNAL_ERROR;
951 }
952
953 std::lock_guard<std::mutex> lockConn(pimpl->connStateMutex_);
954 if (pimpl->connectionState_ != static_cast<int>(BTConnectState::CONNECTED)) {
955 HILOGE("Not connected");
956 return GattStatus::REQUEST_NOT_SUPPORT;
957 }
958 if (connPriority != static_cast<int>(GattConnectionPriority::BALANCED) &&
959 connPriority != static_cast<int>(GattConnectionPriority::HIGH) &&
960 connPriority != static_cast<int>(GattConnectionPriority::LOW_POWER)) {
961 HILOGE("Invalid parameters");
962 return GattStatus::INVALID_PARAMETER;
963 }
964 int result = GattStatus::GATT_FAILURE;
965 sptr<IBluetoothGattClient> proxy = GetRemoteProxy<IBluetoothGattClient>(PROFILE_GATT_CLIENT);
966 CHECK_AND_RETURN_LOG_RET(proxy != nullptr, BT_ERR_INTERNAL_ERROR, "failed: no proxy");
967 result = proxy->RequestConnectionPriority(pimpl->applicationId_, connPriority);
968 HILOGI("result: %{public}d", result);
969 return result;
970 }
971
RequestFastestConn()972 int GattClient::RequestFastestConn()
973 {
974 HILOGI("enter");
975 if (!IS_BLE_ENABLED()) {
976 HILOGE("bluetooth is off.");
977 return BT_ERR_INVALID_STATE;
978 }
979
980 if (pimpl == nullptr || !pimpl->Init(weak_from_this())) {
981 HILOGE("pimpl or gatt client proxy is nullptr");
982 return BT_ERR_INTERNAL_ERROR;
983 }
984
985 sptr<IBluetoothGattClient> proxy = GetRemoteProxy<IBluetoothGattClient>(PROFILE_GATT_CLIENT);
986 CHECK_AND_RETURN_LOG_RET(proxy != nullptr, BT_ERR_INTERNAL_ERROR, "failed: no proxy");
987 std::lock_guard<std::mutex> lock(pimpl->connStateMutex_);
988 return proxy->RequestFastestConn(bluetooth::RawAddress(pimpl->device_.GetDeviceAddr()));
989 }
ReadRemoteRssiValue()990 int GattClient::ReadRemoteRssiValue()
991 {
992 HILOGI("enter");
993 if (!IS_BLE_ENABLED()) {
994 HILOGE("bluetooth is off.");
995 return BT_ERR_INVALID_STATE;
996 }
997
998 if (pimpl == nullptr || !pimpl->Init(weak_from_this())) {
999 HILOGE("pimpl or gatt client proxy is nullptr");
1000 return BT_ERR_INTERNAL_ERROR;
1001 }
1002
1003 std::lock_guard<std::mutex> lock(pimpl->connStateMutex_);
1004 if (pimpl->connectionState_ != static_cast<int>(BTConnectState::CONNECTED) || !pimpl->isRegisterSucceeded_) {
1005 HILOGE("Request not supported");
1006 return BT_ERR_INTERNAL_ERROR;
1007 }
1008 std::lock_guard<std::mutex> lck(pimpl->requestInformation_.mutex_);
1009 if (pimpl->requestInformation_.doing_) {
1010 HILOGE("Remote device busy");
1011 return BT_ERR_INTERNAL_ERROR;
1012 }
1013 int result = GattStatus::GATT_FAILURE;
1014 HILOGI("applicationId: %{public}d", pimpl->applicationId_);
1015 sptr<IBluetoothGattClient> proxy = GetRemoteProxy<IBluetoothGattClient>(PROFILE_GATT_CLIENT);
1016 CHECK_AND_RETURN_LOG_RET(proxy != nullptr, BT_ERR_INTERNAL_ERROR, "failed: no proxy");
1017 result = proxy->ReadRemoteRssiValue(pimpl->applicationId_);
1018 HILOGI("result: %{public}d", result);
1019 if (result == BT_NO_ERROR) {
1020 pimpl->requestInformation_.doing_ = true;
1021 pimpl->requestInformation_.type_ = REQUEST_TYPE_READ_REMOTE_RSSI_VALUE;
1022 }
1023 return result;
1024 }
1025
1026 } // namespace Bluetooth
1027 } // namespace OHOS