bluetooth_remote_gatt_service_win.cc 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. // Copyright 2016 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "device/bluetooth/bluetooth_remote_gatt_service_win.h"
  5. #include <memory>
  6. #include <utility>
  7. #include "base/bind.h"
  8. #include "base/containers/contains.h"
  9. #include "base/memory/ptr_util.h"
  10. #include "device/bluetooth/bluetooth_adapter_win.h"
  11. #include "device/bluetooth/bluetooth_device_win.h"
  12. #include "device/bluetooth/bluetooth_remote_gatt_characteristic_win.h"
  13. #include "device/bluetooth/bluetooth_task_manager_win.h"
  14. namespace device {
  15. BluetoothRemoteGattServiceWin::BluetoothRemoteGattServiceWin(
  16. BluetoothDeviceWin* device,
  17. base::FilePath service_path,
  18. BluetoothUUID service_uuid,
  19. uint16_t service_attribute_handle,
  20. bool is_primary,
  21. BluetoothRemoteGattServiceWin* parent_service,
  22. scoped_refptr<base::SequencedTaskRunner> ui_task_runner)
  23. : device_(device),
  24. service_path_(service_path),
  25. service_uuid_(service_uuid),
  26. service_attribute_handle_(service_attribute_handle),
  27. is_primary_(is_primary),
  28. parent_service_(parent_service),
  29. ui_task_runner_(std::move(ui_task_runner)) {
  30. DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
  31. DCHECK(!service_path_.empty());
  32. DCHECK(service_uuid_.IsValid());
  33. DCHECK(service_attribute_handle_);
  34. DCHECK(device_);
  35. if (!is_primary_)
  36. DCHECK(parent_service_);
  37. adapter_ = static_cast<BluetoothAdapterWin*>(device_->GetAdapter());
  38. DCHECK(adapter_);
  39. task_manager_ = adapter_->GetWinBluetoothTaskManager();
  40. DCHECK(task_manager_);
  41. service_identifier_ = device_->GetIdentifier() + "/" + service_uuid_.value() +
  42. "_" + std::to_string(service_attribute_handle_);
  43. Update();
  44. }
  45. BluetoothRemoteGattServiceWin::~BluetoothRemoteGattServiceWin() {
  46. DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
  47. ClearIncludedCharacteristics();
  48. adapter_->NotifyGattServiceRemoved(this);
  49. }
  50. std::string BluetoothRemoteGattServiceWin::GetIdentifier() const {
  51. return service_identifier_;
  52. }
  53. BluetoothUUID BluetoothRemoteGattServiceWin::GetUUID() const {
  54. return const_cast<BluetoothUUID&>(service_uuid_);
  55. }
  56. bool BluetoothRemoteGattServiceWin::IsPrimary() const {
  57. return is_primary_;
  58. }
  59. BluetoothDevice* BluetoothRemoteGattServiceWin::GetDevice() const {
  60. return device_;
  61. }
  62. std::vector<BluetoothRemoteGattService*>
  63. BluetoothRemoteGattServiceWin::GetIncludedServices() const {
  64. NOTIMPLEMENTED();
  65. // TODO(crbug.com/590008): Needs implementation.
  66. return std::vector<BluetoothRemoteGattService*>();
  67. }
  68. void BluetoothRemoteGattServiceWin::GattCharacteristicDiscoveryComplete(
  69. BluetoothRemoteGattCharacteristicWin* characteristic) {
  70. DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
  71. DCHECK(base::Contains(characteristics_, characteristic->GetIdentifier()));
  72. discovery_completed_included_characteristics_.insert(
  73. characteristic->GetIdentifier());
  74. SetDiscoveryComplete(characteristics_.size() ==
  75. discovery_completed_included_characteristics_.size());
  76. adapter_->NotifyGattCharacteristicAdded(characteristic);
  77. NotifyGattServiceDiscoveryCompleteIfNecessary();
  78. }
  79. void BluetoothRemoteGattServiceWin::Update() {
  80. DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
  81. ++discovery_pending_count_;
  82. task_manager_->PostGetGattIncludedCharacteristics(
  83. service_path_, service_uuid_, service_attribute_handle_,
  84. base::BindOnce(
  85. &BluetoothRemoteGattServiceWin::OnGetIncludedCharacteristics,
  86. weak_ptr_factory_.GetWeakPtr()));
  87. }
  88. void BluetoothRemoteGattServiceWin::OnGetIncludedCharacteristics(
  89. std::unique_ptr<BTH_LE_GATT_CHARACTERISTIC> characteristics,
  90. uint16_t num,
  91. HRESULT hr) {
  92. DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
  93. if (--discovery_pending_count_ != 0)
  94. return;
  95. UpdateIncludedCharacteristics(characteristics.get(), num);
  96. SetDiscoveryComplete(characteristics_.size() ==
  97. discovery_completed_included_characteristics_.size());
  98. // In case there are new included characterisitics that haven't been
  99. // discovered yet, observers should be notified once that the discovery of
  100. // these characteristics is complete. Hence the discovery complete flag is
  101. // reset.
  102. if (!IsDiscoveryComplete()) {
  103. discovery_complete_notified_ = false;
  104. return;
  105. }
  106. adapter_->NotifyGattServiceChanged(this);
  107. NotifyGattServiceDiscoveryCompleteIfNecessary();
  108. }
  109. void BluetoothRemoteGattServiceWin::UpdateIncludedCharacteristics(
  110. PBTH_LE_GATT_CHARACTERISTIC characteristics,
  111. uint16_t num) {
  112. if (num == 0) {
  113. if (!characteristics_.empty()) {
  114. ClearIncludedCharacteristics();
  115. adapter_->NotifyGattServiceChanged(this);
  116. }
  117. return;
  118. }
  119. // First, remove characteristics that no longer exist.
  120. std::vector<std::string> to_be_removed;
  121. for (const auto& c : characteristics_) {
  122. if (!DoesCharacteristicExist(
  123. characteristics, num,
  124. static_cast<BluetoothRemoteGattCharacteristicWin*>(
  125. c.second.get()))) {
  126. to_be_removed.push_back(c.second->GetIdentifier());
  127. }
  128. }
  129. for (const auto& id : to_be_removed) {
  130. RemoveIncludedCharacteristic(id);
  131. }
  132. // Update previously known characteristics.
  133. for (auto& c : characteristics_) {
  134. static_cast<BluetoothRemoteGattCharacteristicWin*>(c.second.get())
  135. ->Update();
  136. }
  137. // Return if no new characteristics have been added.
  138. if (characteristics_.size() == num)
  139. return;
  140. // Add new characteristics.
  141. for (uint16_t i = 0; i < num; i++) {
  142. if (!IsCharacteristicDiscovered(characteristics[i].CharacteristicUuid,
  143. characteristics[i].AttributeHandle)) {
  144. PBTH_LE_GATT_CHARACTERISTIC info = new BTH_LE_GATT_CHARACTERISTIC();
  145. *info = characteristics[i];
  146. AddCharacteristic(std::make_unique<BluetoothRemoteGattCharacteristicWin>(
  147. this, info, ui_task_runner_));
  148. }
  149. }
  150. }
  151. void BluetoothRemoteGattServiceWin::
  152. NotifyGattServiceDiscoveryCompleteIfNecessary() {
  153. if (IsDiscoveryComplete() && !discovery_complete_notified_) {
  154. discovery_complete_notified_ = true;
  155. device_->GattServiceDiscoveryComplete(this);
  156. }
  157. }
  158. bool BluetoothRemoteGattServiceWin::IsCharacteristicDiscovered(
  159. const BTH_LE_UUID& uuid,
  160. uint16_t attribute_handle) {
  161. BluetoothUUID bt_uuid =
  162. BluetoothTaskManagerWin::BluetoothLowEnergyUuidToBluetoothUuid(uuid);
  163. for (const auto& c : characteristics_) {
  164. if (bt_uuid == c.second->GetUUID() &&
  165. attribute_handle ==
  166. static_cast<BluetoothRemoteGattCharacteristicWin*>(c.second.get())
  167. ->GetAttributeHandle()) {
  168. return true;
  169. }
  170. }
  171. return false;
  172. }
  173. bool BluetoothRemoteGattServiceWin::DoesCharacteristicExist(
  174. PBTH_LE_GATT_CHARACTERISTIC characteristics,
  175. uint16_t num,
  176. BluetoothRemoteGattCharacteristicWin* characteristic) {
  177. for (uint16_t i = 0; i < num; i++) {
  178. BluetoothUUID uuid =
  179. BluetoothTaskManagerWin::BluetoothLowEnergyUuidToBluetoothUuid(
  180. characteristics[i].CharacteristicUuid);
  181. if (characteristic->GetUUID() == uuid &&
  182. characteristic->GetAttributeHandle() ==
  183. characteristics[i].AttributeHandle) {
  184. return true;
  185. }
  186. }
  187. return false;
  188. }
  189. void BluetoothRemoteGattServiceWin::RemoveIncludedCharacteristic(
  190. std::string identifier) {
  191. discovery_completed_included_characteristics_.erase(identifier);
  192. // Explicitly moving the to be deleted characteristic into a local variable,
  193. // so that we can erase the entry from |characteristics_| before calling the
  194. // characteristic's destructor. This will ensure that any call to
  195. // GetCharacteristics() won't contain an entry corresponding to |identifier|.
  196. // Note: `characteristics_.erase(identifier);` would not guarantee this.
  197. DCHECK(base::Contains(characteristics_, identifier));
  198. auto iter = characteristics_.find(identifier);
  199. auto pair = std::move(*iter);
  200. characteristics_.erase(iter);
  201. }
  202. void BluetoothRemoteGattServiceWin::ClearIncludedCharacteristics() {
  203. discovery_completed_included_characteristics_.clear();
  204. // Explicitly reset to null to ensure that calling GetCharacteristics() in
  205. // GattCharacteristicRemoved() will return an empty collection.
  206. // Note: `characteristics_.clear();` would not guarantee this.
  207. std::exchange(characteristics_, {});
  208. }
  209. } // namespace device.