This source file includes following definitions.
- Get
- GetAll
- Set
- weak_ptr_factory_
- FakeBluetoothGattCharacteristicClient
- Init
- AddObserver
- RemoveObserver
- GetCharacteristics
- GetProperties
- ExposeHeartRateCharacteristics
- HideHeartRateCharacteristics
- OnPropertyChanged
- NotifyCharacteristicAdded
- NotifyCharacteristicRemoved
- ScheduleHeartRateMeasurementValueChange
- GetHeartRateMeasurementValue
- IsHeartRateVisible
#include "chromeos/dbus/fake_bluetooth_gatt_characteristic_client.h"
#include "base/bind.h"
#include "base/message_loop/message_loop.h"
#include "base/rand_util.h"
#include "base/time/time.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
namespace chromeos {
namespace {
const int kHeartRateMeasurementNotificationIntervalMs = 2000;
}
const char FakeBluetoothGattCharacteristicClient::
kHeartRateMeasurementPathComponent[] = "char0000";
const char FakeBluetoothGattCharacteristicClient::
kBodySensorLocationPathComponent[] = "char0001";
const char FakeBluetoothGattCharacteristicClient::
kHeartRateControlPointPathComponent[] = "char0002";
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(false);
}
void FakeBluetoothGattCharacteristicClient::Properties::GetAll() {
VLOG(1) << "GetAll";
}
void FakeBluetoothGattCharacteristicClient::Properties::Set(
dbus::PropertyBase* property,
dbus::PropertySet::SetCallback callback) {
VLOG(1) << "Set " << property->name();
if (property->name() != value.name()) {
callback.Run(false);
return;
}
if (uuid.value() != kHeartRateControlPointUUID) {
callback.Run(false);
return;
}
callback.Run(true);
property->ReplaceValueWithSetValue();
}
FakeBluetoothGattCharacteristicClient::FakeBluetoothGattCharacteristicClient()
: heart_rate_visible_(false),
calories_burned_(0),
weak_ptr_factory_(this) {
}
FakeBluetoothGattCharacteristicClient::
~FakeBluetoothGattCharacteristicClient() {
}
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(heart_rate_measurement_properties_.get());
return heart_rate_measurement_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::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.";
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);
std::vector<uint8> measurement_value = GetHeartRateMeasurementValue();
heart_rate_measurement_properties_->value.ReplaceValue(measurement_value);
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);
std::vector<uint8> body_sensor_location_value;
body_sensor_location_value.push_back(0);
body_sensor_location_properties_->value.ReplaceValue(
body_sensor_location_value);
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);
std::vector<uint8> heart_rate_control_point_value;
heart_rate_control_point_value.push_back(0);
heart_rate_control_point_properties_->value.ReplaceValue(
heart_rate_control_point_value);
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_));
ScheduleHeartRateMeasurementValueChange();
}
void FakeBluetoothGattCharacteristicClient::HideHeartRateCharacteristics() {
VLOG(2) << "Hiding fake Heart Rate characteristics.";
heart_rate_measurement_properties_.reset();
body_sensor_location_properties_.reset();
heart_rate_control_point_properties_.reset();
std::string hrm_path = heart_rate_measurement_path_;
heart_rate_measurement_path_.clear();
std::string bsl_path = body_sensor_location_path_;
body_sensor_location_path_.clear();
std::string hrcp_path = heart_rate_control_point_path_;
heart_rate_control_point_path_.clear();
heart_rate_visible_ = false;
NotifyCharacteristicRemoved(dbus::ObjectPath(hrm_path));
NotifyCharacteristicRemoved(dbus::ObjectPath(bsl_path));
NotifyCharacteristicRemoved(dbus::ObjectPath(hrcp_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));
if (object_path.value() != heart_rate_control_point_path_)
return;
DCHECK(heart_rate_control_point_properties_.get());
dbus::Property<std::vector<uint8> >* value_prop =
&heart_rate_control_point_properties_->value;
if (property_name != value_prop->name())
return;
std::vector<uint8> value = value_prop->value();
DCHECK(value.size() == 1);
if (value[0] == 0)
return;
DCHECK(value[0] == 1);
calories_burned_ = 0;
value[0] = 0;
value_prop->ReplaceValue(value);
}
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;
VLOG(2) << "Updating heart rate value.";
std::vector<uint8> measurement = GetHeartRateMeasurementValue();
heart_rate_measurement_properties_->value.ReplaceValue(measurement);
base::MessageLoop::current()->PostDelayedTask(
FROM_HERE,
base::Bind(&FakeBluetoothGattCharacteristicClient::
ScheduleHeartRateMeasurementValueChange,
weak_ptr_factory_.GetWeakPtr()),
base::TimeDelta::FromMilliseconds(
kHeartRateMeasurementNotificationIntervalMs));
}
std::vector<uint8>
FakeBluetoothGattCharacteristicClient::GetHeartRateMeasurementValue() {
struct {
uint8 flags;
uint8 bpm;
uint16 energy_expanded;
uint16 rr_interval;
} value;
value.flags = 0x0;
value.flags |= (0x03 << 1);
value.flags |= (0x01 << 3);
value.flags |= (0x01 << 4);
value.bpm = static_cast<uint8>(base::RandInt(117, 153));
value.energy_expanded = calories_burned_++;
value.rr_interval = 60/value.bpm;
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_;
}
}