Home | History | Annotate | Download | only in service
      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 #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 <algorithm>
     26 #include <array>
     27 #include <condition_variable>
     28 #include <map>
     29 #include <memory>
     30 #include <mutex>
     31 #include <set>
     32 #include <string>
     33 #include <unordered_map>
     34 #include <vector>
     35 
     36 #include <hardware/bluetooth.h>
     37 #include <hardware/bt_gatt.h>
     38 
     39 #include "service/hal/bluetooth_interface.h"
     40 #include "service/logging_helpers.h"
     41 
     42 extern "C" {
     43 #include "osi/include/log.h"
     44 #include "osi/include/osi.h"
     45 }  // extern "C"
     46 
     47 namespace {
     48 
     49 const size_t kMaxGattAttributeSize = 512;
     50 // TODO(icoolidge): Difficult to generalize without knowing how many attributes.
     51 const int kNumBlueDroidHandles = 60;
     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 namespace bluetooth {
     81 namespace gatt {
     82 
     83 struct Characteristic {
     84   UUID uuid;
     85   int blob_section;
     86   std::vector<uint8_t> blob;
     87 
     88   // Support synchronized blob updates by latching under mutex.
     89   std::vector<uint8_t> next_blob;
     90   bool next_blob_pending;
     91   bool notify;
     92 };
     93 
     94 struct ServerInternals {
     95   ServerInternals();
     96   ~ServerInternals();
     97   int Initialize();
     98   bt_status_t AddCharacteristic(
     99       const UUID& uuid,
    100       int properties,
    101       int 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   btgatt_srvc_id_t service_id;
    120   std::set<int> connections;
    121 
    122   std::mutex lock;
    123   std::condition_variable api_synchronize;
    124   int pipefd[kPipeNumEnds];
    125 };
    126 
    127 }  // namespace gatt
    128 }  // namespace bluetooth
    129 
    130 namespace {
    131 
    132 /** Callback invoked in response to register_server */
    133 void RegisterServerCallback(int status, int server_if, bt_uuid_t *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   btgatt_srvc_id_t service_id;
    140   service_id.id.uuid = *app_uuid;
    141   service_id.id.inst_id = 0;
    142   service_id.is_primary = true;
    143 
    144   g_internal->gatt->server->add_service(
    145       server_if, &service_id, kNumBlueDroidHandles);
    146 }
    147 
    148 void ServiceAddedCallback(int status, int server_if, btgatt_srvc_id_t *srvc_id,
    149                           int srvc_handle) {
    150   LOG_INFO(LOG_TAG, "%s: status:%d server_if:%d gatt_srvc_id:%u srvc_handle:%d",
    151            __func__, status, server_if, srvc_id->id.inst_id, srvc_handle);
    152 
    153   std::lock_guard<std::mutex> lock(g_internal->lock);
    154   g_internal->server_if = server_if;
    155   g_internal->service_handle = srvc_handle;
    156   g_internal->service_id = *srvc_id;
    157   // This finishes the Initialize call.
    158   g_internal->api_synchronize.notify_one();
    159 }
    160 
    161 void RequestReadCallback(int conn_id, int trans_id, bt_bdaddr_t *bda,
    162                          int attr_handle, int attribute_offset_octets,
    163                          bool is_long) {
    164   std::lock_guard<std::mutex> lock(g_internal->lock);
    165 
    166   bluetooth::gatt::Characteristic &ch = g_internal->characteristics[attr_handle];
    167 
    168   // Latch next_blob to blob on a 'fresh' read.
    169   if (ch.next_blob_pending && attribute_offset_octets == 0 &&
    170       ch.blob_section == 0) {
    171     std::swap(ch.blob, ch.next_blob);
    172     ch.next_blob_pending = false;
    173   }
    174 
    175   const size_t blob_offset_octets =
    176       std::min(ch.blob.size(), ch.blob_section * kMaxGattAttributeSize);
    177   const size_t blob_remaining = ch.blob.size() - blob_offset_octets;
    178   const size_t attribute_size = std::min(kMaxGattAttributeSize, blob_remaining);
    179 
    180   std::string addr(BtAddrString(bda));
    181   LOG_INFO(LOG_TAG,
    182       "%s: connection:%d (%s) reading attr:%d attribute_offset_octets:%d "
    183       "blob_section:%u (is_long:%u)",
    184       __func__, conn_id, addr.c_str(), attr_handle, attribute_offset_octets,
    185       ch.blob_section, is_long);
    186 
    187   btgatt_response_t response;
    188   response.attr_value.len = 0;
    189 
    190   if (attribute_offset_octets < static_cast<int>(attribute_size)) {
    191     std::copy(ch.blob.begin() + blob_offset_octets + attribute_offset_octets,
    192               ch.blob.begin() + blob_offset_octets + attribute_size,
    193               response.attr_value.value);
    194     response.attr_value.len = attribute_size - attribute_offset_octets;
    195   }
    196 
    197   response.attr_value.handle = attr_handle;
    198   response.attr_value.offset = attribute_offset_octets;
    199   response.attr_value.auth_req = 0;
    200   g_internal->gatt->server->send_response(conn_id, trans_id, 0, &response);
    201 }
    202 
    203 void RequestWriteCallback(int conn_id, int trans_id, bt_bdaddr_t *bda,
    204                           int attr_handle, int attribute_offset, int length,
    205                           bool need_rsp, bool is_prep, uint8_t *value) {
    206   std::string addr(BtAddrString(bda));
    207   LOG_INFO(LOG_TAG,
    208       "%s: connection:%d (%s:trans:%d) write attr:%d attribute_offset:%d "
    209       "length:%d "
    210       "need_resp:%u is_prep:%u",
    211       __func__, conn_id, addr.c_str(), trans_id, attr_handle, attribute_offset,
    212       length, need_rsp, is_prep);
    213 
    214   std::lock_guard<std::mutex> lock(g_internal->lock);
    215 
    216   bluetooth::gatt::Characteristic &ch =
    217       g_internal->characteristics[attr_handle];
    218 
    219   ch.blob.resize(attribute_offset + length);
    220 
    221   std::copy(value, value + length, ch.blob.begin() + attribute_offset);
    222 
    223   auto target_blob = g_internal->controlled_blobs.find(attr_handle);
    224   // If this is a control attribute, adjust offset of the target blob.
    225   if (target_blob != g_internal->controlled_blobs.end() &&
    226       ch.blob.size() == 1u) {
    227     g_internal->characteristics[target_blob->second].blob_section = ch.blob[0];
    228     LOG_INFO(LOG_TAG, "%s: updating attribute %d blob_section to %u", __func__,
    229         target_blob->second, ch.blob[0]);
    230   } else if (!is_prep) {
    231     // This is a single frame characteristic write.
    232     // Notify upwards because we're done now.
    233     const bluetooth::UUID::UUID128Bit &attr_uuid = ch.uuid.GetFullBigEndian();
    234     ssize_t status;
    235     OSI_NO_INTR(status = write(g_internal->pipefd[kPipeWriteEnd],
    236                                attr_uuid.data(), attr_uuid.size()));
    237     if (-1 == status)
    238       LOG_ERROR(LOG_TAG, "%s: write failed: %s", __func__, strerror(errno));
    239   } else {
    240     // This is a multi-frame characteristic write.
    241     // Wait for an 'RequestExecWriteCallback' to notify completion.
    242     g_internal->last_write = ch.uuid;
    243   }
    244 
    245   // Respond only if needed.
    246   if (!need_rsp) return;
    247 
    248   btgatt_response_t response;
    249   response.attr_value.handle = attr_handle;
    250   response.attr_value.offset = attribute_offset;
    251   response.attr_value.len = length;
    252   response.attr_value.auth_req = 0;
    253   // Provide written data back to sender for the response.
    254   // Remote stacks use this to validate the success of the write.
    255   std::copy(value, value + length, response.attr_value.value);
    256   g_internal->gatt->server->send_response(conn_id, trans_id, 0, &response);
    257 }
    258 
    259 void RequestExecWriteCallback(int conn_id, int trans_id, bt_bdaddr_t *bda,
    260                               int exec_write) {
    261   std::string addr(BtAddrString(bda));
    262   LOG_INFO(LOG_TAG, "%s: connection:%d (%s:trans:%d) exec_write:%d", __func__,
    263       conn_id, addr.c_str(), trans_id, exec_write);
    264 
    265   // This 'response' data is unused for ExecWriteResponses.
    266   // It is only used to pass BlueDroid argument validation.
    267   btgatt_response_t response = {};
    268   g_internal->gatt->server->send_response(conn_id, trans_id, 0, &response);
    269 
    270   if (!exec_write)
    271     return;
    272 
    273   std::lock_guard<std::mutex> lock(g_internal->lock);
    274   // Communicate the attribute UUID as notification of a write update.
    275   const bluetooth::UUID::UUID128Bit uuid =
    276       g_internal->last_write.GetFullBigEndian();
    277   ssize_t status;
    278   OSI_NO_INTR(status = write(g_internal->pipefd[kPipeWriteEnd], uuid.data(),
    279                              uuid.size()));
    280   if (-1 == status)
    281     LOG_ERROR(LOG_TAG, "%s: write failed: %s", __func__, strerror(errno));
    282 }
    283 
    284 void ConnectionCallback(int conn_id, int server_if, int connected,
    285                         bt_bdaddr_t *bda) {
    286   std::string addr(BtAddrString(bda));
    287   LOG_INFO(LOG_TAG, "%s: connection:%d server_if:%d connected:%d addr:%s",
    288       __func__, conn_id, server_if, connected, addr.c_str());
    289   if (connected == 1) {
    290     g_internal->connections.insert(conn_id);
    291   } else if (connected == 0) {
    292     g_internal->connections.erase(conn_id);
    293   }
    294 }
    295 
    296 void CharacteristicAddedCallback(int status, int server_if, bt_uuid_t *uuid,
    297                                  int srvc_handle, int char_handle) {
    298   LOG_INFO(LOG_TAG,
    299       "%s: status:%d server_if:%d service_handle:%d char_handle:%d", __func__,
    300       status, server_if, srvc_handle, char_handle);
    301 
    302   bluetooth::UUID id(*uuid);
    303 
    304   std::lock_guard<std::mutex> lock(g_internal->lock);
    305 
    306   g_internal->uuid_to_attribute[id] = char_handle;
    307   g_internal->characteristics[char_handle].uuid = id;
    308   g_internal->characteristics[char_handle].blob_section = 0;
    309 
    310   // This terminates an AddCharacteristic.
    311   g_internal->api_synchronize.notify_one();
    312 }
    313 
    314 void DescriptorAddedCallback(int status, int server_if, bt_uuid_t *uuid,
    315                              int srvc_handle, int descr_handle) {
    316   LOG_INFO(LOG_TAG,
    317       "%s: status:%d server_if:%d service_handle:%d uuid[0]:%u "
    318       "descr_handle:%d",
    319       __func__, status, server_if, srvc_handle, uuid->uu[0], descr_handle);
    320 }
    321 
    322 void ServiceStartedCallback(int status, int server_if, int srvc_handle) {
    323   LOG_INFO(LOG_TAG, "%s: status:%d server_if:%d srvc_handle:%d", __func__,
    324       status, server_if, srvc_handle);
    325 
    326   // The UUID provided here is unimportant, and is only used to satisfy
    327   // BlueDroid.
    328   // It must be different than any other registered UUID.
    329   bt_uuid_t client_id = g_internal->service_id.id.uuid;
    330   ++client_id.uu[15];
    331 
    332   bt_status_t btstat = g_internal->gatt->client->register_client(&client_id);
    333   if (btstat != BT_STATUS_SUCCESS) {
    334     LOG_ERROR(LOG_TAG, "%s: Failed to register client", __func__);
    335   }
    336 }
    337 
    338 void RegisterClientCallback(int status, int client_if, bt_uuid_t *app_uuid) {
    339   LOG_INFO(LOG_TAG, "%s: status:%d client_if:%d uuid[0]:%u", __func__, status,
    340       client_if, app_uuid->uu[0]);
    341   g_internal->client_if = client_if;
    342 
    343   // Setup our advertisement. This has no callback.
    344   bt_status_t btstat = g_internal->gatt->client->set_adv_data(
    345       client_if, false, /* beacon, not scan response */
    346       false,            /* name */
    347       false,            /* no txpower */
    348       2, 2,             /* interval */
    349       0,                /* appearance */
    350       0, nullptr,       /* no mfg data */
    351       0, nullptr,       /* no service data */
    352       0, nullptr /* no service id yet */);
    353   if (btstat != BT_STATUS_SUCCESS) {
    354     LOG_ERROR(LOG_TAG, "Failed to set advertising data");
    355     return;
    356   }
    357 
    358   // TODO(icoolidge): Deprecated, use multi-adv interface.
    359   // This calls back to ListenCallback.
    360   btstat = g_internal->gatt->client->listen(client_if, true);
    361   if (btstat != BT_STATUS_SUCCESS) {
    362     LOG_ERROR(LOG_TAG, "Failed to start listening");
    363   }
    364 }
    365 
    366 void ListenCallback(int status, int client_if) {
    367   LOG_INFO(LOG_TAG, "%s: status:%d client_if:%d", __func__, status, client_if);
    368   // This terminates a Start call.
    369   std::lock_guard<std::mutex> lock(g_internal->lock);
    370   g_internal->api_synchronize.notify_one();
    371 }
    372 
    373 void ServiceStoppedCallback(int status, int server_if, int srvc_handle) {
    374   LOG_INFO(LOG_TAG, "%s: status:%d server_if:%d srvc_handle:%d", __func__,
    375       status, server_if, srvc_handle);
    376   // This terminates a Stop call.
    377   // TODO(icoolidge): make this symmetric with start
    378   std::lock_guard<std::mutex> lock(g_internal->lock);
    379   g_internal->api_synchronize.notify_one();
    380 }
    381 
    382 void ScanResultCallback(bt_bdaddr_t *bda, int rssi, uint8_t *adv_data) {
    383   std::string addr(BtAddrString(bda));
    384   (void)adv_data;
    385   std::lock_guard<std::mutex> lock(g_internal->lock);
    386   g_internal->scan_results[addr] = rssi;
    387 }
    388 
    389 void ClientConnectCallback(int conn_id, int status, int client_if,
    390                            bt_bdaddr_t *bda) {
    391   std::string addr(BtAddrString(bda));
    392   LOG_INFO(LOG_TAG, "%s: conn_id:%d status:%d client_if:%d %s", __func__,
    393       conn_id, status, client_if, addr.c_str());
    394 }
    395 
    396 void ClientDisconnectCallback(int conn_id, int status, int client_if,
    397                               bt_bdaddr_t *bda) {
    398   std::string addr(BtAddrString(bda));
    399   LOG_INFO(LOG_TAG, "%s: conn_id:%d status:%d client_if:%d %s", __func__,
    400       conn_id, status, client_if, addr.c_str());
    401 }
    402 
    403 void IndicationSentCallback(UNUSED_ATTR int conn_id,
    404                             UNUSED_ATTR int status) {
    405   // TODO(icoolidge): what to do
    406 }
    407 
    408 void ResponseConfirmationCallback(UNUSED_ATTR int status,
    409                                   UNUSED_ATTR int handle) {
    410   // TODO(icoolidge): what to do
    411 }
    412 
    413 const btgatt_server_callbacks_t gatt_server_callbacks = {
    414     RegisterServerCallback,
    415     ConnectionCallback,
    416     ServiceAddedCallback,
    417     nullptr, /* included_service_added_cb */
    418     CharacteristicAddedCallback,
    419     DescriptorAddedCallback,
    420     ServiceStartedCallback,
    421     ServiceStoppedCallback,
    422     nullptr, /* service_deleted_cb */
    423     RequestReadCallback,
    424     RequestWriteCallback,
    425     RequestExecWriteCallback,
    426     ResponseConfirmationCallback,
    427     IndicationSentCallback,
    428     nullptr, /* congestion_cb*/
    429     nullptr, /* mtu_changed_cb */
    430 };
    431 
    432 // TODO(eisenbach): Refactor GATT interface to not require servers
    433 // to refer to the client interface.
    434 const btgatt_client_callbacks_t gatt_client_callbacks = {
    435     RegisterClientCallback,
    436     ScanResultCallback,
    437     ClientConnectCallback,
    438     ClientDisconnectCallback,
    439     nullptr, /* search_complete_cb; */
    440     nullptr, /* register_for_notification_cb; */
    441     nullptr, /* notify_cb; */
    442     nullptr, /* read_characteristic_cb; */
    443     nullptr, /* write_characteristic_cb; */
    444     nullptr, /* read_descriptor_cb; */
    445     nullptr, /* write_descriptor_cb; */
    446     nullptr, /* execute_write_cb; */
    447     nullptr, /* read_remote_rssi_cb; */
    448     ListenCallback,
    449     nullptr, /* configure_mtu_cb; */
    450     nullptr, /* scan_filter_cfg_cb; */
    451     nullptr, /* scan_filter_param_cb; */
    452     nullptr, /* scan_filter_status_cb; */
    453     nullptr, /* multi_adv_enable_cb */
    454     nullptr, /* multi_adv_update_cb; */
    455     nullptr, /* multi_adv_data_cb*/
    456     nullptr, /* multi_adv_disable_cb; */
    457     nullptr, /* congestion_cb; */
    458     nullptr, /* batchscan_cfg_storage_cb; */
    459     nullptr, /* batchscan_enb_disable_cb; */
    460     nullptr, /* batchscan_reports_cb; */
    461     nullptr, /* batchscan_threshold_cb; */
    462     nullptr, /* track_adv_event_cb; */
    463     nullptr, /* scan_parameter_setup_completed_cb; */
    464     nullptr, /* get_gatt_db_cb; */
    465     nullptr, /* services_removed_cb */
    466     nullptr, /* services_added_cb */
    467 };
    468 
    469 const btgatt_callbacks_t gatt_callbacks = {
    470     /** Set to sizeof(btgatt_callbacks_t) */
    471     sizeof(btgatt_callbacks_t),
    472 
    473     /** GATT Client callbacks */
    474     &gatt_client_callbacks,
    475 
    476     /** GATT Server callbacks */
    477     &gatt_server_callbacks};
    478 
    479 }  // namespace
    480 
    481 namespace bluetooth {
    482 namespace gatt {
    483 
    484 int ServerInternals::Initialize() {
    485   // Get the interface to the GATT profile.
    486   const bt_interface_t* bt_iface =
    487       hal::BluetoothInterface::Get()->GetHALInterface();
    488   gatt = reinterpret_cast<const btgatt_interface_t *>(
    489       bt_iface->get_profile_interface(BT_PROFILE_GATT_ID));
    490   if (!gatt) {
    491     LOG_ERROR(LOG_TAG, "Error getting GATT interface");
    492     return -1;
    493   }
    494 
    495   bt_status_t btstat = gatt->init(&gatt_callbacks);
    496   if (btstat != BT_STATUS_SUCCESS) {
    497     LOG_ERROR(LOG_TAG, "Failed to initialize gatt interface");
    498     return -1;
    499   }
    500 
    501   int status = pipe(pipefd);
    502   if (status == -1) {
    503     LOG_ERROR(LOG_TAG, "pipe creation failed: %s", strerror(errno));
    504     return -1;
    505   }
    506 
    507   return 0;
    508 }
    509 
    510 bt_status_t ServerInternals::AddCharacteristic(
    511     const UUID& uuid,
    512     int properties,
    513     int permissions) {
    514   bt_uuid_t c_uuid = uuid.GetBlueDroid();
    515   return gatt->server->add_characteristic(
    516       server_if, service_handle, &c_uuid, properties, permissions);
    517 }
    518 
    519 ServerInternals::ServerInternals()
    520     : gatt(nullptr),
    521       server_if(0),
    522       client_if(0),
    523       service_handle(0),
    524       pipefd{INVALID_FD, INVALID_FD} {}
    525 
    526 ServerInternals::~ServerInternals() {
    527   if (pipefd[0] != INVALID_FD)
    528     close(pipefd[0]);
    529   if (pipefd[1] != INVALID_FD)
    530     close(pipefd[1]);
    531 
    532   gatt->server->delete_service(server_if, service_handle);
    533   gatt->server->unregister_server(server_if);
    534   gatt->client->unregister_client(client_if);
    535 }
    536 
    537 Server::Server() : internal_(nullptr) {}
    538 
    539 Server::~Server() {}
    540 
    541 bool Server::Initialize(const UUID& service_id, int* gatt_pipe) {
    542   internal_.reset(new ServerInternals);
    543   if (!internal_) {
    544     LOG_ERROR(LOG_TAG, "Error creating internals");
    545     return false;
    546   }
    547   g_internal = internal_.get();
    548 
    549   std::unique_lock<std::mutex> lock(internal_->lock);
    550   int status = internal_->Initialize();
    551   if (status) {
    552     LOG_ERROR(LOG_TAG, "Error initializing internals");
    553     return false;
    554   }
    555 
    556   bt_uuid_t uuid = service_id.GetBlueDroid();
    557 
    558   bt_status_t btstat = internal_->gatt->server->register_server(&uuid);
    559   if (btstat != BT_STATUS_SUCCESS) {
    560     LOG_ERROR(LOG_TAG, "Failed to register server");
    561     return false;
    562   }
    563 
    564   internal_->api_synchronize.wait(lock);
    565   // TODO(icoolidge): Better error handling.
    566   if (internal_->server_if == 0) {
    567     LOG_ERROR(LOG_TAG, "Initialization of server failed");
    568     return false;
    569   }
    570 
    571   *gatt_pipe = internal_->pipefd[kPipeReadEnd];
    572   LOG_INFO(LOG_TAG, "Server Initialize succeeded");
    573   return true;
    574 }
    575 
    576 bool Server::SetAdvertisement(const std::vector<UUID>& ids,
    577                               const std::vector<uint8_t>& service_data,
    578                               const std::vector<uint8_t>& manufacturer_data,
    579                               bool transmit_name) {
    580   std::vector<uint8_t> id_data;
    581   auto mutable_manufacturer_data = manufacturer_data;
    582   auto mutable_service_data = service_data;
    583 
    584   for (const UUID &id : ids) {
    585     const auto le_id = id.GetFullLittleEndian();
    586     id_data.insert(id_data.end(), le_id.begin(), le_id.end());
    587   }
    588 
    589   std::lock_guard<std::mutex> lock(internal_->lock);
    590 
    591   // Setup our advertisement. This has no callback.
    592   bt_status_t btstat = internal_->gatt->client->set_adv_data(
    593       internal_->client_if, false, /* beacon, not scan response */
    594       transmit_name,               /* name */
    595       false,                       /* no txpower */
    596       2, 2,                        /* interval */
    597       0,                           /* appearance */
    598       mutable_manufacturer_data.size(),
    599       reinterpret_cast<char *>(mutable_manufacturer_data.data()),
    600       mutable_service_data.size(),
    601       reinterpret_cast<char *>(mutable_service_data.data()), id_data.size(),
    602       reinterpret_cast<char *>(id_data.data()));
    603   if (btstat != BT_STATUS_SUCCESS) {
    604     LOG_ERROR(LOG_TAG, "Failed to set advertising data");
    605     return false;
    606   }
    607   return true;
    608 }
    609 
    610 bool Server::SetScanResponse(const std::vector<UUID>& ids,
    611                              const std::vector<uint8_t>& service_data,
    612                              const std::vector<uint8_t>& manufacturer_data,
    613                              bool transmit_name) {
    614   std::vector<uint8_t> id_data;
    615   auto mutable_manufacturer_data = manufacturer_data;
    616   auto mutable_service_data = service_data;
    617 
    618   for (const UUID &id : ids) {
    619     const auto le_id = id.GetFullLittleEndian();
    620     id_data.insert(id_data.end(), le_id.begin(), le_id.end());
    621   }
    622 
    623   std::lock_guard<std::mutex> lock(internal_->lock);
    624 
    625   // Setup our advertisement. This has no callback.
    626   bt_status_t btstat = internal_->gatt->client->set_adv_data(
    627       internal_->client_if, true, /* scan response */
    628       transmit_name,              /* name */
    629       false,                      /* no txpower */
    630       2, 2,                       /* interval */
    631       0,                          /* appearance */
    632       mutable_manufacturer_data.size(),
    633       reinterpret_cast<char *>(mutable_manufacturer_data.data()),
    634       mutable_service_data.size(),
    635       reinterpret_cast<char *>(mutable_service_data.data()), id_data.size(),
    636       reinterpret_cast<char *>(id_data.data()));
    637   if (btstat != BT_STATUS_SUCCESS) {
    638     LOG_ERROR(LOG_TAG, "Failed to set scan response data");
    639     return false;
    640   }
    641   return true;
    642 }
    643 
    644 bool Server::AddCharacteristic(
    645     const UUID &id, int properties, int permissions) {
    646   std::unique_lock<std::mutex> lock(internal_->lock);
    647   bt_status_t btstat = internal_->AddCharacteristic(
    648       id, properties, permissions);
    649   if (btstat != BT_STATUS_SUCCESS) {
    650     LOG_ERROR(LOG_TAG, "Failed to add characteristic to service: 0x%04x",
    651               internal_->service_handle);
    652     return false;
    653   }
    654   internal_->api_synchronize.wait(lock);
    655   const int handle = internal_->uuid_to_attribute[id];
    656   internal_->characteristics[handle].notify = properties & kPropertyNotify;
    657   return true;
    658 }
    659 
    660 bool Server::AddBlob(const UUID &id, const UUID &control_id, int properties,
    661                     int permissions) {
    662   std::unique_lock<std::mutex> lock(internal_->lock);
    663 
    664   // First, add the primary attribute (characteristic value)
    665   bt_status_t btstat = internal_->AddCharacteristic(
    666       id, properties, permissions);
    667   if (btstat != BT_STATUS_SUCCESS) {
    668     LOG_ERROR(LOG_TAG, "Failed to set scan response data");
    669     return false;
    670   }
    671 
    672   internal_->api_synchronize.wait(lock);
    673 
    674   // Next, add the secondary attribute (blob control).
    675   // Control attributes have fixed permissions/properties.
    676   btstat = internal_->AddCharacteristic(
    677       control_id,
    678       kPropertyRead | kPropertyWrite,
    679       kPermissionRead | kPermissionWrite);
    680   internal_->api_synchronize.wait(lock);
    681 
    682   // Finally, associate the control attribute with the value attribute.
    683   // Also, initialize the control attribute to a readable zero.
    684   const int control_attribute = internal_->uuid_to_attribute[control_id];
    685   const int blob_attribute = internal_->uuid_to_attribute[id];
    686   internal_->controlled_blobs[control_attribute] = blob_attribute;
    687   internal_->characteristics[blob_attribute].notify =
    688       properties & kPropertyNotify;
    689 
    690   Characteristic &ctrl = internal_->characteristics[control_attribute];
    691   ctrl.next_blob.clear();
    692   ctrl.next_blob.push_back(0);
    693   ctrl.next_blob_pending = true;
    694   ctrl.blob_section = 0;
    695   ctrl.notify = false;
    696   return true;
    697 }
    698 
    699 bool Server::Start() {
    700   std::unique_lock<std::mutex> lock(internal_->lock);
    701   bt_status_t btstat = internal_->gatt->server->start_service(
    702       internal_->server_if, internal_->service_handle, GATT_TRANSPORT_LE);
    703   if (btstat != BT_STATUS_SUCCESS) {
    704     LOG_ERROR(LOG_TAG, "Failed to start service with handle: 0x%04x",
    705               internal_->service_handle);
    706     return false;
    707   }
    708   internal_->api_synchronize.wait(lock);
    709   return true;
    710 }
    711 
    712 bool Server::Stop() {
    713   std::unique_lock<std::mutex> lock(internal_->lock);
    714   bt_status_t btstat = internal_->gatt->server->stop_service(
    715       internal_->server_if, internal_->service_handle);
    716   if (btstat != BT_STATUS_SUCCESS) {
    717     LOG_ERROR(LOG_TAG, "Failed to stop service with handle: 0x%04x",
    718               internal_->service_handle);
    719     return false;
    720   }
    721   internal_->api_synchronize.wait(lock);
    722   return true;
    723 }
    724 
    725 bool Server::ScanEnable() {
    726   bt_status_t btstat = internal_->gatt->client->scan(true);
    727   if (btstat) {
    728     LOG_ERROR(LOG_TAG, "Enable scan failed: %d", btstat);
    729     return false;
    730   }
    731   return true;
    732 }
    733 
    734 bool Server::ScanDisable() {
    735   bt_status_t btstat = internal_->gatt->client->scan(false);
    736   if (btstat) {
    737     LOG_ERROR(LOG_TAG, "Disable scan failed: %d", btstat);
    738     return false;
    739   }
    740   return true;
    741 }
    742 
    743 bool Server::GetScanResults(ScanResults *results) {
    744   std::lock_guard<std::mutex> lock(internal_->lock);
    745   *results = internal_->scan_results;
    746   return true;
    747 }
    748 
    749 bool Server::SetCharacteristicValue(const UUID &id,
    750                               const std::vector<uint8_t> &value) {
    751   std::lock_guard<std::mutex> lock(internal_->lock);
    752   const int attribute_id = internal_->uuid_to_attribute[id];
    753   Characteristic &ch = internal_->characteristics[attribute_id];
    754   ch.next_blob = value;
    755   ch.next_blob_pending = true;
    756 
    757   if (!ch.notify)
    758     return true;
    759 
    760   for (auto connection : internal_->connections) {
    761     char dummy = 0;
    762     internal_->gatt->server->send_indication(internal_->server_if,
    763                                              attribute_id,
    764                                              connection,
    765                                              sizeof(dummy),
    766                                              true,
    767                                              &dummy);
    768   }
    769   return true;
    770 }
    771 
    772 bool Server::GetCharacteristicValue(const UUID &id, std::vector<uint8_t> *value) {
    773   std::lock_guard<std::mutex> lock(internal_->lock);
    774   const int attribute_id = internal_->uuid_to_attribute[id];
    775   *value = internal_->characteristics[attribute_id].blob;
    776   return true;
    777 }
    778 
    779 }  // namespace gatt
    780 }  // namespace bluetooth
    781