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