Home | History | Annotate | Download | only in service
      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 <algorithm>
     27 #include <array>
     28 #include <condition_variable>
     29 #include <map>
     30 #include <memory>
     31 #include <mutex>
     32 #include <set>
     33 #include <string>
     34 #include <unordered_map>
     35 #include <unordered_set>
     36 #include <vector>
     37 
     38 #include <hardware/bluetooth.h>
     39 #include <hardware/bt_gatt.h>
     40 
     41 #include "service/hal/bluetooth_interface.h"
     42 #include "service/logging_helpers.h"
     43 
     44 #include "osi/include/log.h"
     45 #include "osi/include/osi.h"
     46 
     47 namespace {
     48 
     49 const size_t kMaxGattAttributeSize = 512;
     50 std::vector<btgatt_db_element_t> pending_svc_decl;
     51 std::unordered_set<int> blob_index;
     52 
     53 // TODO(icoolidge): Support multiple instances
     54 // TODO(armansito): Remove this variable. No point of having this if
     55 // each bluetooth::gatt::Server instance already keeps a pointer to the
     56 // ServerInternals that is associated with it (which is much cleaner). It looks
     57 // like this variable exists because the btif callbacks don't allow the
     58 // upper-layer to pass user data to them. We could:
     59 //
     60 //    1. Fix the btif callbacks so that some sort of continuation can be
     61 //    attached to a callback. This might be a long shot since the callback
     62 //    interface doesn't allow more than one caller to register its own callbacks
     63 //    (which might be what we want though, since this would make the API more
     64 //    flexible).
     65 //
     66 //    2. Allow creation of Server objects using a factory method that returns
     67 //    the result asynchronously in a base::Callback. The RegisterServerCallback
     68 //    provides an |app_uuid|, which can be used to store callback structures in
     69 //    a map and lazily instantiate the Server and invoke the correct callback.
     70 //    This is a general pattern that we should use throughout the daemon, since
     71 //    all operations can timeout or fail and this is best reported in an
     72 //    asynchronous base::Callback.
     73 //
     74 static bluetooth::gatt::ServerInternals* g_internal = nullptr;
     75 
     76 enum { kPipeReadEnd = 0, kPipeWriteEnd = 1, kPipeNumEnds = 2 };
     77 
     78 }  // namespace
     79 
     80 void DoNothing(uint8_t p) {}
     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::Bind(&DoNothing));
    358 
    359   g_internal->gatt->advertiser->Enable(
    360       0 /* std_inst */, true, base::Bind(&EnableAdvertisingCallback),
    361       0 /* no duration */, 0 /* no maxExtAdvEvent*/, base::Bind(&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::Bind(&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::Bind(&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
    727