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