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 #include "service/low_energy_client.h"
     18 
     19 #include <base/logging.h>
     20 
     21 #include "service/adapter.h"
     22 #include "service/common/bluetooth/util/address_helper.h"
     23 #include "service/logging_helpers.h"
     24 #include "stack/include/bt_types.h"
     25 #include "stack/include/hcidefs.h"
     26 
     27 using std::lock_guard;
     28 using std::mutex;
     29 
     30 namespace bluetooth {
     31 
     32 namespace {
     33 
     34 // 31 + 31 for advertising data and scan response. This is the maximum length
     35 // TODO(armansito): Fix the HAL to return a concatenated blob that contains the
     36 // true length of each field and also provide a length parameter so that we
     37 // can support advertising length extensions in the future.
     38 const size_t kScanRecordLength = 62;
     39 
     40 BLEStatus GetBLEStatus(int status) {
     41   if (status == BT_STATUS_FAIL)
     42     return BLE_STATUS_FAILURE;
     43 
     44   return static_cast<BLEStatus>(status);
     45 }
     46 
     47 // Returns the length of the given scan record array. We have to calculate this
     48 // based on the maximum possible data length and the TLV data. See TODO above
     49 // |kScanRecordLength|.
     50 size_t GetScanRecordLength(uint8_t* bytes) {
     51   for (size_t i = 0, field_len = 0; i < kScanRecordLength;
     52        i += (field_len + 1)) {
     53     field_len = bytes[i];
     54 
     55     // Assert here that the data returned from the stack is correctly formatted
     56     // in TLV form and that the length of the current field won't exceed the
     57     // total data length.
     58     CHECK(i + field_len < kScanRecordLength);
     59 
     60     // If the field length is zero and we haven't reached the maximum length,
     61     // then we have found the length, as the stack will pad the data with zeros
     62     // accordingly.
     63     if (field_len == 0)
     64       return i;
     65   }
     66 
     67   // We have reached the end.
     68   return kScanRecordLength;
     69 }
     70 
     71 // TODO(armansito): BTIF currently expects each advertising field in a
     72 // specific format passed directly in arguments. We should fix BTIF to accept
     73 // the advertising data directly instead.
     74 struct HALAdvertiseData {
     75   std::vector<uint8_t> manufacturer_data;
     76   std::vector<uint8_t> service_data;
     77   std::vector<uint8_t> service_uuid;
     78 };
     79 
     80 bool ProcessUUID(const uint8_t* uuid_data, size_t uuid_len, UUID* out_uuid) {
     81   // BTIF expects a single 128-bit UUID to be passed in little-endian form, so
     82   // we need to convert into that from raw data.
     83   // TODO(armansito): We have three repeated if bodies below only because UUID
     84   // accepts std::array which requires constexpr lengths. We should just have a
     85   // single UUID constructor that takes in an std::vector instead.
     86   if (uuid_len == UUID::kNumBytes16) {
     87     UUID::UUID16Bit uuid_bytes;
     88     for (size_t i = 0; i < uuid_len; ++i)
     89       uuid_bytes[uuid_len - i - 1] = uuid_data[i];
     90     *out_uuid = UUID(uuid_bytes);
     91   } else if (uuid_len == UUID::kNumBytes32) {
     92     UUID::UUID32Bit uuid_bytes;
     93     for (size_t i = 0; i < uuid_len; ++i)
     94       uuid_bytes[uuid_len - i - 1] = uuid_data[i];
     95     *out_uuid = UUID(uuid_bytes);
     96   } else if (uuid_len == UUID::kNumBytes128) {
     97     UUID::UUID128Bit uuid_bytes;
     98     for (size_t i = 0; i < uuid_len; ++i)
     99       uuid_bytes[uuid_len - i - 1] = uuid_data[i];
    100     *out_uuid = UUID(uuid_bytes);
    101   } else {
    102     LOG(ERROR) << "Invalid UUID length";
    103     return false;
    104   }
    105 
    106   return true;
    107 }
    108 
    109 bool ProcessServiceData(const uint8_t* data,
    110         uint8_t uuid_len,
    111         HALAdvertiseData* out_data) {
    112   size_t field_len = data[0];
    113 
    114   // Minimum packet size should be equal to the uuid length + 1 to include
    115   // the byte for the type of packet
    116   if (field_len < uuid_len + 1) {
    117     // Invalid packet size
    118     return false;
    119   }
    120 
    121   if (!out_data->service_data.empty()) {
    122     // More than one Service Data is not allowed due to the limitations
    123     // of the HAL API. We error in order to make sure there
    124     // is no ambiguity on which data to send.
    125     VLOG(1) << "More than one Service Data entry not allowed";
    126     return false;
    127   }
    128 
    129   const uint8_t* service_uuid = data + 2;
    130   UUID uuid;
    131   if (!ProcessUUID(service_uuid, uuid_len, &uuid))
    132     return false;
    133 
    134   UUID::UUID128Bit uuid_bytes = uuid.GetFullLittleEndian();
    135   const std::vector<uint8_t> temp_uuid(
    136       uuid_bytes.data(), uuid_bytes.data() + uuid_bytes.size());
    137 
    138   // This section is to make sure that there is no UUID conflict
    139   if (out_data->service_uuid.empty()) {
    140     out_data->service_uuid = temp_uuid;
    141   } else if (out_data->service_uuid != temp_uuid) {
    142     // Mismatch in uuid passed through service data and uuid passed
    143     // through uuid field
    144     VLOG(1) << "More than one UUID entry not allowed";
    145     return false;
    146   }  // else do nothing as UUID is already properly assigned
    147 
    148   // Use + uuid_len + 2 here in order to skip over a
    149   // uuid contained in the beggining of the field
    150   const uint8_t* srv_data = data + uuid_len + 2;
    151 
    152 
    153   out_data->service_data.insert(
    154       out_data->service_data.begin(),
    155       srv_data, srv_data + field_len - uuid_len - 1);
    156 
    157   return true;
    158 }
    159 
    160 bool ProcessAdvertiseData(const AdvertiseData& adv,
    161                           HALAdvertiseData* out_data) {
    162   CHECK(out_data);
    163   CHECK(out_data->manufacturer_data.empty());
    164   CHECK(out_data->service_data.empty());
    165   CHECK(out_data->service_uuid.empty());
    166 
    167   const auto& data = adv.data();
    168   size_t len = data.size();
    169   for (size_t i = 0, field_len = 0; i < len; i += (field_len + 1)) {
    170     // The length byte is the first byte in the adv. "TLV" format.
    171     field_len = data[i];
    172 
    173     // The type byte is the next byte in the adv. "TLV" format.
    174     uint8_t type = data[i + 1];
    175 
    176     switch (type) {
    177     case HCI_EIR_MANUFACTURER_SPECIFIC_TYPE: {
    178       // TODO(armansito): BTIF doesn't allow setting more than one
    179       // manufacturer-specific data entry. This is something we should fix. For
    180       // now, fail if more than one entry was set.
    181       if (!out_data->manufacturer_data.empty()) {
    182         LOG(ERROR) << "More than one Manufacturer Specific Data entry not allowed";
    183         return false;
    184       }
    185 
    186       // The value bytes start at the next byte in the "TLV" format.
    187       const uint8_t* mnf_data = data.data() + i + 2;
    188       out_data->manufacturer_data.insert(
    189           out_data->manufacturer_data.begin(),
    190           mnf_data, mnf_data + field_len - 1);
    191       break;
    192     }
    193     case HCI_EIR_MORE_16BITS_UUID_TYPE:
    194     case HCI_EIR_COMPLETE_16BITS_UUID_TYPE:
    195     case HCI_EIR_MORE_32BITS_UUID_TYPE:
    196     case HCI_EIR_COMPLETE_32BITS_UUID_TYPE:
    197     case HCI_EIR_MORE_128BITS_UUID_TYPE:
    198     case HCI_EIR_COMPLETE_128BITS_UUID_TYPE: {
    199       const uint8_t* uuid_data = data.data() + i + 2;
    200       size_t uuid_len = field_len - 1;
    201       UUID uuid;
    202       if (!ProcessUUID(uuid_data, uuid_len, &uuid))
    203         return false;
    204 
    205       UUID::UUID128Bit uuid_bytes = uuid.GetFullLittleEndian();
    206 
    207       if (!out_data->service_uuid.empty() &&
    208           memcmp(out_data->service_uuid.data(),
    209                  uuid_bytes.data(), uuid_bytes.size()) != 0) {
    210         // More than one UUID is not allowed due to the limitations
    211         // of the HAL API. We error in order to make sure there
    212         // is no ambiguity on which UUID to send. Also makes sure that
    213         // UUID Hasn't been set by service data first
    214         LOG(ERROR) << "More than one UUID entry not allowed";
    215         return false;
    216       }
    217 
    218       out_data->service_uuid.assign(
    219           uuid_bytes.data(), uuid_bytes.data() + UUID::kNumBytes128);
    220       break;
    221     }
    222     case HCI_EIR_SERVICE_DATA_16BITS_UUID_TYPE: {
    223       if (!ProcessServiceData(data.data() + i, 2, out_data))
    224         return false;
    225       break;
    226     }
    227     case HCI_EIR_SERVICE_DATA_32BITS_UUID_TYPE: {
    228       if (!ProcessServiceData(data.data() + i, 4, out_data))
    229         return false;
    230       break;
    231     }
    232     case HCI_EIR_SERVICE_DATA_128BITS_UUID_TYPE: {
    233       if (!ProcessServiceData(data.data() + i, 16, out_data))
    234         return false;
    235       break;
    236     }
    237     // TODO(armansito): Support other fields.
    238     default:
    239       VLOG(1) << "Unrecognized EIR field: " << type;
    240       return false;
    241     }
    242   }
    243 
    244   return true;
    245 }
    246 
    247 // The Bluetooth Core Specification defines time interval (e.g. Page Scan
    248 // Interval, Advertising Interval, etc) units as 0.625 milliseconds (or 1
    249 // Baseband slot). The HAL advertising functions expect the interval in this
    250 // unit. This function maps an AdvertiseSettings::Mode value to the
    251 // corresponding time unit.
    252 int GetAdvertisingIntervalUnit(AdvertiseSettings::Mode mode) {
    253   int ms;
    254 
    255   switch (mode) {
    256   case AdvertiseSettings::MODE_BALANCED:
    257     ms = kAdvertisingIntervalMediumMs;
    258     break;
    259   case AdvertiseSettings::MODE_LOW_LATENCY:
    260     ms = kAdvertisingIntervalLowMs;
    261     break;
    262   case AdvertiseSettings::MODE_LOW_POWER:
    263     // Fall through
    264   default:
    265     ms = kAdvertisingIntervalHighMs;
    266     break;
    267   }
    268 
    269   // Convert milliseconds Bluetooth units.
    270   return (ms * 1000) / 625;
    271 }
    272 
    273 struct AdvertiseParams {
    274   int min_interval;
    275   int max_interval;
    276   int event_type;
    277   int tx_power_level;
    278   int timeout_s;
    279 };
    280 
    281 void GetAdvertiseParams(const AdvertiseSettings& settings, bool has_scan_rsp,
    282                         AdvertiseParams* out_params) {
    283   CHECK(out_params);
    284 
    285   out_params->min_interval = GetAdvertisingIntervalUnit(settings.mode());
    286   out_params->max_interval =
    287       out_params->min_interval + kAdvertisingIntervalDeltaUnit;
    288 
    289   if (settings.connectable())
    290     out_params->event_type = kAdvertisingEventTypeConnectable;
    291   else if (has_scan_rsp)
    292     out_params->event_type = kAdvertisingEventTypeScannable;
    293   else
    294     out_params->event_type = kAdvertisingEventTypeNonConnectable;
    295 
    296   out_params->tx_power_level = settings.tx_power_level();
    297   out_params->timeout_s = settings.timeout().InSeconds();
    298 }
    299 
    300 }  // namespace
    301 
    302 // LowEnergyClient implementation
    303 // ========================================================
    304 
    305 LowEnergyClient::LowEnergyClient(
    306     Adapter& adapter, const UUID& uuid, int client_id)
    307     : adapter_(adapter),
    308       app_identifier_(uuid),
    309       client_id_(client_id),
    310       adv_data_needs_update_(false),
    311       scan_rsp_needs_update_(false),
    312       is_setting_adv_data_(false),
    313       adv_started_(false),
    314       adv_start_callback_(nullptr),
    315       adv_stop_callback_(nullptr),
    316       scan_started_(false) {
    317 }
    318 
    319 LowEnergyClient::~LowEnergyClient() {
    320   // Automatically unregister the client.
    321   VLOG(1) << "LowEnergyClient unregistering client: " << client_id_;
    322 
    323   // Unregister as observer so we no longer receive any callbacks.
    324   hal::BluetoothGattInterface::Get()->RemoveClientObserver(this);
    325 
    326   // Stop advertising and ignore the result.
    327   hal::BluetoothGattInterface::Get()->
    328       GetClientHALInterface()->multi_adv_disable(client_id_);
    329   hal::BluetoothGattInterface::Get()->
    330       GetClientHALInterface()->unregister_client(client_id_);
    331 
    332   // Stop any scans started by this client.
    333   if (scan_started_.load())
    334     StopScan();
    335 }
    336 
    337 bool LowEnergyClient::Connect(std::string address, bool is_direct) {
    338   VLOG(2) << __func__ << "Address: " << address << " is_direct: " << is_direct;
    339 
    340   bt_bdaddr_t bda;
    341   util::BdAddrFromString(address, &bda);
    342 
    343   bt_status_t status = hal::BluetoothGattInterface::Get()->
    344       GetClientHALInterface()->connect(client_id_, &bda, is_direct,
    345                                        BT_TRANSPORT_LE);
    346   if (status != BT_STATUS_SUCCESS) {
    347     LOG(ERROR) << "HAL call to connect failed";
    348     return false;
    349   }
    350 
    351   return true;
    352 }
    353 
    354 bool LowEnergyClient::Disconnect(std::string address) {
    355   VLOG(2) << __func__ << "Address: " << address;
    356 
    357   bt_bdaddr_t bda;
    358   util::BdAddrFromString(address, &bda);
    359 
    360   std::map<const bt_bdaddr_t, int>::iterator conn_id;
    361   {
    362     lock_guard<mutex> lock(connection_fields_lock_);
    363     conn_id = connection_ids_.find(bda);
    364     if (conn_id == connection_ids_.end()) {
    365       LOG(WARNING) << "Can't disconnect, no existing connection to " << address;
    366       return false;
    367     }
    368   }
    369 
    370   bt_status_t status = hal::BluetoothGattInterface::Get()->
    371       GetClientHALInterface()->disconnect(client_id_, &bda, conn_id->second);
    372   if (status != BT_STATUS_SUCCESS) {
    373     LOG(ERROR) << "HAL call to disconnect failed";
    374     return false;
    375   }
    376 
    377   return true;
    378 }
    379 
    380 bool LowEnergyClient::SetMtu(std::string address, int mtu) {
    381   VLOG(2) << __func__ << "Address: " << address
    382           << " MTU: " << mtu;
    383 
    384   bt_bdaddr_t bda;
    385   util::BdAddrFromString(address, &bda);
    386 
    387   std::map<const bt_bdaddr_t, int>::iterator conn_id;
    388   {
    389     lock_guard<mutex> lock(connection_fields_lock_);
    390     conn_id = connection_ids_.find(bda);
    391     if (conn_id == connection_ids_.end()) {
    392       LOG(WARNING) << "Can't set MTU, no existing connection to " << address;
    393       return false;
    394     }
    395   }
    396 
    397   bt_status_t status = hal::BluetoothGattInterface::Get()->
    398       GetClientHALInterface()->configure_mtu(conn_id->second, mtu);
    399   if (status != BT_STATUS_SUCCESS) {
    400     LOG(ERROR) << "HAL call to set MTU failed";
    401     return false;
    402   }
    403 
    404   return true;
    405 }
    406 
    407 void LowEnergyClient::SetDelegate(Delegate* delegate) {
    408   lock_guard<mutex> lock(delegate_mutex_);
    409   delegate_ = delegate;
    410 }
    411 
    412 bool LowEnergyClient::StartScan(const ScanSettings& settings,
    413                                 const std::vector<ScanFilter>& filters) {
    414   VLOG(2) << __func__;
    415 
    416   // Cannot start a scan if the adapter is not enabled.
    417   if (!adapter_.IsEnabled()) {
    418     LOG(ERROR) << "Cannot scan while Bluetooth is disabled";
    419     return false;
    420   }
    421 
    422   // TODO(jpawlowski): Push settings and filtering logic below the HAL.
    423   bt_status_t status = hal::BluetoothGattInterface::Get()->
    424       StartScan(client_id_);
    425   if (status != BT_STATUS_SUCCESS) {
    426     LOG(ERROR) << "Failed to initiate scanning for client: " << client_id_;
    427     return false;
    428   }
    429 
    430   scan_started_ = true;
    431   return true;
    432 }
    433 
    434 bool LowEnergyClient::StopScan() {
    435   VLOG(2) << __func__;
    436 
    437   // TODO(armansito): We don't support batch scanning yet so call
    438   // StopRegularScanForClient directly. In the future we will need to
    439   // conditionally call a batch scan API here.
    440   bt_status_t status = hal::BluetoothGattInterface::Get()->
    441       StopScan(client_id_);
    442   if (status != BT_STATUS_SUCCESS) {
    443     LOG(ERROR) << "Failed to stop scan for client: " << client_id_;
    444     return false;
    445   }
    446 
    447   scan_started_ = false;
    448   return true;
    449 }
    450 
    451 bool LowEnergyClient::StartAdvertising(const AdvertiseSettings& settings,
    452                                        const AdvertiseData& advertise_data,
    453                                        const AdvertiseData& scan_response,
    454                                        const StatusCallback& callback) {
    455   VLOG(2) << __func__;
    456   lock_guard<mutex> lock(adv_fields_lock_);
    457 
    458   if (IsAdvertisingStarted()) {
    459     LOG(WARNING) << "Already advertising";
    460     return false;
    461   }
    462 
    463   if (IsStartingAdvertising()) {
    464     LOG(WARNING) << "StartAdvertising already pending";
    465     return false;
    466   }
    467 
    468   if (!advertise_data.IsValid()) {
    469     LOG(ERROR) << "Invalid advertising data";
    470     return false;
    471   }
    472 
    473   if (!scan_response.IsValid()) {
    474     LOG(ERROR) << "Invalid scan response data";
    475     return false;
    476   }
    477 
    478   CHECK(!adv_data_needs_update_.load());
    479   CHECK(!scan_rsp_needs_update_.load());
    480 
    481   adv_data_ = advertise_data;
    482   scan_response_ = scan_response;
    483   advertise_settings_ = settings;
    484 
    485   AdvertiseParams params;
    486   GetAdvertiseParams(settings, !scan_response_.data().empty(), &params);
    487 
    488   bt_status_t status = hal::BluetoothGattInterface::Get()->
    489       GetClientHALInterface()->multi_adv_enable(
    490           client_id_,
    491           params.min_interval,
    492           params.max_interval,
    493           params.event_type,
    494           kAdvertisingChannelAll,
    495           params.tx_power_level,
    496           params.timeout_s);
    497   if (status != BT_STATUS_SUCCESS) {
    498     LOG(ERROR) << "Failed to initiate call to enable multi-advertising";
    499     return false;
    500   }
    501 
    502   // Always update advertising data.
    503   adv_data_needs_update_ = true;
    504 
    505   // Update scan response only if it has data, since otherwise we just won't
    506   // send ADV_SCAN_IND.
    507   if (!scan_response_.data().empty())
    508     scan_rsp_needs_update_ = true;
    509 
    510   // OK to set this at the end since we're still holding |adv_fields_lock_|.
    511   adv_start_callback_.reset(new StatusCallback(callback));
    512 
    513   return true;
    514 }
    515 
    516 bool LowEnergyClient::StopAdvertising(const StatusCallback& callback) {
    517   VLOG(2) << __func__;
    518   lock_guard<mutex> lock(adv_fields_lock_);
    519 
    520   if (!IsAdvertisingStarted()) {
    521     LOG(ERROR) << "Not advertising";
    522     return false;
    523   }
    524 
    525   if (IsStoppingAdvertising()) {
    526     LOG(ERROR) << "StopAdvertising already pending";
    527     return false;
    528   }
    529 
    530   CHECK(!adv_start_callback_);
    531 
    532   bt_status_t status = hal::BluetoothGattInterface::Get()->
    533       GetClientHALInterface()->multi_adv_disable(client_id_);
    534   if (status != BT_STATUS_SUCCESS) {
    535     LOG(ERROR) << "Failed to initiate call to disable multi-advertising";
    536     return false;
    537   }
    538 
    539   // OK to set this at the end since we're still holding |adv_fields_lock_|.
    540   adv_stop_callback_.reset(new StatusCallback(callback));
    541 
    542   return true;
    543 }
    544 
    545 bool LowEnergyClient::IsAdvertisingStarted() const {
    546   return adv_started_.load();
    547 }
    548 
    549 bool LowEnergyClient::IsStartingAdvertising() const {
    550   return !IsAdvertisingStarted() && adv_start_callback_;
    551 }
    552 
    553 bool LowEnergyClient::IsStoppingAdvertising() const {
    554   return IsAdvertisingStarted() && adv_stop_callback_;
    555 }
    556 
    557 const UUID& LowEnergyClient::GetAppIdentifier() const {
    558   return app_identifier_;
    559 }
    560 
    561 int LowEnergyClient::GetInstanceId() const {
    562   return client_id_;
    563 }
    564 
    565 void LowEnergyClient::ScanResultCallback(
    566     hal::BluetoothGattInterface* gatt_iface,
    567     const bt_bdaddr_t& bda, int rssi, uint8_t* adv_data) {
    568   // Ignore scan results if this client didn't start a scan.
    569   if (!scan_started_.load())
    570     return;
    571 
    572   lock_guard<mutex> lock(delegate_mutex_);
    573   if (!delegate_)
    574     return;
    575 
    576   // TODO(armansito): Apply software filters here.
    577 
    578   size_t record_len = GetScanRecordLength(adv_data);
    579   std::vector<uint8_t> scan_record(adv_data, adv_data + record_len);
    580 
    581   ScanResult result(BtAddrString(&bda), scan_record, rssi);
    582 
    583   delegate_->OnScanResult(this, result);
    584 }
    585 
    586 void LowEnergyClient::ConnectCallback(
    587       hal::BluetoothGattInterface* gatt_iface, int conn_id, int status,
    588       int client_id, const bt_bdaddr_t& bda) {
    589   if (client_id != client_id_)
    590     return;
    591 
    592   VLOG(1) << __func__ << "client_id: " << client_id << " status: " << status;
    593 
    594   {
    595     lock_guard<mutex> lock(connection_fields_lock_);
    596     auto success = connection_ids_.emplace(bda, conn_id);
    597     if (!success.second) {
    598       LOG(ERROR) << __func__ << " Insertion into connection_ids_ failed!";
    599     }
    600   }
    601 
    602   if (delegate_)
    603     delegate_->OnConnectionState(this, status, BtAddrString(&bda).c_str(),
    604                                  true);
    605 }
    606 
    607 void LowEnergyClient::DisconnectCallback(
    608       hal::BluetoothGattInterface* gatt_iface, int conn_id, int status,
    609       int client_id, const bt_bdaddr_t& bda) {
    610   if (client_id != client_id_)
    611     return;
    612 
    613   VLOG(1) << __func__ << " client_id: " << client_id << " status: " << status;
    614   {
    615     lock_guard<mutex> lock(connection_fields_lock_);
    616     if (!connection_ids_.erase(bda)) {
    617       LOG(ERROR) << __func__ << " Erasing from connection_ids_ failed!";
    618     }
    619   }
    620 
    621   if (delegate_)
    622     delegate_->OnConnectionState(this, status, BtAddrString(&bda).c_str(),
    623                                  false);
    624 }
    625 
    626 void LowEnergyClient::MtuChangedCallback(
    627       hal::BluetoothGattInterface* gatt_iface, int conn_id, int status,
    628       int mtu) {
    629   VLOG(1) << __func__ << " conn_id: " << conn_id << " status: " << status
    630           << " mtu: " << mtu;
    631 
    632   const bt_bdaddr_t *bda = nullptr;
    633   {
    634     lock_guard<mutex> lock(connection_fields_lock_);
    635     for (auto& connection: connection_ids_) {
    636       if (connection.second == conn_id) {
    637         bda = &connection.first;
    638         break;
    639       }
    640     }
    641   }
    642 
    643   if (!bda)
    644     return;
    645 
    646   const char *addr = BtAddrString(bda).c_str();
    647   if (delegate_)
    648     delegate_->OnMtuChanged(this, status, addr, mtu);
    649 }
    650 
    651 void LowEnergyClient::MultiAdvEnableCallback(
    652     hal::BluetoothGattInterface* gatt_iface,
    653     int client_id, int status) {
    654   if (client_id != client_id_)
    655     return;
    656 
    657   lock_guard<mutex> lock(adv_fields_lock_);
    658 
    659   VLOG(1) << __func__ << "client_id: " << client_id << " status: " << status;
    660 
    661   CHECK(adv_start_callback_);
    662   CHECK(!adv_stop_callback_);
    663 
    664   // Terminate operation in case of error.
    665   if (status != BT_STATUS_SUCCESS) {
    666     LOG(ERROR) << "Failed to enable multi-advertising";
    667     InvokeAndClearStartCallback(GetBLEStatus(status));
    668     return;
    669   }
    670 
    671   // Now handle deferred tasks.
    672   HandleDeferredAdvertiseData(gatt_iface);
    673 }
    674 
    675 void LowEnergyClient::MultiAdvDataCallback(
    676     hal::BluetoothGattInterface* gatt_iface,
    677     int client_id, int status) {
    678   if (client_id != client_id_)
    679     return;
    680 
    681   lock_guard<mutex> lock(adv_fields_lock_);
    682 
    683   VLOG(1) << __func__ << "client_id: " << client_id << " status: " << status;
    684 
    685   is_setting_adv_data_ = false;
    686 
    687   // Terminate operation in case of error.
    688   if (status != BT_STATUS_SUCCESS) {
    689     LOG(ERROR) << "Failed to set advertising data";
    690     InvokeAndClearStartCallback(GetBLEStatus(status));
    691     return;
    692   }
    693 
    694   // Now handle deferred tasks.
    695   HandleDeferredAdvertiseData(gatt_iface);
    696 }
    697 
    698 void LowEnergyClient::MultiAdvDisableCallback(
    699     hal::BluetoothGattInterface* /* gatt_iface */,
    700     int client_id, int status) {
    701   if (client_id != client_id_)
    702     return;
    703 
    704   lock_guard<mutex> lock(adv_fields_lock_);
    705 
    706   VLOG(1) << __func__ << "client_id: " << client_id << " status: " << status;
    707 
    708   CHECK(!adv_start_callback_);
    709   CHECK(adv_stop_callback_);
    710 
    711   if (status == BT_STATUS_SUCCESS) {
    712     VLOG(1) << "Multi-advertising stopped for client_id: " << client_id;
    713     adv_started_ = false;
    714   } else {
    715     LOG(ERROR) << "Failed to stop multi-advertising";
    716   }
    717 
    718   InvokeAndClearStopCallback(GetBLEStatus(status));
    719 }
    720 
    721 bt_status_t LowEnergyClient::SetAdvertiseData(
    722     hal::BluetoothGattInterface* gatt_iface,
    723     const AdvertiseData& data,
    724     bool set_scan_rsp) {
    725   VLOG(2) << __func__;
    726 
    727   HALAdvertiseData hal_data;
    728 
    729   // TODO(armansito): The stack should check that the length is valid when other
    730   // fields inserted by the stack (e.g. flags, device name, tx-power) are taken
    731   // into account. At the moment we are skipping this check; this means that if
    732   // the given data is too long then the stack will truncate it.
    733   if (!ProcessAdvertiseData(data, &hal_data)) {
    734     LOG(ERROR) << "Malformed advertise data given";
    735     return BT_STATUS_FAIL;
    736   }
    737 
    738   if (is_setting_adv_data_.load()) {
    739     LOG(ERROR) << "Setting advertising data already in progress.";
    740     return BT_STATUS_FAIL;
    741   }
    742 
    743   // TODO(armansito): The length fields in the BTIF function below are signed
    744   // integers so a call to std::vector::size might get capped. This is very
    745   // unlikely anyway but it's safer to stop using signed-integer types for
    746   // length in APIs, so we should change that.
    747   bt_status_t status = gatt_iface->GetClientHALInterface()->
    748       multi_adv_set_inst_data(
    749           client_id_,
    750           set_scan_rsp,
    751           data.include_device_name(),
    752           data.include_tx_power_level(),
    753           0,  // This is what Bluetooth.apk current hardcodes for "appearance".
    754           hal_data.manufacturer_data.size(),
    755           reinterpret_cast<char*>(hal_data.manufacturer_data.data()),
    756           hal_data.service_data.size(),
    757           reinterpret_cast<char*>(hal_data.service_data.data()),
    758           hal_data.service_uuid.size(),
    759           reinterpret_cast<char*>(hal_data.service_uuid.data()));
    760 
    761   if (status != BT_STATUS_SUCCESS) {
    762     LOG(ERROR) << "Failed to set instance advertising data.";
    763     return status;
    764   }
    765 
    766   if (set_scan_rsp)
    767     scan_rsp_needs_update_ = false;
    768   else
    769     adv_data_needs_update_ = false;
    770 
    771   is_setting_adv_data_ = true;
    772 
    773   return status;
    774 }
    775 
    776 void LowEnergyClient::HandleDeferredAdvertiseData(
    777     hal::BluetoothGattInterface* gatt_iface) {
    778   VLOG(2) << __func__;
    779 
    780   CHECK(!IsAdvertisingStarted());
    781   CHECK(!IsStoppingAdvertising());
    782   CHECK(IsStartingAdvertising());
    783   CHECK(!is_setting_adv_data_.load());
    784 
    785   if (adv_data_needs_update_.load()) {
    786     bt_status_t status = SetAdvertiseData(gatt_iface, adv_data_, false);
    787     if (status != BT_STATUS_SUCCESS) {
    788       LOG(ERROR) << "Failed setting advertisement data";
    789       InvokeAndClearStartCallback(GetBLEStatus(status));
    790     }
    791     return;
    792   }
    793 
    794   if (scan_rsp_needs_update_.load()) {
    795     bt_status_t status = SetAdvertiseData(gatt_iface, scan_response_, true);
    796     if (status != BT_STATUS_SUCCESS) {
    797       LOG(ERROR) << "Failed setting scan response data";
    798       InvokeAndClearStartCallback(GetBLEStatus(status));
    799     }
    800     return;
    801   }
    802 
    803   // All pending tasks are complete. Report success.
    804   adv_started_ = true;
    805   InvokeAndClearStartCallback(BLE_STATUS_SUCCESS);
    806 }
    807 
    808 void LowEnergyClient::InvokeAndClearStartCallback(BLEStatus status) {
    809   adv_data_needs_update_ = false;
    810   scan_rsp_needs_update_ = false;
    811 
    812   // We allow NULL callbacks.
    813   if (*adv_start_callback_)
    814     (*adv_start_callback_)(status);
    815 
    816   adv_start_callback_ = nullptr;
    817 }
    818 
    819 void LowEnergyClient::InvokeAndClearStopCallback(BLEStatus status) {
    820   // We allow NULL callbacks.
    821   if (*adv_stop_callback_)
    822     (*adv_stop_callback_)(status);
    823 
    824   adv_stop_callback_ = nullptr;
    825 }
    826 
    827 // LowEnergyClientFactory implementation
    828 // ========================================================
    829 
    830 LowEnergyClientFactory::LowEnergyClientFactory(Adapter& adapter)
    831     : adapter_(adapter) {
    832   hal::BluetoothGattInterface::Get()->AddClientObserver(this);
    833 }
    834 
    835 LowEnergyClientFactory::~LowEnergyClientFactory() {
    836   hal::BluetoothGattInterface::Get()->RemoveClientObserver(this);
    837 }
    838 
    839 bool LowEnergyClientFactory::RegisterInstance(
    840     const UUID& uuid,
    841     const RegisterCallback& callback) {
    842   VLOG(1) << __func__ << " - UUID: " << uuid.ToString();
    843   lock_guard<mutex> lock(pending_calls_lock_);
    844 
    845   if (pending_calls_.find(uuid) != pending_calls_.end()) {
    846     LOG(ERROR) << "Low-Energy client with given UUID already registered - "
    847                << "UUID: " << uuid.ToString();
    848     return false;
    849   }
    850 
    851   const btgatt_client_interface_t* hal_iface =
    852       hal::BluetoothGattInterface::Get()->GetClientHALInterface();
    853   bt_uuid_t app_uuid = uuid.GetBlueDroid();
    854 
    855   if (hal_iface->register_client(&app_uuid) != BT_STATUS_SUCCESS)
    856     return false;
    857 
    858   pending_calls_[uuid] = callback;
    859 
    860   return true;
    861 }
    862 
    863 void LowEnergyClientFactory::RegisterClientCallback(
    864     hal::BluetoothGattInterface* gatt_iface,
    865     int status, int client_id,
    866     const bt_uuid_t& app_uuid) {
    867   UUID uuid(app_uuid);
    868 
    869   VLOG(1) << __func__ << " - UUID: " << uuid.ToString();
    870   lock_guard<mutex> lock(pending_calls_lock_);
    871 
    872   auto iter = pending_calls_.find(uuid);
    873   if (iter == pending_calls_.end()) {
    874     VLOG(1) << "Ignoring callback for unknown app_id: " << uuid.ToString();
    875     return;
    876   }
    877 
    878   // No need to construct a client if the call wasn't successful.
    879   std::unique_ptr<LowEnergyClient> client;
    880   BLEStatus result = BLE_STATUS_FAILURE;
    881   if (status == BT_STATUS_SUCCESS) {
    882     client.reset(new LowEnergyClient(adapter_, uuid, client_id));
    883 
    884     gatt_iface->AddClientObserver(client.get());
    885 
    886     result = BLE_STATUS_SUCCESS;
    887   }
    888 
    889   // Notify the result via the result callback.
    890   iter->second(result, uuid, std::move(client));
    891 
    892   pending_calls_.erase(iter);
    893 }
    894 
    895 }  // namespace bluetooth
    896