1 //
2 // Copyright 2015 Google, Inc.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at:
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16
17 #include "service/gatt_server.h"
18
19 #include <base/logging.h>
20
21 #include "service/logging_helpers.h"
22 #include "stack/include/bt_types.h"
23 #include "types/raw_address.h"
24
25 using std::lock_guard;
26 using std::mutex;
27
28 namespace bluetooth {
29
30 // GattServer implementation
31
GattServer(const Uuid & uuid,int server_id)32 GattServer::GattServer(const Uuid& uuid, int server_id)
33 : app_identifier_(uuid), server_id_(server_id), delegate_(nullptr) {}
34
~GattServer()35 GattServer::~GattServer() {
36 // Automatically unregister the server.
37 VLOG(1) << "GattServer unregistering: " << server_id_;
38
39 // Unregister as observer so we no longer receive any callbacks.
40 hal::BluetoothGattInterface::Get()->RemoveServerObserver(this);
41
42 // Unregister this server, stop all services, and ignore the result.
43 // TODO(armansito): stop and remove all services here? unregister_server
44 // should really take care of that.
45 hal::BluetoothGattInterface::Get()
46 ->GetServerHALInterface()
47 ->unregister_server(server_id_);
48 }
49
SetDelegate(Delegate * delegate)50 void GattServer::SetDelegate(Delegate* delegate) {
51 lock_guard<mutex> lock(mutex_);
52 delegate_ = delegate;
53 }
54
GetAppIdentifier() const55 const Uuid& GattServer::GetAppIdentifier() const { return app_identifier_; }
56
GetInstanceId() const57 int GattServer::GetInstanceId() const { return server_id_; }
58
AddService(const bluetooth::Service & service,const ResultCallback & callback)59 bool GattServer::AddService(const bluetooth::Service& service,
60 const ResultCallback& callback) {
61 VLOG(1) << __func__ << " server_id: " << server_id_;
62 lock_guard<mutex> lock(mutex_);
63
64 if (!callback) {
65 LOG(ERROR) << "|callback| cannot be NULL";
66 return false;
67 }
68
69 std::vector<btgatt_db_element_t> svc;
70
71 svc.push_back({
72 .uuid = service.uuid(),
73 .type = (service.primary() ? BTGATT_DB_PRIMARY_SERVICE
74 : BTGATT_DB_SECONDARY_SERVICE),
75 });
76
77 for (const auto& characteristic : service.characteristics()) {
78 svc.push_back({.uuid = characteristic.uuid(),
79 .type = BTGATT_DB_CHARACTERISTIC,
80 .properties = characteristic.properties(),
81 .permissions = characteristic.permissions()});
82 for (const auto& descriptor : characteristic.descriptors())
83 svc.push_back({.uuid = descriptor.uuid(),
84 .type = BTGATT_DB_DESCRIPTOR,
85 .permissions = descriptor.permissions()});
86 }
87
88 for (const auto& incl_svc : service.included_services())
89 svc.push_back({.type = BTGATT_DB_INCLUDED_SERVICE,
90 .attribute_handle = incl_svc.handle()});
91
92 pending_end_decl_cb_ = callback;
93
94 bt_status_t status =
95 hal::BluetoothGattInterface::Get()->GetServerHALInterface()->add_service(
96 server_id_, svc.data(), svc.size());
97 if (status != BT_STATUS_SUCCESS) {
98 LOG(ERROR) << "Failed to initiate call to populate GATT service";
99 CleanUpPendingData();
100 return false;
101 }
102
103 return true;
104 }
105
SendResponse(const std::string & device_address,int request_id,GATTError error,int offset,const std::vector<uint8_t> & value)106 bool GattServer::SendResponse(const std::string& device_address, int request_id,
107 GATTError error, int offset,
108 const std::vector<uint8_t>& value) {
109 VLOG(1) << __func__ << " - server_id: " << server_id_
110 << " device_address: " << device_address
111 << " request_id: " << request_id << " error: " << error
112 << " offset: " << offset;
113 lock_guard<mutex> lock(mutex_);
114
115 RawAddress addr;
116 if (!RawAddress::FromString(device_address, addr)) {
117 LOG(ERROR) << "Invalid device address given: " << device_address;
118 return false;
119 }
120
121 if (offset < 0) {
122 LOG(ERROR) << "Offset is less than 0 offset: " << offset;
123 return false;
124 }
125
126 if (value.size() + offset > BTGATT_MAX_ATTR_LEN) {
127 LOG(ERROR) << "Value is too large";
128 return false;
129 }
130
131 // Find the correct connection ID for |device_address| and |request_id|.
132 auto iter = conn_addr_map_.find(device_address);
133 if (iter == conn_addr_map_.end()) {
134 LOG(ERROR) << "No known connections for device address: " << device_address;
135 return false;
136 }
137
138 std::shared_ptr<Connection> connection;
139 for (const auto& tmp : iter->second) {
140 if (tmp->request_id_to_handle.find(request_id) ==
141 tmp->request_id_to_handle.end())
142 continue;
143
144 connection = tmp;
145 }
146
147 if (!connection) {
148 LOG(ERROR) << "Pending request with ID " << request_id
149 << " not found for device with BD_ADDR: " << device_address;
150 return false;
151 }
152
153 btgatt_response_t response;
154 memset(&response, 0, sizeof(response));
155
156 // We keep -1 as the handle for "Execute Write Request". In that case,
157 // there is no need to populate the response data. Just send zeros back.
158 int handle = connection->request_id_to_handle[request_id];
159 response.handle = handle;
160 response.attr_value.handle = handle;
161 if (handle != -1) {
162 memcpy(response.attr_value.value, value.data(), value.size());
163 response.attr_value.offset = offset;
164 response.attr_value.len = value.size();
165 }
166
167 bt_status_t result =
168 hal::BluetoothGattInterface::Get()
169 ->GetServerHALInterface()
170 ->send_response(connection->conn_id, request_id, error, response);
171 if (result != BT_STATUS_SUCCESS) {
172 LOG(ERROR) << "Failed to initiate call to send GATT response";
173 return false;
174 }
175
176 connection->request_id_to_handle.erase(request_id);
177
178 return true;
179 }
180
SendNotification(const std::string & device_address,const uint16_t handle,bool confirm,const std::vector<uint8_t> & value,const GattCallback & callback)181 bool GattServer::SendNotification(const std::string& device_address,
182 const uint16_t handle, bool confirm,
183 const std::vector<uint8_t>& value,
184 const GattCallback& callback) {
185 VLOG(1) << " - server_id: " << server_id_
186 << " device_address: " << device_address << " confirm: " << confirm;
187 lock_guard<mutex> lock(mutex_);
188
189 RawAddress addr;
190 if (!RawAddress::FromString(device_address, addr)) {
191 LOG(ERROR) << "Invalid device address given: " << device_address;
192 return false;
193 }
194
195 // Get the connection IDs for which we will send this notification.
196 auto conn_iter = conn_addr_map_.find(device_address);
197 if (conn_iter == conn_addr_map_.end()) {
198 LOG(ERROR) << "No known connections for device with address: "
199 << device_address;
200 return false;
201 }
202
203 std::shared_ptr<PendingIndication> pending_ind(
204 new PendingIndication(callback));
205
206 // Send the notification/indication on all matching connections.
207 int send_count = 0;
208 for (const auto& conn : conn_iter->second) {
209 // Make sure that one isn't already pending for this connection.
210 if (pending_indications_.find(conn->conn_id) !=
211 pending_indications_.end()) {
212 VLOG(1) << "A" << (confirm ? "n indication" : " notification")
213 << " is already pending for connection: " << conn->conn_id;
214 continue;
215 }
216
217 // The HAL API takes char* rather const char* for |value|, so we have to
218 // cast away the const.
219 // TODO(armansito): Make HAL accept const char*.
220 bt_status_t status =
221 hal::BluetoothGattInterface::Get()
222 ->GetServerHALInterface()
223 ->send_indication(server_id_, handle, conn->conn_id, confirm,
224 value.data(), value.size());
225
226 // Increment the send count if this was successful. We don't immediately
227 // fail if the HAL returned an error. It's better to report success as long
228 // as we sent out at least one notification to this device as
229 // multi-transport GATT connections from the same BD_ADDR will be rare
230 // enough already.
231 if (status != BT_STATUS_SUCCESS) continue;
232
233 send_count++;
234 pending_indications_[conn->conn_id] = pending_ind;
235 }
236
237 if (send_count == 0) {
238 LOG(ERROR) << "Failed to send notifications/indications to device: "
239 << device_address;
240 return false;
241 }
242
243 return true;
244 }
245
ConnectionCallback(hal::BluetoothGattInterface *,int conn_id,int server_id,int connected,const RawAddress & bda)246 void GattServer::ConnectionCallback(
247 hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int server_id,
248 int connected, const RawAddress& bda) {
249 lock_guard<mutex> lock(mutex_);
250
251 if (server_id != server_id_) return;
252
253 std::string device_address = BtAddrString(&bda);
254
255 VLOG(1) << __func__ << " conn_id: " << conn_id << " connected: " << connected
256 << " BD_ADDR: " << device_address;
257
258 if (!connected) {
259 // Erase the entry if we were connected to it.
260 VLOG(1) << "No longer connected: " << device_address;
261 conn_id_map_.erase(conn_id);
262 auto iter = conn_addr_map_.find(device_address);
263 if (iter == conn_addr_map_.end()) return;
264
265 // Remove the appropriate connection objects in the address.
266 for (auto conn_iter = iter->second.begin(); conn_iter != iter->second.end();
267 ++conn_iter) {
268 if ((*conn_iter)->conn_id != conn_id) continue;
269
270 iter->second.erase(conn_iter);
271 break;
272 }
273
274 if (delegate_)
275 delegate_->OnConnectionStateChanged(this, device_address, false);
276
277 return;
278 }
279
280 if (conn_id_map_.find(conn_id) != conn_id_map_.end()) {
281 LOG(WARNING) << "Connection entry already exists; "
282 << "ignoring ConnectionCallback";
283 return;
284 }
285
286 LOG(INFO) << "Added connection entry for conn_id: " << conn_id
287 << " device address: " << device_address;
288 std::shared_ptr<Connection> connection(new Connection(conn_id, bda));
289 conn_id_map_[conn_id] = connection;
290 conn_addr_map_[device_address].push_back(connection);
291
292 if (delegate_)
293 delegate_->OnConnectionStateChanged(this, device_address, true);
294 }
295
ServiceAddedCallback(hal::BluetoothGattInterface * gatt_iface,int status,int server_id,std::vector<btgatt_db_element_t> svc)296 void GattServer::ServiceAddedCallback(hal::BluetoothGattInterface* gatt_iface,
297 int status, int server_id,
298 std::vector<btgatt_db_element_t> svc) {
299 lock_guard<mutex> lock(mutex_);
300
301 if (server_id != server_id_) return;
302
303 VLOG(1) << __func__ << " - status: " << status << " server_id: " << server_id
304 << " first handle: " << svc[0].attribute_handle
305 << " service Uuid: " << Uuid(svc[0].uuid).ToString()
306 << " count: " << svc.size();
307
308 Service service(svc[0].attribute_handle, true, Uuid(svc[0].uuid), {}, {});
309
310 for (size_t i = 1; i < svc.size(); i++) {
311 const btgatt_db_element_t& curr = svc[i];
312 VLOG(1) << " - processing item no: " << i
313 << " handle: " << curr.attribute_handle;
314 if (curr.type == BTGATT_DB_CHARACTERISTIC) {
315 service.characteristics().push_back({curr.attribute_handle,
316 Uuid(curr.uuid),
317 curr.properties,
318 curr.permissions,
319 {}});
320 } else if (curr.type == BTGATT_DB_DESCRIPTOR) {
321 service.characteristics().back().descriptors().push_back(
322 {curr.attribute_handle, Uuid(curr.uuid), curr.permissions});
323 } else if (svc[i].type == BTGATT_DB_INCLUDED_SERVICE) {
324 }
325 }
326
327 pending_end_decl_cb_((bluetooth::BLEStatus)status, service);
328
329 CleanUpPendingData();
330 }
331
ServiceStoppedCallback(hal::BluetoothGattInterface *,int,int,int)332 void GattServer::ServiceStoppedCallback(
333 hal::BluetoothGattInterface* /* gatt_iface */, int /* status */,
334 int /* server_id */, int /* service_handle */) {
335 // TODO(armansito): Support stopping a service.
336 }
337
RequestReadCharacteristicCallback(hal::BluetoothGattInterface *,int conn_id,int trans_id,const RawAddress & bda,int attribute_handle,int offset,bool is_long)338 void GattServer::RequestReadCharacteristicCallback(
339 hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int trans_id,
340 const RawAddress& bda, int attribute_handle, int offset, bool is_long) {
341 lock_guard<mutex> lock(mutex_);
342
343 // Check to see if we know about this connection. Otherwise ignore the
344 // request.
345 auto conn = GetConnection(conn_id, bda, trans_id);
346 if (!conn) return;
347
348 std::string device_address = BtAddrString(&bda);
349
350 VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
351 << " BD_ADDR: " << device_address
352 << " attribute_handle: " << attribute_handle << " offset: " << offset
353 << " is_long: " << is_long;
354
355 conn->request_id_to_handle[trans_id] = attribute_handle;
356
357 // If there is no delegate then there is nobody to handle request. The request
358 // will eventually timeout and we should get a connection update that
359 // terminates the connection.
360 if (!delegate_) {
361 // TODO(armansito): Require a delegate at server registration so that this
362 // is never possible.
363 LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request "
364 << "will time out.";
365 return;
366 }
367
368 delegate_->OnCharacteristicReadRequest(this, device_address, trans_id, offset,
369 is_long, attribute_handle);
370 }
RequestReadDescriptorCallback(hal::BluetoothGattInterface *,int conn_id,int trans_id,const RawAddress & bda,int attribute_handle,int offset,bool is_long)371 void GattServer::RequestReadDescriptorCallback(
372 hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int trans_id,
373 const RawAddress& bda, int attribute_handle, int offset, bool is_long) {
374 lock_guard<mutex> lock(mutex_);
375
376 // Check to see if we know about this connection. Otherwise ignore the
377 // request.
378 auto conn = GetConnection(conn_id, bda, trans_id);
379 if (!conn) return;
380
381 std::string device_address = BtAddrString(&bda);
382
383 VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
384 << " BD_ADDR: " << device_address
385 << " attribute_handle: " << attribute_handle << " offset: " << offset
386 << " is_long: " << is_long;
387
388 conn->request_id_to_handle[trans_id] = attribute_handle;
389
390 // If there is no delegate then there is nobody to handle request. The request
391 // will eventually timeout and we should get a connection update that
392 // terminates the connection.
393 if (!delegate_) {
394 // TODO(armansito): Require a delegate at server registration so that this
395 // is never possible.
396 LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request "
397 << "will time out.";
398 return;
399 }
400
401 delegate_->OnDescriptorReadRequest(this, device_address, trans_id, offset,
402 is_long, attribute_handle);
403 }
404
RequestWriteCharacteristicCallback(hal::BluetoothGattInterface *,int conn_id,int trans_id,const RawAddress & bda,int attr_handle,int offset,bool need_rsp,bool is_prep,std::vector<uint8_t> value)405 void GattServer::RequestWriteCharacteristicCallback(
406 hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int trans_id,
407 const RawAddress& bda, int attr_handle, int offset, bool need_rsp,
408 bool is_prep, std::vector<uint8_t> value) {
409 lock_guard<mutex> lock(mutex_);
410
411 // Check to see if we know about this connection. Otherwise ignore the
412 // request.
413 auto conn = GetConnection(conn_id, bda, trans_id);
414 if (!conn) return;
415
416 std::string device_address = BtAddrString(&bda);
417
418 VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
419 << " BD_ADDR: " << device_address << " attr_handle: " << attr_handle
420 << " offset: " << offset << " length: " << value.size()
421 << " need_rsp: " << need_rsp << " is_prep: " << is_prep;
422
423 // Store the request ID only if this is not a write-without-response. If
424 // another request occurs after this with the same request ID, then we'll
425 // simply process it normally, though that shouldn't ever happen.
426 if (need_rsp) conn->request_id_to_handle[trans_id] = attr_handle;
427
428 // If there is no delegate then there is nobody to handle request. The request
429 // will eventually timeout and we should get a connection update that
430 // terminates the connection.
431 if (!delegate_) {
432 // TODO(armansito): Require a delegate at server registration so that this
433 // is never possible.
434 LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request "
435 << "will time out.";
436 return;
437 }
438
439 delegate_->OnCharacteristicWriteRequest(this, device_address, trans_id,
440 offset, is_prep, need_rsp,
441 std::move(value), attr_handle);
442 }
443
RequestWriteDescriptorCallback(hal::BluetoothGattInterface *,int conn_id,int trans_id,const RawAddress & bda,int attr_handle,int offset,bool need_rsp,bool is_prep,std::vector<uint8_t> value)444 void GattServer::RequestWriteDescriptorCallback(
445 hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int trans_id,
446 const RawAddress& bda, int attr_handle, int offset, bool need_rsp,
447 bool is_prep, std::vector<uint8_t> value) {
448 lock_guard<mutex> lock(mutex_);
449
450 // Check to see if we know about this connection. Otherwise ignore the
451 // request.
452 auto conn = GetConnection(conn_id, bda, trans_id);
453 if (!conn) return;
454
455 std::string device_address = BtAddrString(&bda);
456
457 VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
458 << " BD_ADDR: " << device_address << " attr_handle: " << attr_handle
459 << " offset: " << offset << " length: " << value.size()
460 << " need_rsp: " << need_rsp << " is_prep: " << is_prep;
461
462 // Store the request ID only if this is not a write-without-response. If
463 // another request occurs after this with the same request ID, then we'll
464 // simply process it normally, though that shouldn't ever happen.
465 if (need_rsp) conn->request_id_to_handle[trans_id] = attr_handle;
466
467 // If there is no delegate then there is nobody to handle request. The request
468 // will eventually timeout and we should get a connection update that
469 // terminates the connection.
470 if (!delegate_) {
471 // TODO(armansito): Require a delegate at server registration so that this
472 // is never possible.
473 LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request "
474 << "will time out.";
475 return;
476 }
477
478 delegate_->OnDescriptorWriteRequest(this, device_address, trans_id, offset,
479 is_prep, need_rsp, std::move(value),
480 attr_handle);
481 }
482
RequestExecWriteCallback(hal::BluetoothGattInterface *,int conn_id,int trans_id,const RawAddress & bda,int exec_write)483 void GattServer::RequestExecWriteCallback(
484 hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int trans_id,
485 const RawAddress& bda, int exec_write) {
486 lock_guard<mutex> lock(mutex_);
487
488 // Check to see if we know about this connection. Otherwise ignore the
489 // request.
490 auto conn = GetConnection(conn_id, bda, trans_id);
491 if (!conn) return;
492
493 std::string device_address = BtAddrString(&bda);
494
495 VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
496 << " BD_ADDR: " << device_address << " exec_write: " << exec_write;
497
498 // Just store a dummy invalid handle as this request doesn't apply to a
499 // specific handle.
500 conn->request_id_to_handle[trans_id] = -1;
501
502 // If there is no delegate then there is nobody to handle request. The request
503 // will eventually timeout and we should get a connection update that
504 // terminates the connection.
505 if (!delegate_) {
506 // TODO(armansito): Require a delegate at server registration so that this
507 // is never possible.
508 LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request "
509 << "will time out.";
510 return;
511 }
512
513 delegate_->OnExecuteWriteRequest(this, device_address, trans_id, exec_write);
514 }
515
IndicationSentCallback(hal::BluetoothGattInterface *,int conn_id,int status)516 void GattServer::IndicationSentCallback(
517 hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int status) {
518 VLOG(1) << __func__ << " conn_id: " << conn_id << " status: " << status;
519 lock_guard<mutex> lock(mutex_);
520
521 const auto& pending_ind_iter = pending_indications_.find(conn_id);
522 if (pending_ind_iter == pending_indications_.end()) {
523 VLOG(1) << "Unknown connection: " << conn_id;
524 return;
525 }
526
527 std::shared_ptr<PendingIndication> pending_ind = pending_ind_iter->second;
528 pending_indications_.erase(pending_ind_iter);
529
530 if (status == BT_STATUS_SUCCESS) pending_ind->has_success = true;
531
532 // Invoke it if this was the last reference to the confirmation callback.
533 if (pending_ind.unique() && pending_ind->callback) {
534 pending_ind->callback(pending_ind->has_success
535 ? GATT_ERROR_NONE
536 : static_cast<GATTError>(status));
537 }
538 }
539
CleanUpPendingData()540 void GattServer::CleanUpPendingData() {
541 pending_end_decl_cb_ = ResultCallback();
542 }
543
GetConnection(int conn_id,const RawAddress & bda,int request_id)544 std::shared_ptr<GattServer::Connection> GattServer::GetConnection(
545 int conn_id, const RawAddress& bda, int request_id) {
546 auto iter = conn_id_map_.find(conn_id);
547 if (iter == conn_id_map_.end()) {
548 VLOG(1) << "Connection doesn't belong to this server";
549 return nullptr;
550 }
551
552 auto conn = iter->second;
553 if (conn->bdaddr != bda) {
554 LOG(WARNING) << "BD_ADDR: " << BtAddrString(&bda) << " doesn't match "
555 << "connection ID: " << conn_id;
556 return nullptr;
557 }
558
559 if (conn->request_id_to_handle.find(request_id) !=
560 conn->request_id_to_handle.end()) {
561 VLOG(1) << "Request with ID: " << request_id << " already exists for "
562 << " connection: " << conn_id;
563 return nullptr;
564 }
565
566 return conn;
567 }
568
569 // GattServerFactory implementation
570
GattServerFactory()571 GattServerFactory::GattServerFactory() {
572 hal::BluetoothGattInterface::Get()->AddServerObserver(this);
573 }
574
~GattServerFactory()575 GattServerFactory::~GattServerFactory() {
576 hal::BluetoothGattInterface::Get()->RemoveServerObserver(this);
577 }
578
RegisterInstance(const Uuid & uuid,const RegisterCallback & callback)579 bool GattServerFactory::RegisterInstance(const Uuid& uuid,
580 const RegisterCallback& callback) {
581 VLOG(1) << __func__ << " - Uuid: " << uuid.ToString();
582 lock_guard<mutex> lock(pending_calls_lock_);
583
584 if (pending_calls_.find(uuid) != pending_calls_.end()) {
585 LOG(ERROR) << "GATT-server client with given Uuid already being registered "
586 << " - Uuid: " << uuid.ToString();
587 return false;
588 }
589
590 const btgatt_server_interface_t* hal_iface =
591 hal::BluetoothGattInterface::Get()->GetServerHALInterface();
592
593 if (hal_iface->register_server(uuid, false) != BT_STATUS_SUCCESS)
594 return false;
595
596 pending_calls_[uuid] = callback;
597
598 return true;
599 }
600
RegisterServerCallback(hal::BluetoothGattInterface * gatt_iface,int status,int server_id,const Uuid & app_uuid)601 void GattServerFactory::RegisterServerCallback(
602 hal::BluetoothGattInterface* gatt_iface, int status, int server_id,
603 const Uuid& app_uuid) {
604 Uuid uuid(app_uuid);
605
606 VLOG(1) << __func__ << " - Uuid: " << uuid.ToString();
607 lock_guard<mutex> lock(pending_calls_lock_);
608
609 auto iter = pending_calls_.find(uuid);
610 if (iter == pending_calls_.end()) {
611 VLOG(1) << "Ignoring callback for unknown app_id: " << uuid.ToString();
612 return;
613 }
614
615 // No need to construct a server if the call wasn't successful.
616 std::unique_ptr<GattServer> server;
617 BLEStatus result = BLE_STATUS_FAILURE;
618 if (status == BT_STATUS_SUCCESS) {
619 server.reset(new GattServer(uuid, server_id));
620
621 gatt_iface->AddServerObserver(server.get());
622
623 result = BLE_STATUS_SUCCESS;
624 }
625
626 // Notify the result via the result callback.
627 iter->second(result, uuid, std::move(server));
628
629 pending_calls_.erase(iter);
630 }
631
632 } // namespace bluetooth
633