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