gatt_server.cc 22 KB

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