low_energy_scanner.cc 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. //
  2. // Copyright 2016 The Android Open Source Project
  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. #include "service/low_energy_scanner.h"
  17. #include "service/adapter.h"
  18. #include "service/logging_helpers.h"
  19. #include "stack/include/bt_types.h"
  20. #include "stack/include/hcidefs.h"
  21. #include <base/bind.h>
  22. #include <base/callback.h>
  23. #include <base/logging.h>
  24. using std::lock_guard;
  25. using std::mutex;
  26. namespace bluetooth {
  27. namespace {
  28. // 31 + 31 for advertising data and scan response. This is the maximum length
  29. // TODO(armansito): Fix the HAL to return a concatenated blob that contains the
  30. // true length of each field and also provide a length parameter so that we
  31. // can support advertising length extensions in the future.
  32. const size_t kScanRecordLength = 62;
  33. // Returns the length of the given scan record array. We have to calculate this
  34. // based on the maximum possible data length and the TLV data. See TODO above
  35. // |kScanRecordLength|.
  36. size_t GetScanRecordLength(std::vector<uint8_t> bytes) {
  37. for (size_t i = 0, field_len = 0; i < kScanRecordLength;
  38. i += (field_len + 1)) {
  39. field_len = bytes[i];
  40. // Assert here that the data returned from the stack is correctly formatted
  41. // in TLV form and that the length of the current field won't exceed the
  42. // total data length.
  43. CHECK(i + field_len < kScanRecordLength);
  44. // If the field length is zero and we haven't reached the maximum length,
  45. // then we have found the length, as the stack will pad the data with zeros
  46. // accordingly.
  47. if (field_len == 0) return i;
  48. }
  49. // We have reached the end.
  50. return kScanRecordLength;
  51. }
  52. } // namespace
  53. // LowEnergyScanner implementation
  54. // ========================================================
  55. LowEnergyScanner::LowEnergyScanner(Adapter& adapter, const Uuid& uuid,
  56. int scanner_id)
  57. : adapter_(adapter),
  58. app_identifier_(uuid),
  59. scanner_id_(scanner_id),
  60. scan_started_(false),
  61. delegate_(nullptr) {}
  62. LowEnergyScanner::~LowEnergyScanner() {
  63. // Automatically unregister the scanner.
  64. VLOG(1) << "LowEnergyScanner unregistering scanner: " << scanner_id_;
  65. // Unregister as observer so we no longer receive any callbacks.
  66. hal::BluetoothGattInterface::Get()->RemoveScannerObserver(this);
  67. hal::BluetoothGattInterface::Get()->GetScannerHALInterface()->Unregister(
  68. scanner_id_);
  69. // Stop any scans started by this client.
  70. if (scan_started_.load()) StopScan();
  71. }
  72. void LowEnergyScanner::SetDelegate(Delegate* delegate) {
  73. lock_guard<mutex> lock(delegate_mutex_);
  74. delegate_ = delegate;
  75. }
  76. bool LowEnergyScanner::StartScan(const ScanSettings& settings,
  77. const std::vector<ScanFilter>& filters) {
  78. VLOG(2) << __func__;
  79. // Cannot start a scan if the adapter is not enabled.
  80. if (!adapter_.IsEnabled()) {
  81. LOG(ERROR) << "Cannot scan while Bluetooth is disabled";
  82. return false;
  83. }
  84. // TODO(jpawlowski): Push settings and filtering logic below the HAL.
  85. bt_status_t status =
  86. hal::BluetoothGattInterface::Get()->StartScan(scanner_id_);
  87. if (status != BT_STATUS_SUCCESS) {
  88. LOG(ERROR) << "Failed to initiate scanning for client: " << scanner_id_;
  89. return false;
  90. }
  91. scan_started_ = true;
  92. return true;
  93. }
  94. bool LowEnergyScanner::StopScan() {
  95. VLOG(2) << __func__;
  96. // TODO(armansito): We don't support batch scanning yet so call
  97. // StopRegularScanForClient directly. In the future we will need to
  98. // conditionally call a batch scan API here.
  99. bt_status_t status =
  100. hal::BluetoothGattInterface::Get()->StopScan(scanner_id_);
  101. if (status != BT_STATUS_SUCCESS) {
  102. LOG(ERROR) << "Failed to stop scan for client: " << scanner_id_;
  103. return false;
  104. }
  105. scan_started_ = false;
  106. return true;
  107. }
  108. const Uuid& LowEnergyScanner::GetAppIdentifier() const {
  109. return app_identifier_;
  110. }
  111. int LowEnergyScanner::GetInstanceId() const { return scanner_id_; }
  112. void LowEnergyScanner::ScanResultCallback(
  113. hal::BluetoothGattInterface* gatt_iface, const RawAddress& bda, int rssi,
  114. std::vector<uint8_t> adv_data) {
  115. // Ignore scan results if this client didn't start a scan.
  116. if (!scan_started_.load()) return;
  117. lock_guard<mutex> lock(delegate_mutex_);
  118. if (!delegate_) return;
  119. // TODO(armansito): Apply software filters here.
  120. size_t record_len = GetScanRecordLength(adv_data);
  121. std::vector<uint8_t> scan_record(adv_data.begin(),
  122. adv_data.begin() + record_len);
  123. ScanResult result(BtAddrString(&bda), scan_record, rssi);
  124. delegate_->OnScanResult(this, result);
  125. }
  126. // LowEnergyScannerFactory implementation
  127. // ========================================================
  128. LowEnergyScannerFactory::LowEnergyScannerFactory(Adapter& adapter)
  129. : adapter_(adapter) {
  130. hal::BluetoothGattInterface::Get()->AddScannerObserver(this);
  131. }
  132. LowEnergyScannerFactory::~LowEnergyScannerFactory() {
  133. hal::BluetoothGattInterface::Get()->RemoveScannerObserver(this);
  134. }
  135. bool LowEnergyScannerFactory::RegisterInstance(
  136. const Uuid& uuid, const RegisterCallback& callback) {
  137. VLOG(1) << __func__ << " - Uuid: " << uuid.ToString();
  138. lock_guard<mutex> lock(pending_calls_lock_);
  139. if (pending_calls_.find(uuid) != pending_calls_.end()) {
  140. LOG(ERROR) << "Low-Energy scanner with given Uuid already registered - "
  141. << "Uuid: " << uuid.ToString();
  142. return false;
  143. }
  144. BleScannerInterface* hal_iface =
  145. hal::BluetoothGattInterface::Get()->GetScannerHALInterface();
  146. hal_iface->RegisterScanner(
  147. base::Bind(&LowEnergyScannerFactory::RegisterScannerCallback,
  148. base::Unretained(this), callback, uuid));
  149. pending_calls_.insert(uuid);
  150. return true;
  151. }
  152. void LowEnergyScannerFactory::RegisterScannerCallback(
  153. const RegisterCallback& callback, const Uuid& app_uuid, uint8_t scanner_id,
  154. uint8_t status) {
  155. Uuid uuid(app_uuid);
  156. VLOG(1) << __func__ << " - Uuid: " << uuid.ToString();
  157. lock_guard<mutex> lock(pending_calls_lock_);
  158. auto iter = pending_calls_.find(uuid);
  159. if (iter == pending_calls_.end()) {
  160. VLOG(1) << "Ignoring callback for unknown app_id: " << uuid.ToString();
  161. return;
  162. }
  163. // No need to construct a scanner if the call wasn't successful.
  164. std::unique_ptr<LowEnergyScanner> scanner;
  165. BLEStatus result = BLE_STATUS_FAILURE;
  166. if (status == BT_STATUS_SUCCESS) {
  167. scanner.reset(new LowEnergyScanner(adapter_, uuid, scanner_id));
  168. hal::BluetoothGattInterface::Get()->AddScannerObserver(scanner.get());
  169. result = BLE_STATUS_SUCCESS;
  170. }
  171. // Notify the result via the result callback.
  172. callback(result, app_uuid, std::move(scanner));
  173. pending_calls_.erase(iter);
  174. }
  175. } // namespace bluetooth