Index: chromeos/dbus/fake_bluetooth_gatt_characteristic_client.cc |
diff --git a/chromeos/dbus/fake_bluetooth_gatt_characteristic_client.cc b/chromeos/dbus/fake_bluetooth_gatt_characteristic_client.cc |
deleted file mode 100644 |
index 61bbb8dd92042fa88f0776c960b69cc999cc28ec..0000000000000000000000000000000000000000 |
--- a/chromeos/dbus/fake_bluetooth_gatt_characteristic_client.cc |
+++ /dev/null |
@@ -1,568 +0,0 @@ |
-// Copyright 2014 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 "chromeos/dbus/fake_bluetooth_gatt_characteristic_client.h" |
- |
-#include "base/bind.h" |
-#include "base/location.h" |
-#include "base/rand_util.h" |
-#include "base/single_thread_task_runner.h" |
-#include "base/thread_task_runner_handle.h" |
-#include "base/time/time.h" |
-#include "chromeos/dbus/dbus_thread_manager.h" |
-#include "chromeos/dbus/fake_bluetooth_gatt_descriptor_client.h" |
-#include "third_party/cros_system_api/dbus/service_constants.h" |
- |
-namespace chromeos { |
- |
-namespace { |
- |
-const int kStartNotifyResponseIntervalMs = 200; |
-const int kHeartRateMeasurementNotificationIntervalMs = 2000; |
- |
-} // namespace |
- |
-FakeBluetoothGattCharacteristicClient::DelayedCallback::DelayedCallback( |
- base::Closure callback, |
- size_t delay) |
- : callback_(callback), delay_(delay) { |
-} |
- |
-FakeBluetoothGattCharacteristicClient::DelayedCallback::~DelayedCallback() { |
-} |
- |
-// static |
-const char FakeBluetoothGattCharacteristicClient:: |
- kHeartRateMeasurementPathComponent[] = "char0000"; |
-const char FakeBluetoothGattCharacteristicClient:: |
- kBodySensorLocationPathComponent[] = "char0001"; |
-const char FakeBluetoothGattCharacteristicClient:: |
- kHeartRateControlPointPathComponent[] = "char0002"; |
- |
-// static |
-const char FakeBluetoothGattCharacteristicClient::kHeartRateMeasurementUUID[] = |
- "00002a37-0000-1000-8000-00805f9b34fb"; |
-const char FakeBluetoothGattCharacteristicClient::kBodySensorLocationUUID[] = |
- "00002a38-0000-1000-8000-00805f9b34fb"; |
-const char FakeBluetoothGattCharacteristicClient::kHeartRateControlPointUUID[] = |
- "00002a39-0000-1000-8000-00805f9b34fb"; |
- |
-FakeBluetoothGattCharacteristicClient::Properties::Properties( |
- const PropertyChangedCallback& callback) |
- : BluetoothGattCharacteristicClient::Properties( |
- NULL, |
- bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface, |
- callback) { |
-} |
- |
-FakeBluetoothGattCharacteristicClient::Properties::~Properties() { |
-} |
- |
-void FakeBluetoothGattCharacteristicClient::Properties::Get( |
- dbus::PropertyBase* property, |
- dbus::PropertySet::GetCallback callback) { |
- VLOG(1) << "Get " << property->name(); |
- callback.Run(true); |
-} |
- |
-void FakeBluetoothGattCharacteristicClient::Properties::GetAll() { |
- VLOG(1) << "GetAll"; |
-} |
- |
-void FakeBluetoothGattCharacteristicClient::Properties::Set( |
- dbus::PropertyBase* property, |
- dbus::PropertySet::SetCallback callback) { |
- VLOG(1) << "Set " << property->name(); |
- callback.Run(false); |
-} |
- |
-FakeBluetoothGattCharacteristicClient::FakeBluetoothGattCharacteristicClient() |
- : heart_rate_visible_(false), |
- authorized_(true), |
- authenticated_(true), |
- calories_burned_(0), |
- extra_requests_(0), |
- weak_ptr_factory_(this) { |
-} |
- |
-FakeBluetoothGattCharacteristicClient:: |
- ~FakeBluetoothGattCharacteristicClient() { |
- for (const auto& it : action_extra_requests_) { |
- delete it.second; |
- } |
- action_extra_requests_.clear(); |
-} |
- |
-void FakeBluetoothGattCharacteristicClient::Init(dbus::Bus* bus) { |
-} |
- |
-void FakeBluetoothGattCharacteristicClient::AddObserver(Observer* observer) { |
- observers_.AddObserver(observer); |
-} |
- |
-void FakeBluetoothGattCharacteristicClient::RemoveObserver(Observer* observer) { |
- observers_.RemoveObserver(observer); |
-} |
- |
-std::vector<dbus::ObjectPath> |
-FakeBluetoothGattCharacteristicClient::GetCharacteristics() { |
- std::vector<dbus::ObjectPath> paths; |
- if (IsHeartRateVisible()) { |
- paths.push_back(dbus::ObjectPath(heart_rate_measurement_path_)); |
- paths.push_back(dbus::ObjectPath(body_sensor_location_path_)); |
- paths.push_back(dbus::ObjectPath(heart_rate_control_point_path_)); |
- } |
- return paths; |
-} |
- |
-FakeBluetoothGattCharacteristicClient::Properties* |
-FakeBluetoothGattCharacteristicClient::GetProperties( |
- const dbus::ObjectPath& object_path) { |
- if (object_path.value() == heart_rate_measurement_path_) { |
- DCHECK(heart_rate_measurement_properties_.get()); |
- return heart_rate_measurement_properties_.get(); |
- } |
- if (object_path.value() == body_sensor_location_path_) { |
- DCHECK(body_sensor_location_properties_.get()); |
- return body_sensor_location_properties_.get(); |
- } |
- if (object_path.value() == heart_rate_control_point_path_) { |
- DCHECK(heart_rate_control_point_properties_.get()); |
- return heart_rate_control_point_properties_.get(); |
- } |
- return NULL; |
-} |
- |
-void FakeBluetoothGattCharacteristicClient::ReadValue( |
- const dbus::ObjectPath& object_path, |
- const ValueCallback& callback, |
- const ErrorCallback& error_callback) { |
- if (!authenticated_) { |
- error_callback.Run("org.bluez.Error.NotPaired", "Please login"); |
- return; |
- } |
- |
- if (!authorized_) { |
- error_callback.Run("org.bluez.Error.NotAuthorized", "Authorize first"); |
- return; |
- } |
- |
- if (object_path.value() == heart_rate_control_point_path_) { |
- error_callback.Run("org.bluez.Error.NotPermitted", |
- "Reads of this value are not allowed"); |
- return; |
- } |
- |
- if (object_path.value() == heart_rate_measurement_path_) { |
- error_callback.Run("org.bluez.Error.NotSupported", |
- "Action not supported on this characteristic"); |
- return; |
- } |
- |
- if (object_path.value() != body_sensor_location_path_) { |
- error_callback.Run(kUnknownCharacteristicError, ""); |
- return; |
- } |
- |
- if (action_extra_requests_.find("ReadValue") != |
- action_extra_requests_.end()) { |
- DelayedCallback* delayed = action_extra_requests_["ReadValue"]; |
- delayed->delay_--; |
- error_callback.Run("org.bluez.Error.InProgress", |
- "Another read is currenty in progress"); |
- if (delayed->delay_ == 0) { |
- delayed->callback_.Run(); |
- action_extra_requests_.erase("ReadValue"); |
- delete delayed; |
- } |
- return; |
- } |
- |
- base::Closure completed_callback; |
- if (!IsHeartRateVisible()) { |
- completed_callback = |
- base::Bind(error_callback, kUnknownCharacteristicError, ""); |
- } else { |
- std::vector<uint8> value = {0x06}; // Location is "foot". |
- completed_callback = base::Bind( |
- &FakeBluetoothGattCharacteristicClient::DelayedReadValueCallback, |
- weak_ptr_factory_.GetWeakPtr(), object_path, callback, value); |
- } |
- |
- if (extra_requests_ > 0) { |
- action_extra_requests_["ReadValue"] = |
- new DelayedCallback(completed_callback, extra_requests_); |
- return; |
- } |
- |
- completed_callback.Run(); |
-} |
- |
-void FakeBluetoothGattCharacteristicClient::WriteValue( |
- const dbus::ObjectPath& object_path, |
- const std::vector<uint8>& value, |
- const base::Closure& callback, |
- const ErrorCallback& error_callback) { |
- if (!authenticated_) { |
- error_callback.Run("org.bluez.Error.NotPaired", "Please login"); |
- return; |
- } |
- |
- if (!authorized_) { |
- error_callback.Run("org.bluez.Error.NotAuthorized", "Authorize first"); |
- return; |
- } |
- |
- if (!IsHeartRateVisible()) { |
- error_callback.Run(kUnknownCharacteristicError, ""); |
- return; |
- } |
- |
- if (object_path.value() == heart_rate_measurement_path_) { |
- error_callback.Run("org.bluez.Error.NotSupported", |
- "Action not supported on this characteristic"); |
- return; |
- } |
- |
- if (object_path.value() != heart_rate_control_point_path_) { |
- error_callback.Run("org.bluez.Error.NotPermitted", |
- "Writes of this value are not allowed"); |
- return; |
- } |
- |
- DCHECK(heart_rate_control_point_properties_.get()); |
- if (action_extra_requests_.find("WriteValue") != |
- action_extra_requests_.end()) { |
- DelayedCallback* delayed = action_extra_requests_["WriteValue"]; |
- delayed->delay_--; |
- error_callback.Run("org.bluez.Error.InProgress", |
- "Another write is in progress"); |
- if (delayed->delay_ == 0) { |
- delayed->callback_.Run(); |
- action_extra_requests_.erase("WriteValue"); |
- delete delayed; |
- } |
- return; |
- } |
- base::Closure completed_callback; |
- if (value.size() != 1) { |
- completed_callback = base::Bind(error_callback, |
- "org.bluez.Error.InvalidValueLength", |
- "Invalid length for write"); |
- } else if (value[0] > 1) { |
- completed_callback = base::Bind(error_callback, |
- "org.bluez.Error.Failed", |
- "Invalid value given for write"); |
- } else if (value[0] == 1) { |
- // TODO(jamuraa): make this happen when the callback happens |
- calories_burned_ = 0; |
- completed_callback = callback; |
- } |
- |
- if (extra_requests_ > 0) { |
- action_extra_requests_["WriteValue"] = |
- new DelayedCallback(completed_callback, extra_requests_); |
- return; |
- } |
- completed_callback.Run(); |
-} |
- |
-void FakeBluetoothGattCharacteristicClient::StartNotify( |
- const dbus::ObjectPath& object_path, |
- const base::Closure& callback, |
- const ErrorCallback& error_callback) { |
- if (!IsHeartRateVisible()) { |
- error_callback.Run(kUnknownCharacteristicError, ""); |
- return; |
- } |
- |
- if (object_path.value() != heart_rate_measurement_path_) { |
- error_callback.Run("org.bluez.Error.NotSupported", |
- "This characteristic does not support notifications"); |
- return; |
- } |
- |
- if (heart_rate_measurement_properties_->notifying.value()) { |
- error_callback.Run("org.bluez.Error.InProgress", |
- "Characteristic already notifying"); |
- return; |
- } |
- |
- heart_rate_measurement_properties_->notifying.ReplaceValue(true); |
- ScheduleHeartRateMeasurementValueChange(); |
- |
- // Respond asynchronously. |
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
- FROM_HERE, callback, |
- base::TimeDelta::FromMilliseconds(kStartNotifyResponseIntervalMs)); |
-} |
- |
-void FakeBluetoothGattCharacteristicClient::StopNotify( |
- const dbus::ObjectPath& object_path, |
- const base::Closure& callback, |
- const ErrorCallback& error_callback) { |
- if (!IsHeartRateVisible()) { |
- error_callback.Run(kUnknownCharacteristicError, ""); |
- return; |
- } |
- |
- if (object_path.value() != heart_rate_measurement_path_) { |
- error_callback.Run("org.bluez.Error.NotSupported", |
- "This characteristic does not support notifications"); |
- return; |
- } |
- |
- if (!heart_rate_measurement_properties_->notifying.value()) { |
- error_callback.Run("org.bluez.Error.Failed", "Not notifying"); |
- return; |
- } |
- |
- heart_rate_measurement_properties_->notifying.ReplaceValue(false); |
- |
- callback.Run(); |
-} |
- |
-void FakeBluetoothGattCharacteristicClient::ExposeHeartRateCharacteristics( |
- const dbus::ObjectPath& service_path) { |
- if (IsHeartRateVisible()) { |
- VLOG(2) << "Fake Heart Rate characteristics are already visible."; |
- return; |
- } |
- |
- VLOG(2) << "Exposing fake Heart Rate characteristics."; |
- |
- std::vector<std::string> flags; |
- |
- // ==== Heart Rate Measurement Characteristic ==== |
- heart_rate_measurement_path_ = |
- service_path.value() + "/" + kHeartRateMeasurementPathComponent; |
- heart_rate_measurement_properties_.reset(new Properties(base::Bind( |
- &FakeBluetoothGattCharacteristicClient::OnPropertyChanged, |
- weak_ptr_factory_.GetWeakPtr(), |
- dbus::ObjectPath(heart_rate_measurement_path_)))); |
- heart_rate_measurement_properties_->uuid.ReplaceValue( |
- kHeartRateMeasurementUUID); |
- heart_rate_measurement_properties_->service.ReplaceValue(service_path); |
- flags.push_back(bluetooth_gatt_characteristic::kFlagNotify); |
- heart_rate_measurement_properties_->flags.ReplaceValue(flags); |
- |
- // ==== Body Sensor Location Characteristic ==== |
- body_sensor_location_path_ = |
- service_path.value() + "/" + kBodySensorLocationPathComponent; |
- body_sensor_location_properties_.reset(new Properties(base::Bind( |
- &FakeBluetoothGattCharacteristicClient::OnPropertyChanged, |
- weak_ptr_factory_.GetWeakPtr(), |
- dbus::ObjectPath(body_sensor_location_path_)))); |
- body_sensor_location_properties_->uuid.ReplaceValue(kBodySensorLocationUUID); |
- body_sensor_location_properties_->service.ReplaceValue(service_path); |
- flags.clear(); |
- flags.push_back(bluetooth_gatt_characteristic::kFlagRead); |
- body_sensor_location_properties_->flags.ReplaceValue(flags); |
- |
- // ==== Heart Rate Control Point Characteristic ==== |
- heart_rate_control_point_path_ = |
- service_path.value() + "/" + kHeartRateControlPointPathComponent; |
- heart_rate_control_point_properties_.reset(new Properties(base::Bind( |
- &FakeBluetoothGattCharacteristicClient::OnPropertyChanged, |
- weak_ptr_factory_.GetWeakPtr(), |
- dbus::ObjectPath(heart_rate_control_point_path_)))); |
- heart_rate_control_point_properties_->uuid.ReplaceValue( |
- kHeartRateControlPointUUID); |
- heart_rate_control_point_properties_->service.ReplaceValue(service_path); |
- flags.clear(); |
- flags.push_back(bluetooth_gatt_characteristic::kFlagWrite); |
- heart_rate_control_point_properties_->flags.ReplaceValue(flags); |
- |
- heart_rate_visible_ = true; |
- |
- NotifyCharacteristicAdded(dbus::ObjectPath(heart_rate_measurement_path_)); |
- NotifyCharacteristicAdded(dbus::ObjectPath(body_sensor_location_path_)); |
- NotifyCharacteristicAdded(dbus::ObjectPath(heart_rate_control_point_path_)); |
- |
- // Expose CCC descriptor for Heart Rate Measurement characteristic. |
- FakeBluetoothGattDescriptorClient* descriptor_client = |
- static_cast<FakeBluetoothGattDescriptorClient*>( |
- DBusThreadManager::Get()->GetBluetoothGattDescriptorClient()); |
- dbus::ObjectPath ccc_path(descriptor_client->ExposeDescriptor( |
- dbus::ObjectPath(heart_rate_measurement_path_), |
- FakeBluetoothGattDescriptorClient:: |
- kClientCharacteristicConfigurationUUID)); |
- DCHECK(ccc_path.IsValid()); |
- heart_rate_measurement_ccc_desc_path_ = ccc_path.value(); |
- |
- std::vector<dbus::ObjectPath> desc_paths; |
- desc_paths.push_back(ccc_path); |
- |
- heart_rate_measurement_properties_->descriptors.ReplaceValue(desc_paths); |
-} |
- |
-void FakeBluetoothGattCharacteristicClient::HideHeartRateCharacteristics() { |
- VLOG(2) << "Hiding fake Heart Rate characteristics."; |
- |
- // Hide the descriptors. |
- FakeBluetoothGattDescriptorClient* descriptor_client = |
- static_cast<FakeBluetoothGattDescriptorClient*>( |
- DBusThreadManager::Get()->GetBluetoothGattDescriptorClient()); |
- descriptor_client->HideDescriptor( |
- dbus::ObjectPath(heart_rate_measurement_ccc_desc_path_)); |
- |
- // Notify the observers before deleting the properties structures so that they |
- // can be accessed from the observer method. |
- NotifyCharacteristicRemoved(dbus::ObjectPath(heart_rate_measurement_path_)); |
- NotifyCharacteristicRemoved(dbus::ObjectPath(body_sensor_location_path_)); |
- NotifyCharacteristicRemoved(dbus::ObjectPath(heart_rate_control_point_path_)); |
- |
- heart_rate_measurement_properties_.reset(); |
- body_sensor_location_properties_.reset(); |
- heart_rate_control_point_properties_.reset(); |
- |
- heart_rate_measurement_path_.clear(); |
- body_sensor_location_path_.clear(); |
- heart_rate_control_point_path_.clear(); |
- heart_rate_visible_ = false; |
-} |
- |
-void FakeBluetoothGattCharacteristicClient::SetExtraProcessing( |
- size_t requests) { |
- extra_requests_ = requests; |
- if (extra_requests_ == 0) { |
- for (const auto& it : action_extra_requests_) { |
- it.second->callback_.Run(); |
- delete it.second; |
- } |
- action_extra_requests_.clear(); |
- return; |
- } |
- VLOG(2) << "Requests SLOW now, " << requests << " InProgress errors each."; |
-} |
- |
-size_t FakeBluetoothGattCharacteristicClient::GetExtraProcessing() const { |
- return extra_requests_; |
-} |
- |
-dbus::ObjectPath |
-FakeBluetoothGattCharacteristicClient::GetHeartRateMeasurementPath() const { |
- return dbus::ObjectPath(heart_rate_measurement_path_); |
-} |
- |
-dbus::ObjectPath |
-FakeBluetoothGattCharacteristicClient::GetBodySensorLocationPath() const { |
- return dbus::ObjectPath(body_sensor_location_path_); |
-} |
- |
-dbus::ObjectPath |
-FakeBluetoothGattCharacteristicClient::GetHeartRateControlPointPath() const { |
- return dbus::ObjectPath(heart_rate_control_point_path_); |
-} |
- |
-void FakeBluetoothGattCharacteristicClient::OnPropertyChanged( |
- const dbus::ObjectPath& object_path, |
- const std::string& property_name) { |
- VLOG(2) << "Characteristic property changed: " << object_path.value() |
- << ": " << property_name; |
- |
- FOR_EACH_OBSERVER(BluetoothGattCharacteristicClient::Observer, observers_, |
- GattCharacteristicPropertyChanged( |
- object_path, property_name)); |
-} |
- |
-void FakeBluetoothGattCharacteristicClient::NotifyCharacteristicAdded( |
- const dbus::ObjectPath& object_path) { |
- VLOG(2) << "GATT characteristic added: " << object_path.value(); |
- FOR_EACH_OBSERVER(BluetoothGattCharacteristicClient::Observer, observers_, |
- GattCharacteristicAdded(object_path)); |
-} |
- |
-void FakeBluetoothGattCharacteristicClient::NotifyCharacteristicRemoved( |
- const dbus::ObjectPath& object_path) { |
- VLOG(2) << "GATT characteristic removed: " << object_path.value(); |
- FOR_EACH_OBSERVER(BluetoothGattCharacteristicClient::Observer, observers_, |
- GattCharacteristicRemoved(object_path)); |
-} |
- |
-void FakeBluetoothGattCharacteristicClient:: |
- ScheduleHeartRateMeasurementValueChange() { |
- if (!IsHeartRateVisible()) |
- return; |
- |
- // Don't send updates if the characteristic is not notifying. |
- if (!heart_rate_measurement_properties_->notifying.value()) |
- return; |
- |
- VLOG(2) << "Updating heart rate value."; |
- std::vector<uint8> measurement = GetHeartRateMeasurementValue(); |
- heart_rate_measurement_properties_->value.ReplaceValue(measurement); |
- |
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
- FROM_HERE, base::Bind(&FakeBluetoothGattCharacteristicClient:: |
- ScheduleHeartRateMeasurementValueChange, |
- weak_ptr_factory_.GetWeakPtr()), |
- base::TimeDelta::FromMilliseconds( |
- kHeartRateMeasurementNotificationIntervalMs)); |
-} |
- |
-void FakeBluetoothGattCharacteristicClient::DelayedReadValueCallback( |
- const dbus::ObjectPath& object_path, |
- const ValueCallback& callback, |
- const std::vector<uint8_t>& value) { |
- Properties* properties = GetProperties(object_path); |
- DCHECK(properties); |
- |
- properties->value.ReplaceValue(value); |
- callback.Run(value); |
-} |
- |
-std::vector<uint8> |
-FakeBluetoothGattCharacteristicClient::GetHeartRateMeasurementValue() { |
- // TODO(armansito): We should make sure to properly pack this struct to ensure |
- // correct byte alignment and endianness. It doesn't matter too much right now |
- // as this is a fake and GCC on Linux seems to do the right thing. |
- struct { |
- uint8 flags; |
- uint8 bpm; |
- uint16 energy_expanded; |
- uint16 rr_interval; |
- } value; |
- |
- // Flags in LSB: 0 11 1 1 000 |
- // | | | | | |
- // 8-bit bpm format -- | | | | |
- // Sensor contact supported -- | | | |
- // Energy expanded field present -- | | |
- // RR-Interval values present ------- | |
- // Reserved for future use ------------ |
- value.flags = 0x0; |
- value.flags |= (0x03 << 1); |
- value.flags |= (0x01 << 3); |
- value.flags |= (0x01 << 4); |
- |
- // Pick a value between 117 bpm and 153 bpm for heart rate. |
- value.bpm = static_cast<uint8>(base::RandInt(117, 153)); |
- |
- // Total calories burned in kJoules since the last reset. Increment this by 1 |
- // every time. It's fine if it overflows: it becomes 0 when the user resets |
- // the heart rate monitor (or pretend that he had a lot of cheeseburgers). |
- value.energy_expanded = calories_burned_++; |
- |
- // Include one RR-Interval value, in seconds. |
- value.rr_interval = 60/value.bpm; |
- |
- // Return the bytes in an array. |
- uint8* bytes = reinterpret_cast<uint8*>(&value); |
- std::vector<uint8> return_value; |
- return_value.assign(bytes, bytes + sizeof(value)); |
- return return_value; |
-} |
- |
-bool FakeBluetoothGattCharacteristicClient::IsHeartRateVisible() const { |
- DCHECK(heart_rate_visible_ != heart_rate_measurement_path_.empty()); |
- DCHECK(heart_rate_visible_ != body_sensor_location_path_.empty()); |
- DCHECK(heart_rate_visible_ != heart_rate_control_point_path_.empty()); |
- DCHECK(heart_rate_visible_ == !!heart_rate_measurement_properties_.get()); |
- DCHECK(heart_rate_visible_ == !!body_sensor_location_properties_.get()); |
- DCHECK(heart_rate_visible_ == !!heart_rate_control_point_properties_.get()); |
- return heart_rate_visible_; |
-} |
- |
-} // namespace chromeos |