Index: device/bluetooth/bluetooth_remote_gatt_service_win.cc |
diff --git a/device/bluetooth/bluetooth_remote_gatt_service_win.cc b/device/bluetooth/bluetooth_remote_gatt_service_win.cc |
index 0c93588b92d7d7f67b7968a5ec26145569265331..19064eb67da44106d74581c238c8aed0acd5f950 100644 |
--- a/device/bluetooth/bluetooth_remote_gatt_service_win.cc |
+++ b/device/bluetooth/bluetooth_remote_gatt_service_win.cc |
@@ -4,7 +4,14 @@ |
#include "device/bluetooth/bluetooth_remote_gatt_service_win.h" |
+#include "base/bind.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, |
@@ -13,13 +20,16 @@ BluetoothRemoteGattServiceWin::BluetoothRemoteGattServiceWin( |
bool is_primary, |
BluetoothRemoteGattServiceWin* parent_service, |
scoped_refptr<base::SequencedTaskRunner>& ui_task_runner) |
- : service_path_(service_path), |
- device_(device), |
+ : 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_(ui_task_runner) { |
+ ui_task_runner_(ui_task_runner), |
+ discovery_complete_notified_(false), |
+ included_characteristics_discovered_(false), |
+ weak_ptr_factory_(this) { |
DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); |
DCHECK(!service_path_.empty()); |
DCHECK(service_uuid_.IsValid()); |
@@ -27,18 +37,24 @@ BluetoothRemoteGattServiceWin::BluetoothRemoteGattServiceWin( |
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() {} |
+BluetoothRemoteGattServiceWin::~BluetoothRemoteGattServiceWin() { |
+ DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); |
+ |
+ adapter_->NotifyGattServiceRemoved(this); |
+} |
std::string BluetoothRemoteGattServiceWin::GetIdentifier() const { |
- std::string identifier = |
- service_uuid_.value() + "_" + std::to_string(service_attribute_handle_); |
- if (is_primary_) |
- return device_->GetIdentifier() + "/" + identifier; |
- else |
- return parent_service_->GetIdentifier() + "/" + identifier; |
+ return service_identifier_; |
} |
BluetoothUUID BluetoothRemoteGattServiceWin::GetUUID() const { |
@@ -59,19 +75,25 @@ BluetoothDevice* BluetoothRemoteGattServiceWin::GetDevice() const { |
std::vector<BluetoothGattCharacteristic*> |
BluetoothRemoteGattServiceWin::GetCharacteristics() const { |
- NOTIMPLEMENTED(); |
- return std::vector<BluetoothGattCharacteristic*>(); |
+ std::vector<BluetoothGattCharacteristic*> has_characteristics; |
+ for (const auto& c : included_characteristics_) |
+ has_characteristics.push_back(c.second.get()); |
+ return has_characteristics; |
} |
std::vector<BluetoothGattService*> |
BluetoothRemoteGattServiceWin::GetIncludedServices() const { |
NOTIMPLEMENTED(); |
+ // TODO(crbug.com/590008): Needs implementation. |
scheib
2016/02/26 04:56:17
Thanks for issue. Please always have issues block
|
return std::vector<BluetoothGattService*>(); |
} |
BluetoothGattCharacteristic* BluetoothRemoteGattServiceWin::GetCharacteristic( |
const std::string& identifier) const { |
- NOTIMPLEMENTED(); |
+ GattCharacteristicsMap::const_iterator it = |
+ included_characteristics_.find(identifier); |
+ if (it != included_characteristics_.end()) |
+ return it->second.get(); |
return nullptr; |
} |
@@ -101,13 +123,134 @@ void BluetoothRemoteGattServiceWin::Unregister( |
error_callback.Run(); |
} |
+void BluetoothRemoteGattServiceWin::GattCharacteristicDiscoveryComplete( |
+ BluetoothRemoteGattCharacteristicWin* characteristic) { |
+ DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); |
+ DCHECK(included_characteristics_.find(characteristic->GetIdentifier()) != |
+ included_characteristics_.end()); |
+ |
+ discovery_completed_included_charateristics_.insert( |
+ characteristic->GetIdentifier()); |
+ adapter_->NotifyGattCharacteristicAdded(characteristic); |
+ NotifyGattDiscoveryCompleteForServiceIfNecessary(); |
+} |
+ |
void BluetoothRemoteGattServiceWin::Update() { |
DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); |
- NOTIMPLEMENTED(); |
+ |
+ task_manager_->PostGetGattIncludedCharacteristics( |
+ service_path_, service_uuid_, service_attribute_handle_, |
+ base::Bind(&BluetoothRemoteGattServiceWin::OnGetIncludedCharacteristics, |
+ weak_ptr_factory_.GetWeakPtr())); |
+} |
+ |
+void BluetoothRemoteGattServiceWin::OnGetIncludedCharacteristics( |
+ scoped_ptr<BTH_LE_GATT_CHARACTERISTIC> characteristics, |
+ uint16_t num, |
+ HRESULT hr) { |
+ DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); |
+ |
+ UpdateIncludedCharacteristics(characteristics.get(), num); |
+ included_characteristics_discovered_ = true; |
+ NotifyGattDiscoveryCompleteForServiceIfNecessary(); |
+} |
+ |
+void BluetoothRemoteGattServiceWin::UpdateIncludedCharacteristics( |
+ PBTH_LE_GATT_CHARACTERISTIC characteristics, |
+ uint16_t num) { |
+ if (num == 0) { |
+ if (included_characteristics_.size() > 0) { |
+ ClearIncludedCharacteristics(); |
+ adapter_->NotifyGattServiceChanged(this); |
+ } |
+ return; |
+ } |
+ |
+ // First, remove characteristics that no longer exist. |
+ std::vector<std::string> to_be_removed; |
+ for (const auto& c : included_characteristics_) { |
+ if (!DoesCharacteristicExist(characteristics, num, 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 : included_characteristics_) |
+ c.second->Update(); |
+ |
+ // Return if no new characteristics have been added. |
+ if (included_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]; |
+ BluetoothRemoteGattCharacteristicWin* characteristic_object = |
+ new BluetoothRemoteGattCharacteristicWin(this, info, ui_task_runner_); |
+ included_characteristics_[characteristic_object->GetIdentifier()] = |
+ make_scoped_ptr(characteristic_object); |
+ } |
+ } |
+ |
+ if (included_characteristics_discovered_) |
+ adapter_->NotifyGattServiceChanged(this); |
+} |
+ |
+void BluetoothRemoteGattServiceWin:: |
+ NotifyGattDiscoveryCompleteForServiceIfNecessary() { |
+ if (discovery_completed_included_charateristics_.size() == |
+ included_characteristics_.size() && |
+ included_characteristics_discovered_ && !discovery_complete_notified_) { |
+ adapter_->NotifyGattDiscoveryComplete(this); |
+ discovery_complete_notified_ = true; |
+ } |
+} |
+ |
+bool BluetoothRemoteGattServiceWin::IsCharacteristicDiscovered( |
+ BTH_LE_UUID& uuid, |
+ uint16_t attribute_handle) { |
+ BluetoothUUID bt_uuid = |
+ BluetoothTaskManagerWin::BluetoothLowEnergyUuidToBluetoothUuid(uuid); |
+ for (const auto& c : included_characteristics_) { |
+ if (bt_uuid == c.second->GetUUID() && |
+ attribute_handle == c.second->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_charateristics_.erase(identifier); |
+ included_characteristics_.erase(identifier); |
} |
-uint16_t BluetoothRemoteGattServiceWin::GetAttributeHandle() { |
- return service_attribute_handle_; |
+void BluetoothRemoteGattServiceWin::ClearIncludedCharacteristics() { |
+ discovery_completed_included_charateristics_.clear(); |
+ included_characteristics_.clear(); |
} |
-} // namespace device. |
+} // namespace device. |