123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244 |
- // Copyright 2016 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "device/bluetooth/bluetooth_remote_gatt_service_win.h"
- #include <memory>
- #include <utility>
- #include "base/bind.h"
- #include "base/containers/contains.h"
- #include "base/memory/ptr_util.h"
- #include "device/bluetooth/bluetooth_adapter_win.h"
- #include "device/bluetooth/bluetooth_device_win.h"
- #include "device/bluetooth/bluetooth_remote_gatt_characteristic_win.h"
- #include "device/bluetooth/bluetooth_task_manager_win.h"
- namespace device {
- BluetoothRemoteGattServiceWin::BluetoothRemoteGattServiceWin(
- BluetoothDeviceWin* device,
- base::FilePath service_path,
- BluetoothUUID service_uuid,
- uint16_t service_attribute_handle,
- bool is_primary,
- BluetoothRemoteGattServiceWin* parent_service,
- scoped_refptr<base::SequencedTaskRunner> ui_task_runner)
- : device_(device),
- service_path_(service_path),
- service_uuid_(service_uuid),
- service_attribute_handle_(service_attribute_handle),
- is_primary_(is_primary),
- parent_service_(parent_service),
- ui_task_runner_(std::move(ui_task_runner)) {
- DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
- DCHECK(!service_path_.empty());
- DCHECK(service_uuid_.IsValid());
- DCHECK(service_attribute_handle_);
- DCHECK(device_);
- if (!is_primary_)
- DCHECK(parent_service_);
- adapter_ = static_cast<BluetoothAdapterWin*>(device_->GetAdapter());
- DCHECK(adapter_);
- task_manager_ = adapter_->GetWinBluetoothTaskManager();
- DCHECK(task_manager_);
- service_identifier_ = device_->GetIdentifier() + "/" + service_uuid_.value() +
- "_" + std::to_string(service_attribute_handle_);
- Update();
- }
- BluetoothRemoteGattServiceWin::~BluetoothRemoteGattServiceWin() {
- DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
- ClearIncludedCharacteristics();
- adapter_->NotifyGattServiceRemoved(this);
- }
- std::string BluetoothRemoteGattServiceWin::GetIdentifier() const {
- return service_identifier_;
- }
- BluetoothUUID BluetoothRemoteGattServiceWin::GetUUID() const {
- return const_cast<BluetoothUUID&>(service_uuid_);
- }
- bool BluetoothRemoteGattServiceWin::IsPrimary() const {
- return is_primary_;
- }
- BluetoothDevice* BluetoothRemoteGattServiceWin::GetDevice() const {
- return device_;
- }
- std::vector<BluetoothRemoteGattService*>
- BluetoothRemoteGattServiceWin::GetIncludedServices() const {
- NOTIMPLEMENTED();
- // TODO(crbug.com/590008): Needs implementation.
- return std::vector<BluetoothRemoteGattService*>();
- }
- void BluetoothRemoteGattServiceWin::GattCharacteristicDiscoveryComplete(
- BluetoothRemoteGattCharacteristicWin* characteristic) {
- DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
- DCHECK(base::Contains(characteristics_, characteristic->GetIdentifier()));
- discovery_completed_included_characteristics_.insert(
- characteristic->GetIdentifier());
- SetDiscoveryComplete(characteristics_.size() ==
- discovery_completed_included_characteristics_.size());
- adapter_->NotifyGattCharacteristicAdded(characteristic);
- NotifyGattServiceDiscoveryCompleteIfNecessary();
- }
- void BluetoothRemoteGattServiceWin::Update() {
- DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
- ++discovery_pending_count_;
- task_manager_->PostGetGattIncludedCharacteristics(
- service_path_, service_uuid_, service_attribute_handle_,
- base::BindOnce(
- &BluetoothRemoteGattServiceWin::OnGetIncludedCharacteristics,
- weak_ptr_factory_.GetWeakPtr()));
- }
- void BluetoothRemoteGattServiceWin::OnGetIncludedCharacteristics(
- std::unique_ptr<BTH_LE_GATT_CHARACTERISTIC> characteristics,
- uint16_t num,
- HRESULT hr) {
- DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
- if (--discovery_pending_count_ != 0)
- return;
- UpdateIncludedCharacteristics(characteristics.get(), num);
- SetDiscoveryComplete(characteristics_.size() ==
- discovery_completed_included_characteristics_.size());
- // In case there are new included characterisitics that haven't been
- // discovered yet, observers should be notified once that the discovery of
- // these characteristics is complete. Hence the discovery complete flag is
- // reset.
- if (!IsDiscoveryComplete()) {
- discovery_complete_notified_ = false;
- return;
- }
- adapter_->NotifyGattServiceChanged(this);
- NotifyGattServiceDiscoveryCompleteIfNecessary();
- }
- void BluetoothRemoteGattServiceWin::UpdateIncludedCharacteristics(
- PBTH_LE_GATT_CHARACTERISTIC characteristics,
- uint16_t num) {
- if (num == 0) {
- if (!characteristics_.empty()) {
- ClearIncludedCharacteristics();
- adapter_->NotifyGattServiceChanged(this);
- }
- return;
- }
- // First, remove characteristics that no longer exist.
- std::vector<std::string> to_be_removed;
- for (const auto& c : characteristics_) {
- if (!DoesCharacteristicExist(
- characteristics, num,
- static_cast<BluetoothRemoteGattCharacteristicWin*>(
- c.second.get()))) {
- to_be_removed.push_back(c.second->GetIdentifier());
- }
- }
- for (const auto& id : to_be_removed) {
- RemoveIncludedCharacteristic(id);
- }
- // Update previously known characteristics.
- for (auto& c : characteristics_) {
- static_cast<BluetoothRemoteGattCharacteristicWin*>(c.second.get())
- ->Update();
- }
- // Return if no new characteristics have been added.
- if (characteristics_.size() == num)
- return;
- // Add new characteristics.
- for (uint16_t i = 0; i < num; i++) {
- if (!IsCharacteristicDiscovered(characteristics[i].CharacteristicUuid,
- characteristics[i].AttributeHandle)) {
- PBTH_LE_GATT_CHARACTERISTIC info = new BTH_LE_GATT_CHARACTERISTIC();
- *info = characteristics[i];
- AddCharacteristic(std::make_unique<BluetoothRemoteGattCharacteristicWin>(
- this, info, ui_task_runner_));
- }
- }
- }
- void BluetoothRemoteGattServiceWin::
- NotifyGattServiceDiscoveryCompleteIfNecessary() {
- if (IsDiscoveryComplete() && !discovery_complete_notified_) {
- discovery_complete_notified_ = true;
- device_->GattServiceDiscoveryComplete(this);
- }
- }
- bool BluetoothRemoteGattServiceWin::IsCharacteristicDiscovered(
- const BTH_LE_UUID& uuid,
- uint16_t attribute_handle) {
- BluetoothUUID bt_uuid =
- BluetoothTaskManagerWin::BluetoothLowEnergyUuidToBluetoothUuid(uuid);
- for (const auto& c : characteristics_) {
- if (bt_uuid == c.second->GetUUID() &&
- attribute_handle ==
- static_cast<BluetoothRemoteGattCharacteristicWin*>(c.second.get())
- ->GetAttributeHandle()) {
- return true;
- }
- }
- return false;
- }
- bool BluetoothRemoteGattServiceWin::DoesCharacteristicExist(
- PBTH_LE_GATT_CHARACTERISTIC characteristics,
- uint16_t num,
- BluetoothRemoteGattCharacteristicWin* characteristic) {
- for (uint16_t i = 0; i < num; i++) {
- BluetoothUUID uuid =
- BluetoothTaskManagerWin::BluetoothLowEnergyUuidToBluetoothUuid(
- characteristics[i].CharacteristicUuid);
- if (characteristic->GetUUID() == uuid &&
- characteristic->GetAttributeHandle() ==
- characteristics[i].AttributeHandle) {
- return true;
- }
- }
- return false;
- }
- void BluetoothRemoteGattServiceWin::RemoveIncludedCharacteristic(
- std::string identifier) {
- discovery_completed_included_characteristics_.erase(identifier);
- // Explicitly moving the to be deleted characteristic into a local variable,
- // so that we can erase the entry from |characteristics_| before calling the
- // characteristic's destructor. This will ensure that any call to
- // GetCharacteristics() won't contain an entry corresponding to |identifier|.
- // Note: `characteristics_.erase(identifier);` would not guarantee this.
- DCHECK(base::Contains(characteristics_, identifier));
- auto iter = characteristics_.find(identifier);
- auto pair = std::move(*iter);
- characteristics_.erase(iter);
- }
- void BluetoothRemoteGattServiceWin::ClearIncludedCharacteristics() {
- discovery_completed_included_characteristics_.clear();
- // Explicitly reset to null to ensure that calling GetCharacteristics() in
- // GattCharacteristicRemoved() will return an empty collection.
- // Note: `characteristics_.clear();` would not guarantee this.
- std::exchange(characteristics_, {});
- }
- } // namespace device.
|