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(), ¶ms); 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