1 /*
2  * Copyright (C) 2021 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 "generic_attribute_service.h"
17 #include "../common/compat.h"
18 #include "../gatt_connection_manager.h"
19 #include "../gatt_connection_observer.h"
20 #include "../gatt_defines.h"
21 #include "adapter_device_config.h"
22 #include "class_creator.h"
23 #include "log.h"
24 #include "securec.h"
25 
26 namespace OHOS {
27 namespace bluetooth {
28 const size_t GenericAttributeService::CLIENT_CHARACTERISTIC_CONFIGURATION_VALUE_LENGTH = 0x02;
29 const size_t GenericAttributeService::SERVICE_CHANGED_VALUE_LENGTH = 0x04;
30 const uint8_t GenericAttributeService::CLIENT_CHARACTERISTIC_CONFIGURATION_DEFAULT_VALUE[2] = {0};
31 const uint8_t GenericAttributeService::SERVICE_CHANGED_DEFAULT_VALUE[4] = {0};
32 
GenericAttributeService(GattServerService & service,utility::Dispatcher & dispatcher)33 GenericAttributeService::GenericAttributeService(GattServerService &service, utility::Dispatcher &dispatcher)
34     : serverService_(service), dispatcher_(dispatcher),
35     serviceCallback_(std::make_shared<GattServerCallbackImpl>(*this))
36 {
37     LoadNotifyInformation();
38 }
39 
~GenericAttributeService()40 GenericAttributeService::~GenericAttributeService()
41 {
42     StoreNotifyInformation();
43 }
44 
45 class GenericAttributeService::GattServerCallbackImpl : public IGattServerCallback {
46 public:
OnConnectionStateChanged(const GattDevice & device,int ret,int state)47     void OnConnectionStateChanged(const GattDevice &device, int ret, int state) override
48     {
49         if (state == static_cast<int>(BTConnectState::CONNECTED)) {
50             service_.dispatcher_.PostTask(std::bind(&GenericAttributeService::ConnectIncoming, &service_, device));
51         } else if (state == static_cast<int>(BTConnectState::DISCONNECTED)) {
52             service_.dispatcher_.PostTask(std::bind(&GenericAttributeService::Disconnected, &service_, device));
53         }
54     }
55 
OnServiceChanged(const Service & service)56     void OnServiceChanged(const Service &service) override
57     {
58         LOG_INFO("%{public}s:%{public}d:%{public}s", __FILE__, __LINE__, __FUNCTION__);
59         service_.dispatcher_.PostTask(
60             std::bind(&GenericAttributeService::NotifyAllDevices, &service_, service.handle_, service.endHandle_));
61     }
62 
OnNotifyConfirm(const GattDevice & device,const Characteristic & characteristic,int result)63     void OnNotifyConfirm(const GattDevice &device, const Characteristic &characteristic, int result) override
64     {
65         if (characteristic.uuid_ == Uuid::ConvertFrom16Bits(UUID_SERVICE_CHANGED) &&
66             result == GattStatus::GATT_SUCCESS) {
67             service_.dispatcher_.PostTask(std::bind(&GenericAttributeService::ComfirmNotify, &service_, device));
68         }
69     }
70 
GattServerCallbackImpl(GenericAttributeService & service)71     explicit GattServerCallbackImpl(GenericAttributeService &service) : service_(service)
72     {}
~GattServerCallbackImpl()73     ~GattServerCallbackImpl()
74     {}
75 
76 private:
77     GenericAttributeService &service_;
78 };
79 
RegisterService()80 int GenericAttributeService::RegisterService()
81 {
82     appId_ = serverService_.RegisterApplicationSync(serviceCallback_);
83     if (appId_ < 0) {
84         return appId_;
85     }
86 
87     instance_ = BuildService();
88     int result = serverService_.AddServiceSync(appId_, *instance_);
89     if (result != GattStatus::GATT_SUCCESS) {
90         LOG_WARN("%{public}s:%{public}d:%{public}s : Add GATTS Failed! ret: %{public}d", __FILE__, __LINE__, __FUNCTION__, result);
91     }
92 
93     return result;
94 }
95 
DeregisterService() const96 void GenericAttributeService::DeregisterService() const
97 {
98     LOG_INFO("%{public}s:%{public}d:%{public}s", __FILE__, __LINE__, __FUNCTION__);
99     serverService_.DeregisterApplicationSync(appId_);
100 }
101 
RegisterSDP()102 int GenericAttributeService::RegisterSDP()
103 {
104     if (instance_ == nullptr) {
105         return GattStatus::REQUEST_NOT_SUPPORT;
106     }
107 
108     sdpRegister_.reset(ClassCreator<GattServiceOverBredr>::NewInstance("GattServiceOverBredr"));
109     if (sdpRegister_ != nullptr) {
110         static_cast<GattServiceOverBredrInterface *>(sdpRegister_.get())
111             ->RegisterSDP(instance_->startHandle_, instance_->endHandle_);
112     }
113 
114     LOG_DEBUG("[GenericAttributeService]::%{public}s", __FUNCTION__);
115 
116     return GattStatus::GATT_SUCCESS;
117 }
118 
DeregisterSDP() const119 void GenericAttributeService::DeregisterSDP() const
120 {
121     LOG_INFO("%{public}s:%{public}d:%{public}s", __FILE__, __LINE__, __FUNCTION__);
122     if (sdpRegister_ != nullptr) {
123         static_cast<GattServiceOverBredrInterface *>(sdpRegister_.get())->DeregisterSDP();
124     }
125 }
126 
StoreNotifyInformation() const127 void GenericAttributeService::StoreNotifyInformation() const
128 {
129     bool needsave = false;
130     for (auto &dev : devices_) {
131         if (!dev.second.isNotified && GattConnectionManager::GetInstance().GetEncryptionInfo(dev.first)) {
132             AdapterDeviceConfig::GetInstance()->SetValue(SECTION_GENERIC_ATTRIBUTE_SERVICE,
133                 dev.first.addr_.GetAddress(),
134                 PROPERTY_GATTS_START_HANDLE,
135                 dev.second.startHandle_);
136             AdapterDeviceConfig::GetInstance()->SetValue(SECTION_GENERIC_ATTRIBUTE_SERVICE,
137                 dev.first.addr_.GetAddress(),
138                 PROPERTY_GATTS_END_HANDLE,
139                 dev.second.endHandle_);
140             AdapterDeviceConfig::GetInstance()->SetValue(SECTION_GENERIC_ATTRIBUTE_SERVICE,
141                 dev.first.addr_.GetAddress(),
142                 PROPERTY_GATT_TRANSPORT,
143                 dev.first.transport_);
144             needsave = true;
145         }
146     }
147     if (needsave) {
148         AdapterDeviceConfig::GetInstance()->Save();
149     }
150 }
151 
LoadNotifyInformation()152 void GenericAttributeService::LoadNotifyInformation()
153 {
154     AdapterDeviceConfig::GetInstance()->Load();
155 
156     std::vector<std::string> devices;
157     AdapterDeviceConfig::GetInstance()->GetSubSections(SECTION_GENERIC_ATTRIBUTE_SERVICE, devices);
158     for (auto &dev : devices) {
159         int startHandle = MIN_ATTRIBUTE_HANDLE;
160         int endhandle = MAX_ATTRIBUTE_HANDLE;
161         int transport = GATT_TRANSPORT_TYPE_LE;
162         AdapterDeviceConfig::GetInstance()->GetValue(
163             SECTION_GENERIC_ATTRIBUTE_SERVICE, dev, PROPERTY_GATTS_START_HANDLE, startHandle);
164         AdapterDeviceConfig::GetInstance()->GetValue(
165             SECTION_GENERIC_ATTRIBUTE_SERVICE, dev, PROPERTY_GATTS_END_HANDLE, endhandle);
166 
167         if (!AdapterDeviceConfig::GetInstance()->GetValue(
168             SECTION_GENERIC_ATTRIBUTE_SERVICE, dev, PROPERTY_GATT_TRANSPORT, transport)) {
169             LOG_WARN("%{public}s:%{public}d:%{public}s::Get device transport Failed!", __FILE__, __LINE__, __FUNCTION__);
170         }
171 
172         devices_.emplace(std::make_pair<GattDevice, NotifyInformation>(
173             GattDevice(RawAddress(dev), (uint8_t)transport), {
174             .isNotified = false, .startHandle_ = (uint16_t)startHandle, .endHandle_ = (uint16_t)endhandle
175             }));
176 
177         AdapterDeviceConfig::GetInstance()->RemoveSection(SECTION_GENERIC_ATTRIBUTE_SERVICE, dev);
178         AdapterDeviceConfig::GetInstance()->Save();
179     }
180 }
181 
ComfirmNotify(GattDevice device)182 void GenericAttributeService::ComfirmNotify(GattDevice device)
183 {
184     auto dev = devices_.find(device);
185     if (dev != devices_.end()) {
186         dev->second.isNotified = true;
187     }
188 }
189 
BuildService()190 std::unique_ptr<Service> GenericAttributeService::BuildService()
191 {
192     std::unique_ptr<Service> svc =
193         std::make_unique<Service>(Uuid::ConvertFrom16Bits(UUID_GENERIC_ATTRIBUTE_SERVICE), 0, 0, 0);
194     svc->isPrimary_ = true;
195 
196     Characteristic characteristic(Uuid::ConvertFrom16Bits(UUID_SERVICE_CHANGED),
197         0,
198         CHARACTERISTIC_PROPERTIE_INDICATE,
199         0,
200         SERVICE_CHANGED_DEFAULT_VALUE,
201         SERVICE_CHANGED_VALUE_LENGTH);
202 
203     characteristic.descriptors_.push_back(Descriptor(Uuid::ConvertFrom16Bits(UUID_CLIENT_CHARACTERISTIC_CONFIGURATION),
204         0,
205         (int)GattPermissionService::READABLE | (int)GattPermissionService::WRITEABLE,
206         CLIENT_CHARACTERISTIC_CONFIGURATION_DEFAULT_VALUE,
207         CLIENT_CHARACTERISTIC_CONFIGURATION_VALUE_LENGTH));
208 
209     svc->characteristics_.push_back(characteristic);
210 
211     return svc;
212 }
213 
NotifyAllDevices(uint16_t startHandle,uint16_t endHandle)214 void GenericAttributeService::NotifyAllDevices(uint16_t startHandle, uint16_t endHandle)
215 {
216     LOG_INFO("%{public}s:%{public}d:%{public}s", __FILE__, __LINE__, __FUNCTION__);
217     Characteristic ccc(instance_->characteristics_[0].handle_);
218     ccc.value_ = BuildValue(startHandle, endHandle);
219     ccc.length_ = SERVICE_CHANGED_VALUE_LENGTH;
220 
221     for (auto& dev : devices_) {
222         if (Compat::CompatCheck(CompatType::COMPAT_GATTC_NO_SERVICE_CHANGED_IND, dev.first.addr_.GetAddress())) {
223             dev.second.isNotified = true;
224             continue;
225         }
226         dev.second.isNotified = false;
227         dev.second.startHandle_ = startHandle;
228         dev.second.endHandle_ = endHandle;
229         NotifyServiceChanged(dev.first, ccc);
230     }
231 }
232 
NotifyServiceChanged(const GattDevice & device,Characteristic & characteristic) const233 void GenericAttributeService::NotifyServiceChanged(const GattDevice& device, Characteristic& characteristic) const
234 {
235     LOG_INFO("%{public}s:%{public}d:%{public}s", __FILE__, __LINE__, __FUNCTION__);
236     serverService_.NotifyClient(device, characteristic, true);
237 }
238 
ConnectIncoming(const GattDevice & device)239 void GenericAttributeService::ConnectIncoming(const GattDevice& device)
240 {
241     LOG_INFO("%{public}s:%{public}d:%{public}s", __FILE__, __LINE__, __FUNCTION__);
242     auto dev = devices_.emplace(device, NotifyInformation());
243     if (!dev.second && !dev.first->second.isNotified) {
244         if (GattConnectionManager::GetInstance().GetEncryptionInfo(device)) {
245             Characteristic ccc(instance_->characteristics_[0].handle_);
246             ccc.value_ = BuildValue(dev.first->second.startHandle_, dev.first->second.endHandle_);
247             ccc.length_ = SERVICE_CHANGED_VALUE_LENGTH;
248 
249             NotifyServiceChanged(device, ccc);
250         } else {
251             dev.first->second.isNotified = true;
252         }
253     }
254 }
255 
Disconnected(const GattDevice & device)256 void GenericAttributeService::Disconnected(const GattDevice& device)
257 {
258     LOG_INFO("%{public}s:%{public}d:%{public}s", __FILE__, __LINE__, __FUNCTION__);
259     auto dev = devices_.find(device);
260     if (dev != devices_.end() && dev->second.isNotified) {
261         devices_.erase(device);
262     }
263 }
264 
BuildValue(uint16_t startHandle,uint16_t endHandle) const265 std::unique_ptr<uint8_t[]> GenericAttributeService::BuildValue(uint16_t startHandle, uint16_t endHandle) const
266 {
267     LOG_INFO("%{public}s:%{public}d:%{public}s", __FILE__, __LINE__, __FUNCTION__);
268     std::unique_ptr<uint8_t[]> value = std::make_unique<uint8_t[]>(SERVICE_CHANGED_VALUE_LENGTH);
269 
270     static const size_t doubleByte = 2;
271     if (memcpy_s(value.get(), SERVICE_CHANGED_VALUE_LENGTH, &startHandle, doubleByte) != EOK) {
272         LOG_ERROR("%{public}s:%{public}d:%{public}s::memcpy_s Failed!", __FILE__, __LINE__, __FUNCTION__);
273         return NULL;
274     }
275     if (memcpy_s(value.get() + doubleByte, SERVICE_CHANGED_VALUE_LENGTH - doubleByte, &endHandle, doubleByte) != EOK) {
276         LOG_ERROR("%{public}s:%{public}d:%{public}s::memcpy_s Failed!", __FILE__, __LINE__, __FUNCTION__);
277         return NULL;
278     }
279 
280     return value;
281 }
282 }  // namespace bluetooth
283 }  // namespace OHOS
284