• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_errorcode.h"
21 #include "bluetooth_def.h"
22 #include "bluetooth_gatt_client.h"
23 #include "bluetooth_gatt_client_proxy.h"
24 #include "bluetooth_gatt_client_callback_stub.h"
25 #include "bluetooth_host.h"
26 #include "bluetooth_host_proxy.h"
27 #include "bluetooth_log.h"
28 #include "bluetooth_utils.h"
29 #include "gatt_data.h"
30 #include "hilog/log.h"
31 #include "i_bluetooth_gatt_client.h"
32 #include "iservice_registry.h"
33 #include "raw_address.h"
34 #include "system_ability_definition.h"
35 
36 namespace OHOS {
37 namespace Bluetooth {
38 constexpr uint8_t REQUEST_TYPE_CHARACTERISTICS_READ = 0x00;
39 constexpr uint8_t REQUEST_TYPE_CHARACTERISTICS_WRITE = 0x01;
40 constexpr uint8_t REQUEST_TYPE_DESCRIPTOR_READ = 0x02;
41 constexpr uint8_t REQUEST_TYPE_DESCRIPTOR_WRITE = 0x03;
42 constexpr uint8_t REQUEST_TYPE_SET_NOTIFY_CHARACTERISTICS = 0x04;
43 
44 struct DiscoverInfomation {
45     struct Characteristics {
46         bool isDiscoverDescCompleted_;
CharacteristicsOHOS::Bluetooth::DiscoverInfomation::Characteristics47         Characteristics() : isDiscoverDescCompleted_(false)
48         {}
49     };
50 
51     struct Service {
52         bool isDiscoverCompleted_;
53         bool isDiscoverCharacteristicCompleted_;
54         bool isDiscoverIncludeSvcCompleted_;
55         uint16_t endHandle_;
56         std::map<uint16_t, Characteristics> characteristics_;
ServiceOHOS::Bluetooth::DiscoverInfomation::Service57         Service(uint16_t endHandle)
58             : isDiscoverCompleted_(false),
59               isDiscoverCharacteristicCompleted_(false),
60               isDiscoverIncludeSvcCompleted_(false),
61               endHandle_(endHandle)
62         {}
63     };
64     bool isDiscovering_;
65     bool needNotify_;
66     std::mutex mutex_;
67     std::condition_variable condition_;
68     std::map<uint16_t, Service> service_;
DiscoverInfomationOHOS::Bluetooth::DiscoverInfomation69     DiscoverInfomation() : isDiscovering_(false), needNotify_(false)
70     {}
71 };
72 
73 struct RequestInformation {
74     bool doing_;
75     uint8_t type_;
76     union {
77         GattCharacteristic *characteristic_;
78         GattDescriptor *descriptor_;
79     } context_;
80     std::mutex mutex_;
RequestInformationOHOS::Bluetooth::RequestInformation81     RequestInformation() : doing_(false)
82     {}
83 };
84 
85 struct GattClient::impl {
86     class BluetoothGattClientCallbackStubImpl;
87 
88     bool isGetServiceYet_;
89     bool isRegisterSucceeded_;
90     GattClientCallback *callback_;
91     int applicationId_;
92     int connectionState_;
93     BluetoothRemoteDevice device_;
94     sptr<IBluetoothGattClient> proxy_;
95     sptr<BluetoothGattClientCallbackStubImpl> clientCallback_;
96     std::vector<GattService> gattServices_;
97     std::mutex connStateMutex_;
98     RequestInformation requestInformation_;
99     DiscoverInfomation discoverInformation_;
100 
101     impl(GattClient &client, const BluetoothRemoteDevice &device);
102     ~impl();
103 
104     int DiscoverStart();
105     void DiscoverComplete(int state);
106     void BuildServiceList(const std::vector<BluetoothGattService> &src);
107     GattService *FindService(uint16_t handle);
108     void GetServices();
109     int GetTransport(int &transport);
110     void CleanConnectionInfo();
111     int CheckInterface(void);
112 
113     class GattClientDeathRecipient;
114     sptr<GattClientDeathRecipient> deathRecipient_;
115 };
116 
117 class GattClient::impl::GattClientDeathRecipient final : public IRemoteObject::DeathRecipient {
118 public:
GattClientDeathRecipient(GattClient::impl & client)119     GattClientDeathRecipient(GattClient::impl &client) : client_(client){};
120     ~GattClientDeathRecipient() final = default;
121     BLUETOOTH_DISALLOW_COPY_AND_ASSIGN(GattClientDeathRecipient);
122 
OnRemoteDied(const wptr<IRemoteObject> & remote)123     void OnRemoteDied(const wptr<IRemoteObject> &remote) final
124     {
125         HILOGI("enter");
126         client_.proxy_->AsObject()->RemoveDeathRecipient(client_.deathRecipient_);
127         client_.proxy_ = nullptr;
128     }
129 
130 private:
131     GattClient::impl &client_;
132 };
133 
134 class GattClient::impl::BluetoothGattClientCallbackStubImpl : public BluetoothGattClientCallbackStub {
135 public:
OnServicesChanged(std::vector<BluetoothGattService> & service)136     void OnServicesChanged(std::vector<BluetoothGattService> &service) override
137     {
138         HILOGI("enter");
139         client_.pimpl->DiscoverStart();
140     }
141 
OnConnectionStateChanged(int32_t state,int32_t newState)142     void OnConnectionStateChanged(int32_t state, int32_t newState) override
143     {
144         HILOGI("gattClient conn state, status: %{public}d, newState: %{public}s",
145             state, GetProfileConnStateName(newState).c_str());
146         if (newState == static_cast<int>(BTConnectState::DISCONNECTED)) {
147             client_.pimpl->CleanConnectionInfo();
148         }
149 
150         {
151             std::lock_guard<std::mutex> lck(client_.pimpl->connStateMutex_);
152             client_.pimpl->connectionState_ = newState;
153         }
154 
155         client_.pimpl->callback_->OnConnectionStateChanged(newState, state);
156     }
157 
OnCharacteristicChanged(const BluetoothGattCharacteristic & characteristic)158     void OnCharacteristicChanged(const BluetoothGattCharacteristic &characteristic) override
159     {
160         HILOGI("enter");
161         for (auto &svc : client_.pimpl->gattServices_) {
162             for (auto &character : svc.GetCharacteristics()) {
163                 if (character.GetHandle() == characteristic.handle_) {
164                     character.SetValue(characteristic.value_.get(), characteristic.length_);
165                     client_.pimpl->callback_->OnCharacteristicChanged(character);
166                 }
167             }
168         }
169     }
170 
OnCharacteristicRead(int32_t ret,const BluetoothGattCharacteristic & characteristic)171     void OnCharacteristicRead(int32_t ret, const BluetoothGattCharacteristic &characteristic) override
172     {
173         HILOGI("enter, ret: %{public}d", ret);
174         std::lock_guard<std::mutex> lock(client_.pimpl->requestInformation_.mutex_);
175         client_.pimpl->requestInformation_.doing_ = false;
176         auto ptr = client_.pimpl->requestInformation_.context_.characteristic_;
177         if (client_.pimpl->requestInformation_.type_ != REQUEST_TYPE_CHARACTERISTICS_READ) {
178             HILOGE("Unexpected call!");
179         }
180         if (GattStatus::GATT_SUCCESS == ret) {
181             ptr->SetValue(characteristic.value_.get(), characteristic.length_);
182         }
183         client_.pimpl->callback_->OnCharacteristicReadResult(*ptr, ret);
184     }
185 
OnCharacteristicWrite(int32_t ret,const BluetoothGattCharacteristic & characteristic)186     void OnCharacteristicWrite(int32_t ret, const BluetoothGattCharacteristic &characteristic) override
187     {
188         HILOGI("enter, ret: %{public}d", ret);
189         std::lock_guard<std::mutex> lock(client_.pimpl->requestInformation_.mutex_);
190         client_.pimpl->requestInformation_.doing_ = false;
191         auto ptr = client_.pimpl->requestInformation_.context_.characteristic_;
192         if (client_.pimpl->requestInformation_.type_ != REQUEST_TYPE_CHARACTERISTICS_WRITE) {
193             HILOGE("Unexpected call!");
194         }
195         client_.pimpl->callback_->OnCharacteristicWriteResult(*ptr, ret);
196     }
197 
OnDescriptorRead(int32_t ret,const BluetoothGattDescriptor & descriptor)198     void OnDescriptorRead(int32_t ret, const BluetoothGattDescriptor &descriptor) override
199     {
200         HILOGI("enter, ret: %{public}d", ret);
201         std::lock_guard<std::mutex> lock(client_.pimpl->requestInformation_.mutex_);
202         client_.pimpl->requestInformation_.doing_ = false;
203         auto ptr = client_.pimpl->requestInformation_.context_.descriptor_;
204         if (client_.pimpl->requestInformation_.type_ != REQUEST_TYPE_DESCRIPTOR_READ) {
205             HILOGE("Unexpected call!");
206         }
207         if (GattStatus::GATT_SUCCESS == ret) {
208             ptr->SetValue(descriptor.value_.get(), descriptor.length_);
209         }
210         client_.pimpl->callback_->OnDescriptorReadResult(*ptr, ret);
211     }
212 
OnDescriptorWrite(int32_t ret,const BluetoothGattDescriptor & descriptor)213     void OnDescriptorWrite(int32_t ret, const BluetoothGattDescriptor &descriptor) override
214     {
215         HILOGI("enter, ret: %{public}d", ret);
216         std::lock_guard<std::mutex> lock(client_.pimpl->requestInformation_.mutex_);
217         client_.pimpl->requestInformation_.doing_ = false;
218         auto ptr = client_.pimpl->requestInformation_.context_.descriptor_;
219         if (client_.pimpl->requestInformation_.type_ == REQUEST_TYPE_DESCRIPTOR_WRITE) {
220             client_.pimpl->callback_->OnDescriptorWriteResult(*ptr, ret);
221         } else if (client_.pimpl->requestInformation_.type_ == REQUEST_TYPE_SET_NOTIFY_CHARACTERISTICS) {
222             client_.pimpl->callback_->OnSetNotifyCharacteristic(ret);
223         } else {
224             HILOGE("Unexpected call!");
225         }
226     }
227 
OnMtuChanged(int32_t state,int32_t mtu)228     void OnMtuChanged(int32_t state, int32_t mtu) override
229     {
230         HILOGI("state: %{public}d, mtu: %{public}d", state, mtu);
231         client_.pimpl->callback_->OnMtuUpdate(mtu, state);
232     }
233 
OnServicesDiscovered(int32_t status)234     void OnServicesDiscovered(int32_t status) override
235     {
236         HILOGI("status: %{public}d", status);
237         client_.pimpl->DiscoverComplete(status);
238     }
239 
OnConnectionParameterChanged(int32_t interval,int32_t latency,int32_t timeout,int32_t status)240     void OnConnectionParameterChanged(int32_t interval, int32_t latency, int32_t timeout, int32_t status) override
241     {
242         HILOGI("interval: %{public}d, latency: %{public}d, timeout: %{public}d, status: %{public}d",
243             interval, latency, timeout, status);
244         client_.pimpl->callback_->OnConnectionParameterChanged(interval, latency, timeout, status);
245     }
246 
BluetoothGattClientCallbackStubImpl(GattClient & client)247     BluetoothGattClientCallbackStubImpl(GattClient &client) : client_(client)
248     {}
~BluetoothGattClientCallbackStubImpl()249     ~BluetoothGattClientCallbackStubImpl()
250     {}
251 
252 private:
253     GattClient &client_;
254 };
255 
impl(GattClient & client,const BluetoothRemoteDevice & device)256 GattClient::impl::impl(GattClient &client, const BluetoothRemoteDevice &device)
257     : isGetServiceYet_(false),
258       isRegisterSucceeded_(false),
259       callback_(nullptr),
260       applicationId_(0),
261       connectionState_(static_cast<int>(BTConnectState::DISCONNECTED)),
262       device_(device)
263 {
264     HILOGI("enter");
265     sptr<ISystemAbilityManager> samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
266     sptr<IRemoteObject> hostRemote = samgr->GetSystemAbility(BLUETOOTH_HOST_SYS_ABILITY_ID);
267 
268     if (!hostRemote) {
269         HILOGE("hostRemote is null");
270         return;
271     }
272 
273     sptr<IBluetoothHost> hostProxy = iface_cast<IBluetoothHost>(hostRemote);
274     sptr<IRemoteObject> remote = hostProxy->GetProfile(PROFILE_GATT_CLIENT);
275 
276     if (!remote) {
277         HILOGE("remote is null");
278         return;
279     }
280     HILOGI("remote obtained");
281     proxy_ = iface_cast<IBluetoothGattClient>(remote);
282     clientCallback_ = new BluetoothGattClientCallbackStubImpl(client);
283 
284     deathRecipient_ = new GattClientDeathRecipient(*this);
285     if (!proxy_) {
286         HILOGE("proxy_ is null");
287     } else {
288         proxy_->AsObject()->AddDeathRecipient(deathRecipient_);
289     }
290 }
291 
~impl()292 GattClient::impl::~impl()
293 {
294     HILOGI("GattClient ~impl");
295     if (!proxy_) {
296         HILOGE("proxy_ is null");
297     } else {
298         proxy_->AsObject()->RemoveDeathRecipient(deathRecipient_);
299     }
300 }
301 
CheckInterface(void)302 int GattClient::impl::CheckInterface(void)
303 {
304     if (proxy_ == nullptr) {
305         HILOGE("proxy_ is nullptr.");
306         return BT_ERR_INTERNAL_ERROR;
307     }
308     if (!BluetoothHost::GetDefaultHost().IsBleEnabled()) {
309         HILOGE("BLE is not enabled.");
310         return BT_ERR_INVALID_STATE;
311     }
312     return BT_SUCCESS;
313 }
314 
DiscoverStart()315 int GattClient::impl::DiscoverStart()
316 {
317     {
318         std::unique_lock<std::mutex> lock(discoverInformation_.mutex_);
319         while (discoverInformation_.isDiscovering_) {
320             discoverInformation_.condition_.wait(lock);
321         }
322         discoverInformation_.isDiscovering_ = true;
323     }
324 
325     if (!isRegisterSucceeded_) {
326         return BT_ERR_INTERNAL_ERROR;
327     }
328     int result = BT_ERR_INTERNAL_ERROR;
329     if (!proxy_) {
330         HILOGE("proxy_ is null");
331     } else {
332         result = proxy_->DiscoveryServices(applicationId_);
333         if (result != BT_SUCCESS) {
334             DiscoverComplete(BT_ERR_INTERNAL_ERROR);
335         }
336     }
337     return result;
338 }
339 
DiscoverComplete(int state)340 void GattClient::impl::DiscoverComplete(int state)
341 {
342     bool ret = false;
343     {
344         std::unique_lock<std::mutex> lock(discoverInformation_.mutex_);
345         if (discoverInformation_.isDiscovering_) {
346             discoverInformation_.isDiscovering_ = false;
347             isGetServiceYet_ = false;
348             discoverInformation_.condition_.notify_all();
349             ret = true;
350         }
351     }
352     if (ret) {
353         callback_->OnServicesDiscovered(state);
354     }
355 }
356 
BuildServiceList(const std::vector<BluetoothGattService> & src)357 void GattClient::impl::BuildServiceList(const std::vector<BluetoothGattService> &src)
358 {
359     HILOGI("enter");
360     for (auto &svc : src) {
361         GattService svcTmp(UUID::ConvertFrom128Bits(svc.uuid_.ConvertTo128Bits()),
362             svc.handle_,
363             svc.endHandle_,
364             svc.isPrimary_ ? GattServiceType::PRIMARY : GattServiceType::SECONDARY);
365         for (auto &character : svc.characteristics_) {
366             GattCharacteristic characterTmp(UUID::ConvertFrom128Bits(character.uuid_.ConvertTo128Bits()),
367                 character.handle_,
368                 character.permissions_,
369                 character.properties_);
370             for (auto &desc : character.descriptors_) {
371                 characterTmp.AddDescriptor(GattDescriptor(
372                     UUID::ConvertFrom128Bits(desc.uuid_.ConvertTo128Bits()), desc.handle_, desc.permissions_));
373             }
374             svcTmp.AddCharacteristic(std::move(characterTmp));
375         }
376         gattServices_.emplace_back(std::move(svcTmp));
377     }
378     for (auto &svc : src) {
379         GattService *ptr = FindService(svc.handle_);
380         if (ptr == NULL) {
381             return;
382         }
383         for (auto &isvc : svc.includeServices_) {
384             GattService *iptr = FindService(isvc.startHandle_);
385             ptr->AddService(*iptr);
386         }
387     }
388 }
389 
FindService(uint16_t handle)390 GattService *GattClient::impl::FindService(uint16_t handle)
391 {
392     for (auto &item : gattServices_) {
393         if (item.GetHandle() == handle) {
394             return &item;
395         }
396     }
397     return nullptr;
398 }
399 
GetServices()400 void GattClient::impl::GetServices()
401 {
402     HILOGI("enter");
403     std::unique_lock<std::mutex> lock(discoverInformation_.mutex_);
404     while (discoverInformation_.isDiscovering_) {
405         discoverInformation_.condition_.wait(lock);
406     }
407     if (isGetServiceYet_) {
408         HILOGE("isGetServiceYet_ is true");
409         return;
410     }
411     if (!isRegisterSucceeded_) {
412         HILOGE("isRegisterSucceeded_ is false");
413         return;
414     }
415     gattServices_.clear();
416     std::vector<BluetoothGattService> result;
417     if (!proxy_) {
418         HILOGE("proxy_ is null");
419     } else {
420         proxy_->GetServices(applicationId_, result);
421         BuildServiceList(result);
422         isGetServiceYet_ = true;
423     }
424 }
425 
GetTransport(int & transport)426 int GattClient::impl::GetTransport(int &transport)
427 {
428     auto deviceType = device_.GetDeviceType();
429     switch (transport) {
430         case GATT_TRANSPORT_TYPE_LE: {
431             if (deviceType == DEVICE_TYPE_BREDR) {
432                 return GattStatus::REQUEST_NOT_SUPPORT;
433             }
434             break;
435         }
436         case GATT_TRANSPORT_TYPE_CLASSIC: {
437             if (deviceType == DEVICE_TYPE_LE) {
438                 return GattStatus::REQUEST_NOT_SUPPORT;
439             }
440             break;
441         }
442         case GATT_TRANSPORT_TYPE_AUTO: {
443             if (deviceType == DEVICE_TYPE_LE || deviceType == DEVICE_TYPE_DUAL_MONO ||
444                 deviceType == DEVICE_TYPE_UNKNOWN) {
445                 transport = GATT_TRANSPORT_TYPE_LE;
446             } else {
447                 transport = GATT_TRANSPORT_TYPE_CLASSIC;
448             }
449             break;
450         }
451         default:
452             return GattStatus::INVALID_PARAMETER;
453             break;
454     }
455     return GattStatus::GATT_SUCCESS;
456 }
457 
CleanConnectionInfo()458 void GattClient::impl::CleanConnectionInfo()
459 {
460     DiscoverComplete(GattStatus::GATT_FAILURE);
461     std::lock_guard<std::mutex> lock(requestInformation_.mutex_);
462     requestInformation_.doing_ = false;
463 }
464 
GattClient(const BluetoothRemoteDevice & device)465 GattClient::GattClient(const BluetoothRemoteDevice &device) : pimpl(new GattClient::impl(*this, device))
466 {
467     HILOGI("enter");
468 }
469 
~GattClient()470 GattClient::~GattClient()
471 {
472     HILOGI("~GattClient");
473     if (pimpl->isRegisterSucceeded_) {
474         if (!pimpl->proxy_) {
475             HILOGE("proxy_ is null");
476         } else {
477             pimpl->proxy_->DeregisterApplication(pimpl->applicationId_);
478         }
479     }
480 }
481 
Connect(GattClientCallback & callback,bool isAutoConnect,int transport)482 int GattClient::Connect(GattClientCallback &callback, bool isAutoConnect, int transport)
483 {
484     HILOGI("enter, isAutoConnect: %{public}d, transport: %{public}d", isAutoConnect, transport);
485     int ret = pimpl->CheckInterface();
486     if (ret != BT_SUCCESS) {
487         return ret;
488     }
489     std::lock_guard<std::mutex> lock(pimpl->connStateMutex_);
490     if (pimpl->connectionState_ == static_cast<int>(BTConnectState::CONNECTED)) {
491         HILOGE("Already connected");
492         return BT_ERR_INTERNAL_ERROR;
493     }
494     HILOGI("isRegisterSucceeded: %{public}d", pimpl->isRegisterSucceeded_);
495     if (pimpl->isRegisterSucceeded_) {
496         return pimpl->proxy_->Connect(pimpl->applicationId_, isAutoConnect);
497     }
498     pimpl->callback_ = &callback;
499     int32_t result = pimpl->GetTransport(transport);
500     if (GattStatus::GATT_SUCCESS != result) {
501         HILOGE("Transport error, status: %{public}d", result);
502         return result;
503     }
504     if ((transport == GATT_TRANSPORT_TYPE_LE && !IS_BLE_ENABLED()) ||
505         (transport == GATT_TRANSPORT_TYPE_CLASSIC && !IS_BT_ENABLED())) {
506         HILOGE("Unsupported mode");
507         return BT_ERR_INTERNAL_ERROR;
508     }
509     if (transport == GATT_TRANSPORT_TYPE_CLASSIC && isAutoConnect) {
510         HILOGE("Unsupported mode");
511         return BT_ERR_INTERNAL_ERROR;
512     }
513     if (!pimpl->device_.IsValidBluetoothRemoteDevice()) {
514         HILOGE("Invalid remote device");
515         return BT_ERR_INTERNAL_ERROR;
516     }
517     int appId = 0;
518     result = pimpl->proxy_->RegisterApplication(
519         pimpl->clientCallback_, bluetooth::RawAddress(pimpl->device_.GetDeviceAddr()), transport, appId);
520     HILOGI("Proxy register application : %{public}d", appId);
521     if (result != BT_SUCCESS) {
522         HILOGE("register application fail");
523         return result;
524     }
525     if (appId > 0) {
526         pimpl->applicationId_ = appId;
527         pimpl->isRegisterSucceeded_ = true;
528         result = pimpl->proxy_->Connect(pimpl->applicationId_, isAutoConnect);
529     }
530     return result;
531 }
532 
Disconnect()533 int GattClient::Disconnect()
534 {
535     HILOGI("enter");
536     int ret = pimpl->CheckInterface();
537     if (ret != BT_SUCCESS) {
538         return ret;
539     }
540     std::lock_guard<std::mutex> lock(pimpl->connStateMutex_);
541     if (pimpl->connectionState_ != static_cast<int>(BTConnectState::CONNECTED) || !pimpl->isRegisterSucceeded_) {
542         HILOGE("Request not supported");
543         return BT_ERR_INTERNAL_ERROR;
544     }
545     int result = BT_ERR_INTERNAL_ERROR;
546     result = pimpl->proxy_->Disconnect(pimpl->applicationId_);
547     return result;
548 }
549 
Close()550 int GattClient::Close()
551 {
552     HILOGI("enter");
553     int ret = pimpl->CheckInterface();
554     if (ret != BT_SUCCESS) {
555         return ret;
556     }
557     if (pimpl->isRegisterSucceeded_) {
558         int32_t result = pimpl->proxy_->DeregisterApplication(pimpl->applicationId_);
559         HILOGI("result: %{public}d", result);
560         if (result == BT_SUCCESS) {
561             pimpl->isRegisterSucceeded_ = false;
562         }
563         return result;
564     }
565     HILOGI("isRegisterSucceeded_ is false");
566     return BT_SUCCESS;
567 }
568 
DiscoverServices()569 int GattClient::DiscoverServices()
570 {
571     int ret = pimpl->CheckInterface();
572     if (ret != BT_SUCCESS) {
573         return ret;
574     }
575     HILOGI("enter");
576     std::lock_guard<std::mutex> lck(pimpl->connStateMutex_);
577     if (pimpl->connectionState_ != static_cast<int>(BTConnectState::CONNECTED)) {
578         HILOGE("Request not supported");
579         return BT_ERR_INTERNAL_ERROR;
580     }
581     return pimpl->DiscoverStart();
582 }
583 
GetService(const UUID & uuid)584 std::optional<std::reference_wrapper<GattService>> GattClient::GetService(const UUID &uuid)
585 {
586     HILOGI("enter");
587     pimpl->GetServices();
588     for (auto &svc : pimpl->gattServices_) {
589         if (svc.GetUuid().Equals(uuid)) {
590             HILOGI("successful");
591             return svc;
592         }
593     }
594     HILOGE("failed");
595     return std::nullopt;
596 }
597 
GetService()598 std::vector<GattService> &GattClient::GetService()
599 {
600     HILOGI("enter");
601     pimpl->GetServices();
602     return pimpl->gattServices_;
603 }
604 
ReadCharacteristic(GattCharacteristic & characteristic)605 int GattClient::ReadCharacteristic(GattCharacteristic &characteristic)
606 {
607     HILOGI("enter");
608     int ret = pimpl->CheckInterface();
609     if (ret != BT_SUCCESS) {
610         return ret;
611     }
612     std::lock_guard<std::mutex> lock(pimpl->connStateMutex_);
613     if (pimpl->connectionState_ != static_cast<int>(BTConnectState::CONNECTED) || !pimpl->isRegisterSucceeded_) {
614         HILOGE("Request not supported");
615         return BT_ERR_INTERNAL_ERROR;
616     }
617     std::lock_guard<std::mutex> lck(pimpl->requestInformation_.mutex_);
618     if (pimpl->requestInformation_.doing_) {
619         HILOGE("Remote device busy");
620         return BT_ERR_INTERNAL_ERROR;
621     }
622     int result = GattStatus::GATT_FAILURE;
623     HILOGI("applicationId: %{public}d, handle: 0x%{public}04X", pimpl->applicationId_, characteristic.GetHandle());
624     result = pimpl->proxy_->ReadCharacteristic(
625         pimpl->applicationId_, (BluetoothGattCharacteristic)bluetooth::Characteristic(characteristic.GetHandle()));
626     HILOGI("result: %{public}d", result);
627     if (result == BT_SUCCESS) {
628         pimpl->requestInformation_.doing_ = true;
629         pimpl->requestInformation_.type_ = REQUEST_TYPE_CHARACTERISTICS_READ;
630         pimpl->requestInformation_.context_.characteristic_ = &characteristic;
631     }
632     return result;
633 }
634 
ReadDescriptor(GattDescriptor & descriptor)635 int GattClient::ReadDescriptor(GattDescriptor &descriptor)
636 {
637     HILOGI("enter");
638     int ret = pimpl->CheckInterface();
639     if (ret != BT_SUCCESS) {
640         return ret;
641     }
642     std::lock_guard<std::mutex> lck(pimpl->connStateMutex_);
643     if (pimpl->connectionState_ != static_cast<int>(BTConnectState::CONNECTED) || !pimpl->isRegisterSucceeded_) {
644         HILOGE("Request not supported");
645         return BT_ERR_INTERNAL_ERROR;
646     }
647     std::lock_guard<std::mutex> lock(pimpl->requestInformation_.mutex_);
648     if (pimpl->requestInformation_.doing_) {
649         HILOGE("Remote device busy");
650         return BT_ERR_INTERNAL_ERROR;
651     }
652     int result = BT_ERR_INTERNAL_ERROR;
653     HILOGI("applicationId: %{public}d, handle: 0x%{public}04X", pimpl->applicationId_, descriptor.GetHandle());
654     result = pimpl->proxy_->ReadDescriptor(
655         pimpl->applicationId_, (BluetoothGattDescriptor)bluetooth::Descriptor(descriptor.GetHandle()));
656     HILOGI("result: %{public}d", result);
657     if (result == BT_SUCCESS) {
658         pimpl->requestInformation_.doing_ = true;
659         pimpl->requestInformation_.type_ = REQUEST_TYPE_DESCRIPTOR_READ;
660         pimpl->requestInformation_.context_.descriptor_ = &descriptor;
661     }
662     return result;
663 }
664 
RequestBleMtuSize(int mtu)665 int GattClient::RequestBleMtuSize(int mtu)
666 {
667     HILOGI("enter");
668     int ret = pimpl->CheckInterface();
669     if (ret != BT_SUCCESS) {
670         return ret;
671     }
672     std::lock_guard<std::mutex> lck(pimpl->connStateMutex_);
673     if (pimpl->connectionState_ != static_cast<int>(BTConnectState::CONNECTED) || !pimpl->isRegisterSucceeded_) {
674         HILOGE("Request not supported");
675         return BT_ERR_INTERNAL_ERROR;
676     }
677     int result = BT_ERR_INTERNAL_ERROR;
678     HILOGI("applicationId: %{public}d, mtu: %{public}d", pimpl->applicationId_, mtu);
679     result = pimpl->proxy_->RequestExchangeMtu(pimpl->applicationId_, mtu);
680     HILOGI("result: %{public}d", result);
681     return result;
682 }
683 
SetNotifyCharacteristic(GattCharacteristic & characteristic,bool enable)684 int GattClient::SetNotifyCharacteristic(GattCharacteristic &characteristic, bool enable)
685 {
686     HILOGI("handle: 0x%{public}04X, enable: %{public}d", characteristic.GetHandle(), enable);
687     int ret = pimpl->CheckInterface();
688     if (ret != BT_SUCCESS) {
689         return ret;
690     }
691     static const uint8_t NOTIFICATION[2] = {1, 0};
692     static const uint8_t DEFAULT_VALUE[2] = {0};
693     static const size_t CLIENT_CHARACTERISTIC_CONFIGURATION_VALUE_LENGTH = 0x02;
694     std::lock_guard<std::mutex> lockConn(pimpl->connStateMutex_);
695     if (pimpl->connectionState_ != static_cast<int>(BTConnectState::CONNECTED)) {
696         HILOGE("Request not supported");
697         return BT_ERR_INTERNAL_ERROR;
698     }
699     auto descriptor = characteristic.GetDescriptor(UUID::FromString("00002902-0000-1000-8000-00805F9B34FB"));
700     if (descriptor == nullptr) {
701         HILOGE("Invalid parameters");
702         return BT_ERR_INTERNAL_ERROR;
703     }
704     std::lock_guard<std::mutex> lock(pimpl->requestInformation_.mutex_);
705     if (pimpl->requestInformation_.doing_) {
706         HILOGI("Remote device busy");
707         return BT_ERR_INTERNAL_ERROR;
708     }
709     BluetoothGattDescriptor desc(bluetooth::Descriptor(descriptor->GetHandle(),
710         (enable ? NOTIFICATION : DEFAULT_VALUE),
711         CLIENT_CHARACTERISTIC_CONFIGURATION_VALUE_LENGTH));
712     int result = GattStatus::GATT_FAILURE;
713     HILOGI("applicationId: %{public}d", pimpl->applicationId_);
714     result = pimpl->proxy_->WriteDescriptor(pimpl->applicationId_, &desc);
715     HILOGI("result: %{public}d", result);
716     if (result == BT_SUCCESS) {
717         pimpl->requestInformation_.type_ = REQUEST_TYPE_SET_NOTIFY_CHARACTERISTICS;
718         pimpl->requestInformation_.context_.descriptor_ = descriptor;
719         pimpl->requestInformation_.doing_ = true;
720     }
721     return result;
722 }
723 
WriteCharacteristic(GattCharacteristic & characteristic)724 int GattClient::WriteCharacteristic(GattCharacteristic &characteristic)
725 {
726     HILOGI("enter");
727     int ret = pimpl->CheckInterface();
728     if (ret != BT_SUCCESS) {
729         return ret;
730     }
731     std::lock_guard<std::mutex> lockConn(pimpl->connStateMutex_);
732     if (pimpl->connectionState_ != static_cast<int>(BTConnectState::CONNECTED)) {
733         HILOGE("Request not supported");
734         return BT_ERR_INTERNAL_ERROR;
735     }
736     size_t length = 0;
737     auto &characterValue = characteristic.GetValue(&length);
738     HILOGI("length:%{public}zu", length);
739     if (characterValue == nullptr || length == 0) {
740         HILOGE("Invalid parameters");
741         return BT_ERR_INTERNAL_ERROR;
742     }
743     std::lock_guard<std::mutex> lock(pimpl->requestInformation_.mutex_);
744     if (pimpl->requestInformation_.doing_) {
745         HILOGE("Remote device busy");
746         return BT_ERR_INTERNAL_ERROR;
747     }
748     BluetoothGattCharacteristic character(
749         bluetooth::Characteristic(characteristic.GetHandle(), characterValue.get(), length));
750     int result = BT_ERR_INTERNAL_ERROR;
751     bool withoutRespond = true;
752     if (characteristic.GetWriteType() == static_cast<int>(GattCharacteristic::WriteType::SIGNED)) {
753         HILOGI("Signed write");
754         result = pimpl->proxy_->SignedWriteCharacteristic(pimpl->applicationId_, &character);
755     } else {
756         withoutRespond = ((characteristic.GetWriteType() ==
757             static_cast<int>(GattCharacteristic::WriteType::DEFAULT)) ? false : true);
758         HILOGI("Write without response");
759         result = pimpl->proxy_->WriteCharacteristic(pimpl->applicationId_, &character, withoutRespond);
760     }
761     if (result && !withoutRespond == GattStatus::GATT_SUCCESS) {
762         HILOGI("successful");
763         pimpl->requestInformation_.type_ = REQUEST_TYPE_CHARACTERISTICS_WRITE;
764         pimpl->requestInformation_.context_.characteristic_ = &characteristic;
765         pimpl->requestInformation_.doing_ = true;
766     } else {
767         HILOGI("result: %{public}d", result);
768     }
769     return result;
770 }
771 
WriteDescriptor(GattDescriptor & descriptor)772 int GattClient::WriteDescriptor(GattDescriptor &descriptor)
773 {
774     HILOGI("enter");
775     int ret = pimpl->CheckInterface();
776     if (ret != BT_SUCCESS) {
777         return ret;
778     }
779     std::lock_guard<std::mutex> lck(pimpl->connStateMutex_);
780     if (pimpl->connectionState_ != static_cast<int>(BTConnectState::CONNECTED) || !pimpl->isRegisterSucceeded_) {
781         HILOGE("Request not supported");
782         return BT_ERR_INTERNAL_ERROR;
783     }
784     size_t length = 0;
785     auto &characterValue = descriptor.GetValue(&length);
786     if (characterValue == nullptr || length == 0) {
787         HILOGE("Invalid parameters");
788         return BT_ERR_INTERNAL_ERROR;
789     }
790     std::lock_guard<std::mutex> lock(pimpl->requestInformation_.mutex_);
791     if (pimpl->requestInformation_.doing_) {
792         HILOGE("Remote device busy");
793         return BT_ERR_INTERNAL_ERROR;
794     }
795     int result = BT_ERR_INTERNAL_ERROR;
796     BluetoothGattDescriptor desc(bluetooth::Descriptor(descriptor.GetHandle(), characterValue.get(), length));
797     result = pimpl->proxy_->WriteDescriptor(pimpl->applicationId_, &desc);
798     HILOGI("result: %{public}d", result);
799     if (result == BT_SUCCESS) {
800         pimpl->requestInformation_.doing_ = true;
801         pimpl->requestInformation_.type_ = REQUEST_TYPE_DESCRIPTOR_WRITE;
802         pimpl->requestInformation_.context_.descriptor_ = &descriptor;
803     }
804     return result;
805 }
806 
RequestConnectionPriority(int connPriority)807 int GattClient::RequestConnectionPriority(int connPriority)
808 {
809     int ret = pimpl->CheckInterface();
810     if (ret != BT_SUCCESS) {
811         return ret;
812     }
813     std::lock_guard<std::mutex> lockConn(pimpl->connStateMutex_);
814     if (pimpl->connectionState_ != static_cast<int>(BTConnectState::CONNECTED)) {
815         HILOGE("Not connected");
816         return GattStatus::REQUEST_NOT_SUPPORT;
817     }
818     if (connPriority != static_cast<int>(GattConnectionPriority::BALANCED) &&
819         connPriority != static_cast<int>(GattConnectionPriority::HIGH) &&
820         connPriority != static_cast<int>(GattConnectionPriority::LOW_POWER)) {
821         HILOGE("Invalid parameters");
822         return GattStatus::INVALID_PARAMETER;
823     }
824     int result = GattStatus::GATT_FAILURE;
825     result = pimpl->proxy_->RequestConnectionPriority(pimpl->applicationId_, connPriority);
826     HILOGI("result: %{public}d", result);
827     return result;
828 }
829 }  // namespace Bluetooth
830 }  // namespace OHOS