OSDN Git Service

[automerger skipped] DO NOT MERGE: btif: require pairing dialog for JustWorks SSP...
[android-x86/system-bt.git] / service / gatt_server_old.cc
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 #define LOG_TAG "bt_gatts"
18
19 #include "gatt_server_old.h"
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <unistd.h>
24
25 #include <base/bind.h>
26 #include <base/bind_helpers.h>
27 #include <base/callback.h>
28 #include <algorithm>
29 #include <array>
30 #include <condition_variable>
31 #include <map>
32 #include <memory>
33 #include <mutex>
34 #include <set>
35 #include <string>
36 #include <unordered_map>
37 #include <unordered_set>
38 #include <vector>
39
40 #include <hardware/bluetooth.h>
41 #include <hardware/bt_gatt.h>
42
43 #include "service/hal/bluetooth_interface.h"
44 #include "service/logging_helpers.h"
45
46 #include "osi/include/log.h"
47 #include "osi/include/osi.h"
48
49 namespace {
50
51 const size_t kMaxGattAttributeSize = 512;
52 std::vector<btgatt_db_element_t> pending_svc_decl;
53 std::unordered_set<int> blob_index;
54
55 // TODO(icoolidge): Support multiple instances
56 // TODO(armansito): Remove this variable. No point of having this if
57 // each bluetooth::gatt::Server instance already keeps a pointer to the
58 // ServerInternals that is associated with it (which is much cleaner). It looks
59 // like this variable exists because the btif callbacks don't allow the
60 // upper-layer to pass user data to them. We could:
61 //
62 //    1. Fix the btif callbacks so that some sort of continuation can be
63 //    attached to a callback. This might be a long shot since the callback
64 //    interface doesn't allow more than one caller to register its own callbacks
65 //    (which might be what we want though, since this would make the API more
66 //    flexible).
67 //
68 //    2. Allow creation of Server objects using a factory method that returns
69 //    the result asynchronously in a base::Callback. The RegisterServerCallback
70 //    provides an |app_uuid|, which can be used to store callback structures in
71 //    a map and lazily instantiate the Server and invoke the correct callback.
72 //    This is a general pattern that we should use throughout the daemon, since
73 //    all operations can timeout or fail and this is best reported in an
74 //    asynchronous base::Callback.
75 //
76 static bluetooth::gatt::ServerInternals* g_internal = nullptr;
77
78 enum { kPipeReadEnd = 0, kPipeWriteEnd = 1, kPipeNumEnds = 2 };
79
80 }  // namespace
81
82 namespace bluetooth {
83 namespace gatt {
84
85 struct Characteristic {
86   Uuid uuid;
87   int blob_section;
88   std::vector<uint8_t> blob;
89
90   // Support synchronized blob updates by latching under mutex.
91   std::vector<uint8_t> next_blob;
92   bool next_blob_pending;
93   bool notify;
94 };
95
96 struct ServerInternals {
97   ServerInternals();
98   ~ServerInternals();
99   int Initialize();
100   bt_status_t AddCharacteristic(const Uuid& uuid, uint8_t properties,
101                                 uint16_t permissions);
102
103   // This maps API attribute Uuids to BlueDroid handles.
104   std::map<Uuid, int> uuid_to_attribute;
105
106   // The attribute cache, indexed by BlueDroid handles.
107   std::unordered_map<int, Characteristic> characteristics;
108
109   // Associate a control attribute with its value attribute.
110   std::unordered_map<int, int> controlled_blobs;
111
112   ScanResults scan_results;
113
114   Uuid last_write;
115   const btgatt_interface_t* gatt;
116   int server_if;
117   int client_if;
118   int service_handle;
119   std::set<int> connections;
120
121   std::mutex lock;
122   std::condition_variable api_synchronize;
123   int pipefd[kPipeNumEnds];
124 };
125
126 }  // namespace gatt
127 }  // namespace bluetooth
128
129 namespace {
130
131 /** Callback invoked in response to register_server */
132 void RegisterServerCallback(int status, int server_if,
133                             const bluetooth::Uuid& app_uuid) {
134   LOG_INFO(LOG_TAG, "%s: status:%d server_if:%d app_uuid:%p", __func__, status,
135            server_if, &app_uuid);
136
137   g_internal->server_if = server_if;
138
139   pending_svc_decl.push_back(
140       {.type = BTGATT_DB_PRIMARY_SERVICE, .uuid = app_uuid});
141 }
142
143 void ServiceAddedCallback(int status, int server_if,
144                           std::vector<btgatt_db_element_t> service) {
145   LOG_INFO(LOG_TAG, "%s: status:%d server_if:%d count:%zu svc_handle:%d",
146            __func__, status, server_if, service.size(),
147            service[0].attribute_handle);
148
149   std::lock_guard<std::mutex> lock(g_internal->lock);
150   g_internal->server_if = server_if;
151
152   g_internal->service_handle = service[0].attribute_handle;
153
154   uint16_t prev_char_handle = 0;
155   uint16_t prev_char_properties = 0;
156   for (size_t i = 1; i < service.size(); i++) {
157     const btgatt_db_element_t& el = service[i];
158     if (el.type == BTGATT_DB_DESCRIPTOR) {
159       LOG_INFO(LOG_TAG, "%s: descr_handle:%d", __func__, el.attribute_handle);
160     } else if (el.type == BTGATT_DB_CHARACTERISTIC) {
161       bluetooth::Uuid id(el.uuid);
162       uint16_t char_handle = el.attribute_handle;
163
164       LOG_INFO(LOG_TAG, "%s: char_handle:%d", __func__, char_handle);
165
166       g_internal->uuid_to_attribute[id] = char_handle;
167       g_internal->characteristics[char_handle].uuid = id;
168       g_internal->characteristics[char_handle].blob_section = 0;
169
170       // If the added characteristic is blob
171       if (blob_index.find(i) != blob_index.end()) {
172         // Finally, associate the control attribute with the value attribute.
173         // Also, initialize the control attribute to a readable zero.
174         const uint16_t control_attribute = char_handle;
175         const uint16_t blob_attribute = prev_char_handle;
176         g_internal->controlled_blobs[control_attribute] = blob_attribute;
177         g_internal->characteristics[blob_attribute].notify =
178             prev_char_properties & bluetooth::gatt::kPropertyNotify;
179
180         bluetooth::gatt::Characteristic& ctrl =
181             g_internal->characteristics[control_attribute];
182         ctrl.next_blob.clear();
183         ctrl.next_blob.push_back(0);
184         ctrl.next_blob_pending = true;
185         ctrl.blob_section = 0;
186         ctrl.notify = false;
187       }
188       prev_char_handle = char_handle;
189       prev_char_properties = el.properties;
190     }
191   }
192
193   pending_svc_decl.clear();
194   blob_index.clear();
195
196   // The Uuid provided here is unimportant, and is only used to satisfy
197   // BlueDroid.
198   // It must be different than any other registered Uuid.
199   bluetooth::Uuid client_id = bluetooth::Uuid::GetRandom();
200
201   bt_status_t btstat = g_internal->gatt->client->register_client(client_id);
202   if (btstat != BT_STATUS_SUCCESS) {
203     LOG_ERROR(LOG_TAG, "%s: Failed to register client", __func__);
204   }
205 }
206
207 void RequestReadCallback(int conn_id, int trans_id, const RawAddress& bda,
208                          int attr_handle, int attribute_offset_octets,
209                          bool is_long) {
210   std::lock_guard<std::mutex> lock(g_internal->lock);
211
212   bluetooth::gatt::Characteristic& ch =
213       g_internal->characteristics[attr_handle];
214
215   // Latch next_blob to blob on a 'fresh' read.
216   if (ch.next_blob_pending && attribute_offset_octets == 0 &&
217       ch.blob_section == 0) {
218     std::swap(ch.blob, ch.next_blob);
219     ch.next_blob_pending = false;
220   }
221
222   const size_t blob_offset_octets =
223       std::min(ch.blob.size(), ch.blob_section * kMaxGattAttributeSize);
224   const size_t blob_remaining = ch.blob.size() - blob_offset_octets;
225   const size_t attribute_size = std::min(kMaxGattAttributeSize, blob_remaining);
226
227   std::string addr(BtAddrString(&bda));
228   LOG_INFO(LOG_TAG,
229            "%s: connection:%d (%s) reading attr:%d attribute_offset_octets:%d "
230            "blob_section:%u (is_long:%u)",
231            __func__, conn_id, addr.c_str(), attr_handle,
232            attribute_offset_octets, ch.blob_section, is_long);
233
234   btgatt_response_t response;
235   response.attr_value.len = 0;
236
237   if (attribute_offset_octets < static_cast<int>(attribute_size)) {
238     std::copy(ch.blob.begin() + blob_offset_octets + attribute_offset_octets,
239               ch.blob.begin() + blob_offset_octets + attribute_size,
240               response.attr_value.value);
241     response.attr_value.len = attribute_size - attribute_offset_octets;
242   }
243
244   response.attr_value.handle = attr_handle;
245   response.attr_value.offset = attribute_offset_octets;
246   response.attr_value.auth_req = 0;
247   g_internal->gatt->server->send_response(conn_id, trans_id, 0, response);
248 }
249
250 void RequestWriteCallback(int conn_id, int trans_id, const RawAddress& bda,
251                           int attr_handle, int attribute_offset, bool need_rsp,
252                           bool is_prep, std::vector<uint8_t> value) {
253   std::string addr(BtAddrString(&bda));
254   LOG_INFO(LOG_TAG,
255            "%s: connection:%d (%s:trans:%d) write attr:%d attribute_offset:%d "
256            "length:%zu "
257            "need_resp:%u is_prep:%u",
258            __func__, conn_id, addr.c_str(), trans_id, attr_handle,
259            attribute_offset, value.size(), need_rsp, is_prep);
260
261   std::lock_guard<std::mutex> lock(g_internal->lock);
262
263   bluetooth::gatt::Characteristic& ch =
264       g_internal->characteristics[attr_handle];
265
266   ch.blob.resize(attribute_offset + value.size());
267
268   std::copy(value.begin(), value.end(), ch.blob.begin() + attribute_offset);
269
270   auto target_blob = g_internal->controlled_blobs.find(attr_handle);
271   // If this is a control attribute, adjust offset of the target blob.
272   if (target_blob != g_internal->controlled_blobs.end() &&
273       ch.blob.size() == 1u) {
274     g_internal->characteristics[target_blob->second].blob_section = ch.blob[0];
275     LOG_INFO(LOG_TAG, "%s: updating attribute %d blob_section to %u", __func__,
276              target_blob->second, ch.blob[0]);
277   } else if (!is_prep) {
278     // This is a single frame characteristic write.
279     // Notify upwards because we're done now.
280     const bluetooth::Uuid::UUID128Bit& attr_uuid = ch.uuid.To128BitBE();
281     ssize_t status;
282     OSI_NO_INTR(status = write(g_internal->pipefd[kPipeWriteEnd],
283                                attr_uuid.data(), attr_uuid.size()));
284     if (-1 == status)
285       LOG_ERROR(LOG_TAG, "%s: write failed: %s", __func__, strerror(errno));
286   } else {
287     // This is a multi-frame characteristic write.
288     // Wait for an 'RequestExecWriteCallback' to notify completion.
289     g_internal->last_write = ch.uuid;
290   }
291
292   // Respond only if needed.
293   if (!need_rsp) return;
294
295   btgatt_response_t response;
296   response.attr_value.handle = attr_handle;
297   response.attr_value.offset = attribute_offset;
298   response.attr_value.len = value.size();
299   response.attr_value.auth_req = 0;
300   // Provide written data back to sender for the response.
301   // Remote stacks use this to validate the success of the write.
302   std::copy(value.begin(), value.end(), response.attr_value.value);
303   g_internal->gatt->server->send_response(conn_id, trans_id, 0, response);
304 }
305
306 void RequestExecWriteCallback(int conn_id, int trans_id, const RawAddress& bda,
307                               int exec_write) {
308   std::string addr(BtAddrString(&bda));
309   LOG_INFO(LOG_TAG, "%s: connection:%d (%s:trans:%d) exec_write:%d", __func__,
310            conn_id, addr.c_str(), trans_id, exec_write);
311
312   // This 'response' data is unused for ExecWriteResponses.
313   // It is only used to pass BlueDroid argument validation.
314   btgatt_response_t response = {};
315   g_internal->gatt->server->send_response(conn_id, trans_id, 0, response);
316
317   if (!exec_write) return;
318
319   std::lock_guard<std::mutex> lock(g_internal->lock);
320   // Communicate the attribute Uuid as notification of a write update.
321   const bluetooth::Uuid::UUID128Bit uuid = g_internal->last_write.To128BitBE();
322   ssize_t status;
323   OSI_NO_INTR(status = write(g_internal->pipefd[kPipeWriteEnd], uuid.data(),
324                              uuid.size()));
325   if (-1 == status)
326     LOG_ERROR(LOG_TAG, "%s: write failed: %s", __func__, strerror(errno));
327 }
328
329 void ConnectionCallback(int conn_id, int server_if, int connected,
330                         const RawAddress& bda) {
331   std::string addr(BtAddrString(&bda));
332   LOG_INFO(LOG_TAG, "%s: connection:%d server_if:%d connected:%d addr:%s",
333            __func__, conn_id, server_if, connected, addr.c_str());
334   if (connected == 1) {
335     g_internal->connections.insert(conn_id);
336   } else if (connected == 0) {
337     g_internal->connections.erase(conn_id);
338   }
339 }
340
341 void EnableAdvertisingCallback(uint8_t status) {
342   LOG_INFO(LOG_TAG, "%s: status:%d", __func__, status);
343   // This terminates a Start call.
344   std::lock_guard<std::mutex> lock(g_internal->lock);
345   g_internal->api_synchronize.notify_one();
346 }
347
348 void RegisterClientCallback(int status, int client_if,
349                             const bluetooth::Uuid& app_uuid) {
350   LOG_INFO(LOG_TAG, "%s: status:%d client_if:%d uuid[0]:%s", __func__, status,
351            client_if, app_uuid.ToString().c_str());
352   g_internal->client_if = client_if;
353
354   // Setup our advertisement. This has no callback.
355   g_internal->gatt->advertiser->SetData(0 /* std_inst */, false,
356                                         {/*TODO: put inverval 2,2 here*/},
357                                         base::DoNothing());
358
359   g_internal->gatt->advertiser->Enable(
360       0 /* std_inst */, true, base::Bind(&EnableAdvertisingCallback),
361       0 /* no duration */, 0 /* no maxExtAdvEvent*/, base::DoNothing());
362 }
363
364 void ServiceStoppedCallback(int status, int server_if, int srvc_handle) {
365   LOG_INFO(LOG_TAG, "%s: status:%d server_if:%d srvc_handle:%d", __func__,
366            status, server_if, srvc_handle);
367   // This terminates a Stop call.
368   // TODO(icoolidge): make this symmetric with start
369   std::lock_guard<std::mutex> lock(g_internal->lock);
370   g_internal->api_synchronize.notify_one();
371 }
372
373 void ScanResultCallback(uint16_t ble_evt_type, uint8_t addr_type,
374                         RawAddress* bda, uint8_t ble_primary_phy,
375                         uint8_t ble_secondary_phy, uint8_t ble_advertising_sid,
376                         int8_t ble_tx_power, int8_t rssi,
377                         uint16_t ble_periodic_adv_int,
378                         std::vector<uint8_t> adv_data) {
379   std::string addr(BtAddrString(bda));
380   std::lock_guard<std::mutex> lock(g_internal->lock);
381   g_internal->scan_results[addr] = rssi;
382 }
383
384 void ClientConnectCallback(int conn_id, int status, int client_if,
385                            const RawAddress& bda) {
386   std::string addr(BtAddrString(&bda));
387   LOG_INFO(LOG_TAG, "%s: conn_id:%d status:%d client_if:%d %s", __func__,
388            conn_id, status, client_if, addr.c_str());
389 }
390
391 void ClientDisconnectCallback(int conn_id, int status, int client_if,
392                               const RawAddress& bda) {
393   std::string addr(BtAddrString(&bda));
394   LOG_INFO(LOG_TAG, "%s: conn_id:%d status:%d client_if:%d %s", __func__,
395            conn_id, status, client_if, addr.c_str());
396 }
397
398 void IndicationSentCallback(UNUSED_ATTR int conn_id, UNUSED_ATTR int status) {
399   // TODO(icoolidge): what to do
400 }
401
402 void ResponseConfirmationCallback(UNUSED_ATTR int status,
403                                   UNUSED_ATTR int handle) {
404   // TODO(icoolidge): what to do
405 }
406
407 const btgatt_server_callbacks_t gatt_server_callbacks = {
408     RegisterServerCallback,
409     ConnectionCallback,
410     ServiceAddedCallback,
411     ServiceStoppedCallback,
412     nullptr, /* service_deleted_cb */
413     RequestReadCallback,
414     RequestReadCallback,
415     RequestWriteCallback,
416     RequestWriteCallback,
417     RequestExecWriteCallback,
418     ResponseConfirmationCallback,
419     IndicationSentCallback,
420     nullptr, /* congestion_cb*/
421     nullptr, /* mtu_changed_cb */
422     nullptr, /* phy_update_cb */
423     nullptr, /* conn_update_cb */
424 };
425
426 // TODO(eisenbach): Refactor GATT interface to not require servers
427 // to refer to the client interface.
428 const btgatt_client_callbacks_t gatt_client_callbacks = {
429     RegisterClientCallback,
430     ClientConnectCallback,
431     ClientDisconnectCallback,
432     nullptr, /* search_complete_cb; */
433     nullptr, /* register_for_notification_cb; */
434     nullptr, /* notify_cb; */
435     nullptr, /* read_characteristic_cb; */
436     nullptr, /* write_characteristic_cb; */
437     nullptr, /* read_descriptor_cb; */
438     nullptr, /* write_descriptor_cb; */
439     nullptr, /* execute_write_cb; */
440     nullptr, /* read_remote_rssi_cb; */
441     nullptr, /* configure_mtu_cb; */
442     nullptr, /* congestion_cb; */
443     nullptr, /* get_gatt_db_cb; */
444     nullptr, /* services_removed_cb */
445     nullptr, /* services_added_cb */
446     nullptr, /* phy_update_cb */
447     nullptr, /* conn_update_cb */
448 };
449
450 const btgatt_scanner_callbacks_t gatt_scanner_callbacks = {
451     ScanResultCallback,
452     nullptr, /* batchscan_reports_cb; */
453     nullptr, /* batchscan_threshold_cb; */
454     nullptr, /* track_adv_event_cb; */
455 };
456
457 const btgatt_callbacks_t gatt_callbacks = {
458     /** Set to sizeof(btgatt_callbacks_t) */
459     sizeof(btgatt_callbacks_t),
460
461     /** GATT Client callbacks */
462     &gatt_client_callbacks,
463
464     /** GATT Server callbacks */
465     &gatt_server_callbacks,
466
467     /** GATT Server callbacks */
468     &gatt_scanner_callbacks,
469 };
470
471 }  // namespace
472
473 namespace bluetooth {
474 namespace gatt {
475
476 int ServerInternals::Initialize() {
477   // Get the interface to the GATT profile.
478   const bt_interface_t* bt_iface =
479       hal::BluetoothInterface::Get()->GetHALInterface();
480   gatt = reinterpret_cast<const btgatt_interface_t*>(
481       bt_iface->get_profile_interface(BT_PROFILE_GATT_ID));
482   if (!gatt) {
483     LOG_ERROR(LOG_TAG, "Error getting GATT interface");
484     return -1;
485   }
486
487   bt_status_t btstat = gatt->init(&gatt_callbacks);
488   if (btstat != BT_STATUS_SUCCESS) {
489     LOG_ERROR(LOG_TAG, "Failed to initialize gatt interface");
490     return -1;
491   }
492
493   int status = pipe(pipefd);
494   if (status == -1) {
495     LOG_ERROR(LOG_TAG, "pipe creation failed: %s", strerror(errno));
496     return -1;
497   }
498
499   return 0;
500 }
501
502 bt_status_t ServerInternals::AddCharacteristic(const Uuid& uuid,
503                                                uint8_t properties,
504                                                uint16_t permissions) {
505   pending_svc_decl.push_back({.type = BTGATT_DB_CHARACTERISTIC,
506                               .uuid = uuid,
507                               .properties = properties,
508                               .permissions = permissions});
509   return BT_STATUS_SUCCESS;
510 }
511
512 ServerInternals::ServerInternals()
513     : gatt(nullptr),
514       server_if(0),
515       client_if(0),
516       service_handle(0),
517       pipefd{INVALID_FD, INVALID_FD} {}
518
519 ServerInternals::~ServerInternals() {
520   if (pipefd[0] != INVALID_FD) close(pipefd[0]);
521   if (pipefd[1] != INVALID_FD) close(pipefd[1]);
522
523   gatt->server->delete_service(server_if, service_handle);
524   gatt->server->unregister_server(server_if);
525   gatt->client->unregister_client(client_if);
526 }
527
528 Server::Server() : internal_(nullptr) {}
529
530 Server::~Server() {}
531
532 bool Server::Initialize(const Uuid& service_id, int* gatt_pipe) {
533   internal_.reset(new ServerInternals);
534   if (!internal_) {
535     LOG_ERROR(LOG_TAG, "Error creating internals");
536     return false;
537   }
538   g_internal = internal_.get();
539
540   std::unique_lock<std::mutex> lock(internal_->lock);
541   int status = internal_->Initialize();
542   if (status) {
543     LOG_ERROR(LOG_TAG, "Error initializing internals");
544     return false;
545   }
546
547   bt_status_t btstat = internal_->gatt->server->register_server(service_id);
548   if (btstat != BT_STATUS_SUCCESS) {
549     LOG_ERROR(LOG_TAG, "Failed to register server");
550     return false;
551   }
552
553   internal_->api_synchronize.wait(lock);
554   // TODO(icoolidge): Better error handling.
555   if (internal_->server_if == 0) {
556     LOG_ERROR(LOG_TAG, "Initialization of server failed");
557     return false;
558   }
559
560   *gatt_pipe = internal_->pipefd[kPipeReadEnd];
561   LOG_INFO(LOG_TAG, "Server Initialize succeeded");
562   return true;
563 }
564
565 bool Server::SetAdvertisement(const std::vector<Uuid>& ids,
566                               const std::vector<uint8_t>& service_data,
567                               const std::vector<uint8_t>& manufacturer_data,
568                               bool transmit_name) {
569   // std::vector<uint8_t> id_data;
570   // const auto& mutable_manufacturer_data = manufacturer_data;
571   // const auto& mutable_service_data = service_data;
572
573   // for (const Uuid &id : ids) {
574   //   const auto le_id = id.To128BitLE();
575   //   id_data.insert(id_data.end(), le_id.begin(), le_id.end());
576   // }
577
578   std::lock_guard<std::mutex> lock(internal_->lock);
579
580   // Setup our advertisement. This has no callback.
581   internal_->gatt->advertiser->SetData(0, false, /* beacon, not scan response */
582                                        {}, base::DoNothing());
583   // transmit_name,               /* name */
584   // 2, 2,                         interval
585   // mutable_manufacturer_data,
586   // mutable_service_data,
587   // id_data);
588   return true;
589 }
590
591 bool Server::SetScanResponse(const std::vector<Uuid>& ids,
592                              const std::vector<uint8_t>& service_data,
593                              const std::vector<uint8_t>& manufacturer_data,
594                              bool transmit_name) {
595   // std::vector<uint8_t> id_data;
596   // const auto& mutable_manufacturer_data = manufacturer_data;
597   // const auto& mutable_service_data = service_data;
598
599   // for (const Uuid &id : ids) {
600   //   const auto le_id = id.To128BitLE();
601   //   id_data.insert(id_data.end(), le_id.begin(), le_id.end());
602   // }
603
604   std::lock_guard<std::mutex> lock(internal_->lock);
605
606   // Setup our advertisement. This has no callback.
607   internal_->gatt->advertiser->SetData(0, true, /* scan response */
608                                        {}, base::DoNothing());
609   // transmit_name,              /* name */
610   // false,                      /* no txpower */
611   // 2, 2,                        interval
612   // 0,                          /* appearance */
613   // mutable_manufacturer_data,
614   // mutable_service_data,
615   // id_data);
616   return true;
617 }
618
619 bool Server::AddCharacteristic(const Uuid& id, int properties,
620                                int permissions) {
621   std::unique_lock<std::mutex> lock(internal_->lock);
622   bt_status_t btstat =
623       internal_->AddCharacteristic(id, properties, permissions);
624   if (btstat != BT_STATUS_SUCCESS) {
625     LOG_ERROR(LOG_TAG, "Failed to add characteristic to service: 0x%04x",
626               internal_->service_handle);
627     return false;
628   }
629   internal_->api_synchronize.wait(lock);
630   const int handle = internal_->uuid_to_attribute[id];
631   internal_->characteristics[handle].notify = properties & kPropertyNotify;
632   return true;
633 }
634
635 bool Server::AddBlob(const Uuid& id, const Uuid& control_id, int properties,
636                      int permissions) {
637   std::unique_lock<std::mutex> lock(internal_->lock);
638
639   // First, add the primary attribute (characteristic value)
640   bt_status_t btstat =
641       internal_->AddCharacteristic(id, properties, permissions);
642   if (btstat != BT_STATUS_SUCCESS) {
643     LOG_ERROR(LOG_TAG, "Failed to set scan response data");
644     return false;
645   }
646
647   // Next, add the secondary attribute (blob control).
648   // Control attributes have fixed permissions/properties.
649   // Remember position at which blob was added.
650   blob_index.insert(pending_svc_decl.size());
651   btstat =
652       internal_->AddCharacteristic(control_id, kPropertyRead | kPropertyWrite,
653                                    kPermissionRead | kPermissionWrite);
654
655   return true;
656 }
657
658 bool Server::Start() {
659   std::unique_lock<std::mutex> lock(internal_->lock);
660   bt_status_t btstat = internal_->gatt->server->add_service(
661       internal_->server_if, pending_svc_decl);
662   if (btstat != BT_STATUS_SUCCESS) {
663     LOG_ERROR(LOG_TAG, "Failed to start service with handle: 0x%04x",
664               internal_->service_handle);
665     return false;
666   }
667   internal_->api_synchronize.wait(lock);
668   return true;
669 }
670
671 bool Server::Stop() {
672   std::unique_lock<std::mutex> lock(internal_->lock);
673   bt_status_t btstat = internal_->gatt->server->stop_service(
674       internal_->server_if, internal_->service_handle);
675   if (btstat != BT_STATUS_SUCCESS) {
676     LOG_ERROR(LOG_TAG, "Failed to stop service with handle: 0x%04x",
677               internal_->service_handle);
678     return false;
679   }
680   internal_->api_synchronize.wait(lock);
681   return true;
682 }
683
684 bool Server::ScanEnable() {
685   internal_->gatt->scanner->Scan(true);
686   return true;
687 }
688
689 bool Server::ScanDisable() {
690   internal_->gatt->scanner->Scan(false);
691   return true;
692 }
693
694 bool Server::GetScanResults(ScanResults* results) {
695   std::lock_guard<std::mutex> lock(internal_->lock);
696   *results = internal_->scan_results;
697   return true;
698 }
699
700 bool Server::SetCharacteristicValue(const Uuid& id,
701                                     const std::vector<uint8_t>& value) {
702   std::lock_guard<std::mutex> lock(internal_->lock);
703   const int attribute_id = internal_->uuid_to_attribute[id];
704   Characteristic& ch = internal_->characteristics[attribute_id];
705   ch.next_blob = value;
706   ch.next_blob_pending = true;
707
708   if (!ch.notify) return true;
709
710   for (auto connection : internal_->connections) {
711     internal_->gatt->server->send_indication(internal_->server_if, attribute_id,
712                                              connection, true, {0});
713   }
714   return true;
715 }
716
717 bool Server::GetCharacteristicValue(const Uuid& id,
718                                     std::vector<uint8_t>* value) {
719   std::lock_guard<std::mutex> lock(internal_->lock);
720   const int attribute_id = internal_->uuid_to_attribute[id];
721   *value = internal_->characteristics[attribute_id].blob;
722   return true;
723 }
724
725 }  // namespace gatt
726 }  // namespace bluetooth