| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chromeos/dbus/fake_bluetooth_gatt_characteristic_client.h" | 5 #include "chromeos/dbus/fake_bluetooth_gatt_characteristic_client.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/message_loop/message_loop.h" | 8 #include "base/message_loop/message_loop.h" |
| 9 #include "base/rand_util.h" | 9 #include "base/rand_util.h" |
| 10 #include "base/time/time.h" | 10 #include "base/time/time.h" |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 44 callback) { | 44 callback) { |
| 45 } | 45 } |
| 46 | 46 |
| 47 FakeBluetoothGattCharacteristicClient::Properties::~Properties() { | 47 FakeBluetoothGattCharacteristicClient::Properties::~Properties() { |
| 48 } | 48 } |
| 49 | 49 |
| 50 void FakeBluetoothGattCharacteristicClient::Properties::Get( | 50 void FakeBluetoothGattCharacteristicClient::Properties::Get( |
| 51 dbus::PropertyBase* property, | 51 dbus::PropertyBase* property, |
| 52 dbus::PropertySet::GetCallback callback) { | 52 dbus::PropertySet::GetCallback callback) { |
| 53 VLOG(1) << "Get " << property->name(); | 53 VLOG(1) << "Get " << property->name(); |
| 54 | |
| 55 // TODO(armansito): Return success or failure here based on characteristic | |
| 56 // read permission. | |
| 57 callback.Run(true); | 54 callback.Run(true); |
| 58 } | 55 } |
| 59 | 56 |
| 60 void FakeBluetoothGattCharacteristicClient::Properties::GetAll() { | 57 void FakeBluetoothGattCharacteristicClient::Properties::GetAll() { |
| 61 VLOG(1) << "GetAll"; | 58 VLOG(1) << "GetAll"; |
| 62 } | 59 } |
| 63 | 60 |
| 64 void FakeBluetoothGattCharacteristicClient::Properties::Set( | 61 void FakeBluetoothGattCharacteristicClient::Properties::Set( |
| 65 dbus::PropertyBase* property, | 62 dbus::PropertyBase* property, |
| 66 dbus::PropertySet::SetCallback callback) { | 63 dbus::PropertySet::SetCallback callback) { |
| 67 VLOG(1) << "Set " << property->name(); | 64 VLOG(1) << "Set " << property->name(); |
| 68 if (property->name() != value.name()) { | 65 callback.Run(false); |
| 69 callback.Run(false); | |
| 70 return; | |
| 71 } | |
| 72 | |
| 73 // Allow writing to only certain characteristics that are defined with the | |
| 74 // write permission. | |
| 75 bool write = false; | |
| 76 for (std::vector<std::string>::const_iterator iter = flags.value().begin(); | |
| 77 iter != flags.value().end(); | |
| 78 ++iter) { | |
| 79 if (*iter == bluetooth_gatt_characteristic::kFlagWrite || | |
| 80 *iter == bluetooth_gatt_characteristic::kFlagWriteWithoutResponse || | |
| 81 *iter == | |
| 82 bluetooth_gatt_characteristic::kFlagAuthenticatedSignedWrites || | |
| 83 *iter == bluetooth_gatt_characteristic::kFlagReliableWrite) { | |
| 84 write = true; | |
| 85 break; | |
| 86 } | |
| 87 } | |
| 88 | |
| 89 if (!write) { | |
| 90 callback.Run(false); | |
| 91 return; | |
| 92 } | |
| 93 | |
| 94 callback.Run(true); | |
| 95 property->ReplaceValueWithSetValue(); | |
| 96 } | 66 } |
| 97 | 67 |
| 98 FakeBluetoothGattCharacteristicClient::FakeBluetoothGattCharacteristicClient() | 68 FakeBluetoothGattCharacteristicClient::FakeBluetoothGattCharacteristicClient() |
| 99 : heart_rate_visible_(false), | 69 : heart_rate_visible_(false), |
| 100 calories_burned_(0), | 70 calories_burned_(0), |
| 101 weak_ptr_factory_(this) { | 71 weak_ptr_factory_(this) { |
| 102 } | 72 } |
| 103 | 73 |
| 104 FakeBluetoothGattCharacteristicClient:: | 74 FakeBluetoothGattCharacteristicClient:: |
| 105 ~FakeBluetoothGattCharacteristicClient() { | 75 ~FakeBluetoothGattCharacteristicClient() { |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 138 DCHECK(body_sensor_location_properties_.get()); | 108 DCHECK(body_sensor_location_properties_.get()); |
| 139 return body_sensor_location_properties_.get(); | 109 return body_sensor_location_properties_.get(); |
| 140 } | 110 } |
| 141 if (object_path.value() == heart_rate_control_point_path_) { | 111 if (object_path.value() == heart_rate_control_point_path_) { |
| 142 DCHECK(heart_rate_control_point_properties_.get()); | 112 DCHECK(heart_rate_control_point_properties_.get()); |
| 143 return heart_rate_control_point_properties_.get(); | 113 return heart_rate_control_point_properties_.get(); |
| 144 } | 114 } |
| 145 return NULL; | 115 return NULL; |
| 146 } | 116 } |
| 147 | 117 |
| 118 void FakeBluetoothGattCharacteristicClient::ReadValue( |
| 119 const dbus::ObjectPath& object_path, |
| 120 const ValueCallback& callback, |
| 121 const ErrorCallback& error_callback) { |
| 122 if (!IsHeartRateVisible()) { |
| 123 error_callback.Run(kUnknownCharacteristicError, ""); |
| 124 return; |
| 125 } |
| 126 |
| 127 if (object_path.value() == heart_rate_measurement_path_ || |
| 128 object_path.value() == heart_rate_control_point_path_) { |
| 129 error_callback.Run("org.bluez.Error.ReadNotPermitted", |
| 130 "Reads of this value are not allowed"); |
| 131 return; |
| 132 } |
| 133 |
| 134 if (object_path.value() != body_sensor_location_path_) { |
| 135 error_callback.Run(kUnknownCharacteristicError, ""); |
| 136 return; |
| 137 } |
| 138 |
| 139 std::vector<uint8> value; |
| 140 value.push_back(0x06); // Location is "foot". |
| 141 callback.Run(value); |
| 142 } |
| 143 |
| 144 void FakeBluetoothGattCharacteristicClient::WriteValue( |
| 145 const dbus::ObjectPath& object_path, |
| 146 const std::vector<uint8>& value, |
| 147 const base::Closure& callback, |
| 148 const ErrorCallback& error_callback) { |
| 149 if (!IsHeartRateVisible()) { |
| 150 error_callback.Run(kUnknownCharacteristicError, ""); |
| 151 return; |
| 152 } |
| 153 |
| 154 if (object_path.value() != heart_rate_control_point_path_) { |
| 155 error_callback.Run("org.bluez.Error.WriteNotPermitted", |
| 156 "Writes of this value are not allowed"); |
| 157 return; |
| 158 } |
| 159 |
| 160 DCHECK(heart_rate_control_point_properties_.get()); |
| 161 if (value.size() != 1 || value[0] > 1) { |
| 162 error_callback.Run("org.bluez.Error.Failed", |
| 163 "Invalid value given for write"); |
| 164 return; |
| 165 } |
| 166 |
| 167 if (value[0] == 1) |
| 168 calories_burned_ = 0; |
| 169 |
| 170 callback.Run(); |
| 171 } |
| 172 |
| 148 void FakeBluetoothGattCharacteristicClient::ExposeHeartRateCharacteristics( | 173 void FakeBluetoothGattCharacteristicClient::ExposeHeartRateCharacteristics( |
| 149 const dbus::ObjectPath& service_path) { | 174 const dbus::ObjectPath& service_path) { |
| 150 if (IsHeartRateVisible()) { | 175 if (IsHeartRateVisible()) { |
| 151 VLOG(2) << "Fake Heart Rate characteristics are already visible."; | 176 VLOG(2) << "Fake Heart Rate characteristics are already visible."; |
| 152 return; | 177 return; |
| 153 } | 178 } |
| 154 | 179 |
| 155 VLOG(2) << "Exposing fake Heart Rate characteristics."; | 180 VLOG(2) << "Exposing fake Heart Rate characteristics."; |
| 156 | 181 |
| 157 std::vector<std::string> flags; | 182 std::vector<std::string> flags; |
| 158 | 183 |
| 159 // ==== Heart Rate Measurement Characteristic ==== | 184 // ==== Heart Rate Measurement Characteristic ==== |
| 160 heart_rate_measurement_path_ = | 185 heart_rate_measurement_path_ = |
| 161 service_path.value() + "/" + kHeartRateMeasurementPathComponent; | 186 service_path.value() + "/" + kHeartRateMeasurementPathComponent; |
| 162 heart_rate_measurement_properties_.reset(new Properties(base::Bind( | 187 heart_rate_measurement_properties_.reset(new Properties(base::Bind( |
| 163 &FakeBluetoothGattCharacteristicClient::OnPropertyChanged, | 188 &FakeBluetoothGattCharacteristicClient::OnPropertyChanged, |
| 164 weak_ptr_factory_.GetWeakPtr(), | 189 weak_ptr_factory_.GetWeakPtr(), |
| 165 dbus::ObjectPath(heart_rate_measurement_path_)))); | 190 dbus::ObjectPath(heart_rate_measurement_path_)))); |
| 166 heart_rate_measurement_properties_->uuid.ReplaceValue( | 191 heart_rate_measurement_properties_->uuid.ReplaceValue( |
| 167 kHeartRateMeasurementUUID); | 192 kHeartRateMeasurementUUID); |
| 168 heart_rate_measurement_properties_->service.ReplaceValue(service_path); | 193 heart_rate_measurement_properties_->service.ReplaceValue(service_path); |
| 169 flags.push_back(bluetooth_gatt_characteristic::kFlagNotify); | 194 flags.push_back(bluetooth_gatt_characteristic::kFlagNotify); |
| 170 heart_rate_measurement_properties_->flags.ReplaceValue(flags); | 195 heart_rate_measurement_properties_->flags.ReplaceValue(flags); |
| 171 | 196 |
| 172 std::vector<uint8> measurement_value = GetHeartRateMeasurementValue(); | |
| 173 heart_rate_measurement_properties_->value.ReplaceValue(measurement_value); | |
| 174 | |
| 175 // ==== Body Sensor Location Characteristic ==== | 197 // ==== Body Sensor Location Characteristic ==== |
| 176 body_sensor_location_path_ = | 198 body_sensor_location_path_ = |
| 177 service_path.value() + "/" + kBodySensorLocationPathComponent; | 199 service_path.value() + "/" + kBodySensorLocationPathComponent; |
| 178 body_sensor_location_properties_.reset(new Properties(base::Bind( | 200 body_sensor_location_properties_.reset(new Properties(base::Bind( |
| 179 &FakeBluetoothGattCharacteristicClient::OnPropertyChanged, | 201 &FakeBluetoothGattCharacteristicClient::OnPropertyChanged, |
| 180 weak_ptr_factory_.GetWeakPtr(), | 202 weak_ptr_factory_.GetWeakPtr(), |
| 181 dbus::ObjectPath(body_sensor_location_path_)))); | 203 dbus::ObjectPath(body_sensor_location_path_)))); |
| 182 body_sensor_location_properties_->uuid.ReplaceValue(kBodySensorLocationUUID); | 204 body_sensor_location_properties_->uuid.ReplaceValue(kBodySensorLocationUUID); |
| 183 body_sensor_location_properties_->service.ReplaceValue(service_path); | 205 body_sensor_location_properties_->service.ReplaceValue(service_path); |
| 184 flags.clear(); | 206 flags.clear(); |
| 185 flags.push_back(bluetooth_gatt_characteristic::kFlagRead); | 207 flags.push_back(bluetooth_gatt_characteristic::kFlagRead); |
| 186 body_sensor_location_properties_->flags.ReplaceValue(flags); | 208 body_sensor_location_properties_->flags.ReplaceValue(flags); |
| 187 | 209 |
| 188 // The sensor is in the "Other" location. | |
| 189 std::vector<uint8> body_sensor_location_value; | |
| 190 body_sensor_location_value.push_back(0); | |
| 191 body_sensor_location_properties_->value.ReplaceValue( | |
| 192 body_sensor_location_value); | |
| 193 | |
| 194 // ==== Heart Rate Control Point Characteristic ==== | 210 // ==== Heart Rate Control Point Characteristic ==== |
| 195 heart_rate_control_point_path_ = | 211 heart_rate_control_point_path_ = |
| 196 service_path.value() + "/" + kHeartRateControlPointPathComponent; | 212 service_path.value() + "/" + kHeartRateControlPointPathComponent; |
| 197 heart_rate_control_point_properties_.reset(new Properties(base::Bind( | 213 heart_rate_control_point_properties_.reset(new Properties(base::Bind( |
| 198 &FakeBluetoothGattCharacteristicClient::OnPropertyChanged, | 214 &FakeBluetoothGattCharacteristicClient::OnPropertyChanged, |
| 199 weak_ptr_factory_.GetWeakPtr(), | 215 weak_ptr_factory_.GetWeakPtr(), |
| 200 dbus::ObjectPath(heart_rate_control_point_path_)))); | 216 dbus::ObjectPath(heart_rate_control_point_path_)))); |
| 201 heart_rate_control_point_properties_->uuid.ReplaceValue( | 217 heart_rate_control_point_properties_->uuid.ReplaceValue( |
| 202 kHeartRateControlPointUUID); | 218 kHeartRateControlPointUUID); |
| 203 heart_rate_control_point_properties_->service.ReplaceValue(service_path); | 219 heart_rate_control_point_properties_->service.ReplaceValue(service_path); |
| 204 flags.clear(); | 220 flags.clear(); |
| 205 flags.push_back(bluetooth_gatt_characteristic::kFlagWrite); | 221 flags.push_back(bluetooth_gatt_characteristic::kFlagWrite); |
| 206 heart_rate_control_point_properties_->flags.ReplaceValue(flags); | 222 heart_rate_control_point_properties_->flags.ReplaceValue(flags); |
| 207 | 223 |
| 208 // Set the initial value to 0. Whenever this gets set to 1, we will reset the | |
| 209 // total calories burned and change the value back to 0. | |
| 210 std::vector<uint8> heart_rate_control_point_value; | |
| 211 heart_rate_control_point_value.push_back(0); | |
| 212 heart_rate_control_point_properties_->value.ReplaceValue( | |
| 213 heart_rate_control_point_value); | |
| 214 | |
| 215 heart_rate_visible_ = true; | 224 heart_rate_visible_ = true; |
| 216 | 225 |
| 217 NotifyCharacteristicAdded(dbus::ObjectPath(heart_rate_measurement_path_)); | 226 NotifyCharacteristicAdded(dbus::ObjectPath(heart_rate_measurement_path_)); |
| 218 NotifyCharacteristicAdded(dbus::ObjectPath(body_sensor_location_path_)); | 227 NotifyCharacteristicAdded(dbus::ObjectPath(body_sensor_location_path_)); |
| 219 NotifyCharacteristicAdded(dbus::ObjectPath(heart_rate_control_point_path_)); | 228 NotifyCharacteristicAdded(dbus::ObjectPath(heart_rate_control_point_path_)); |
| 220 | 229 |
| 221 // Set up notifications for heart rate measurement. | 230 // Set up notifications for heart rate measurement. |
| 222 // TODO(armansito): Do this based on the value of the "client characteristic | 231 // TODO(armansito): Do this based on the value of the "client characteristic |
| 223 // configuration" descriptor. Since it's still unclear how descriptors will | 232 // configuration" descriptor. Since it's still unclear how descriptors will |
| 224 // be handled by BlueZ, automatically set up notifications for now. | 233 // be handled by BlueZ, automatically set up notifications for now. |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 279 | 288 |
| 280 void FakeBluetoothGattCharacteristicClient::OnPropertyChanged( | 289 void FakeBluetoothGattCharacteristicClient::OnPropertyChanged( |
| 281 const dbus::ObjectPath& object_path, | 290 const dbus::ObjectPath& object_path, |
| 282 const std::string& property_name) { | 291 const std::string& property_name) { |
| 283 VLOG(2) << "Characteristic property changed: " << object_path.value() | 292 VLOG(2) << "Characteristic property changed: " << object_path.value() |
| 284 << ": " << property_name; | 293 << ": " << property_name; |
| 285 | 294 |
| 286 FOR_EACH_OBSERVER(BluetoothGattCharacteristicClient::Observer, observers_, | 295 FOR_EACH_OBSERVER(BluetoothGattCharacteristicClient::Observer, observers_, |
| 287 GattCharacteristicPropertyChanged( | 296 GattCharacteristicPropertyChanged( |
| 288 object_path, property_name)); | 297 object_path, property_name)); |
| 289 | |
| 290 // If the heart rate control point was set, reset the calories burned. | |
| 291 if (object_path.value() != heart_rate_control_point_path_) | |
| 292 return; | |
| 293 DCHECK(heart_rate_control_point_properties_.get()); | |
| 294 dbus::Property<std::vector<uint8> >* value_prop = | |
| 295 &heart_rate_control_point_properties_->value; | |
| 296 if (property_name != value_prop->name()) | |
| 297 return; | |
| 298 | |
| 299 std::vector<uint8> value = value_prop->value(); | |
| 300 DCHECK(value.size() == 1); | |
| 301 if (value[0] == 0) | |
| 302 return; | |
| 303 | |
| 304 DCHECK(value[0] == 1); | |
| 305 calories_burned_ = 0; | |
| 306 value[0] = 0; | |
| 307 value_prop->ReplaceValue(value); | |
| 308 } | 298 } |
| 309 | 299 |
| 310 void FakeBluetoothGattCharacteristicClient::NotifyCharacteristicAdded( | 300 void FakeBluetoothGattCharacteristicClient::NotifyCharacteristicAdded( |
| 311 const dbus::ObjectPath& object_path) { | 301 const dbus::ObjectPath& object_path) { |
| 312 VLOG(2) << "GATT characteristic added: " << object_path.value(); | 302 VLOG(2) << "GATT characteristic added: " << object_path.value(); |
| 313 FOR_EACH_OBSERVER(BluetoothGattCharacteristicClient::Observer, observers_, | 303 FOR_EACH_OBSERVER(BluetoothGattCharacteristicClient::Observer, observers_, |
| 314 GattCharacteristicAdded(object_path)); | 304 GattCharacteristicAdded(object_path)); |
| 315 } | 305 } |
| 316 | 306 |
| 317 void FakeBluetoothGattCharacteristicClient::NotifyCharacteristicRemoved( | 307 void FakeBluetoothGattCharacteristicClient::NotifyCharacteristicRemoved( |
| 318 const dbus::ObjectPath& object_path) { | 308 const dbus::ObjectPath& object_path) { |
| 319 VLOG(2) << "GATT characteristic removed: " << object_path.value(); | 309 VLOG(2) << "GATT characteristic removed: " << object_path.value(); |
| 320 FOR_EACH_OBSERVER(BluetoothGattCharacteristicClient::Observer, observers_, | 310 FOR_EACH_OBSERVER(BluetoothGattCharacteristicClient::Observer, observers_, |
| 321 GattCharacteristicRemoved(object_path)); | 311 GattCharacteristicRemoved(object_path)); |
| 322 } | 312 } |
| 323 | 313 |
| 324 void FakeBluetoothGattCharacteristicClient:: | 314 void FakeBluetoothGattCharacteristicClient:: |
| 325 ScheduleHeartRateMeasurementValueChange() { | 315 ScheduleHeartRateMeasurementValueChange() { |
| 326 if (!IsHeartRateVisible()) | 316 if (!IsHeartRateVisible()) |
| 327 return; | 317 return; |
| 328 VLOG(2) << "Updating heart rate value."; | 318 VLOG(2) << "Updating heart rate value."; |
| 329 std::vector<uint8> measurement = GetHeartRateMeasurementValue(); | 319 std::vector<uint8> measurement = GetHeartRateMeasurementValue(); |
| 330 heart_rate_measurement_properties_->value.ReplaceValue(measurement); | 320 |
| 321 FOR_EACH_OBSERVER( |
| 322 BluetoothGattCharacteristicClient::Observer, |
| 323 observers_, |
| 324 GattCharacteristicValueUpdated( |
| 325 dbus::ObjectPath(heart_rate_measurement_path_), measurement)); |
| 331 | 326 |
| 332 base::MessageLoop::current()->PostDelayedTask( | 327 base::MessageLoop::current()->PostDelayedTask( |
| 333 FROM_HERE, | 328 FROM_HERE, |
| 334 base::Bind(&FakeBluetoothGattCharacteristicClient:: | 329 base::Bind(&FakeBluetoothGattCharacteristicClient:: |
| 335 ScheduleHeartRateMeasurementValueChange, | 330 ScheduleHeartRateMeasurementValueChange, |
| 336 weak_ptr_factory_.GetWeakPtr()), | 331 weak_ptr_factory_.GetWeakPtr()), |
| 337 base::TimeDelta::FromMilliseconds( | 332 base::TimeDelta::FromMilliseconds( |
| 338 kHeartRateMeasurementNotificationIntervalMs)); | 333 kHeartRateMeasurementNotificationIntervalMs)); |
| 339 } | 334 } |
| 340 | 335 |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 384 DCHECK(heart_rate_visible_ != heart_rate_measurement_path_.empty()); | 379 DCHECK(heart_rate_visible_ != heart_rate_measurement_path_.empty()); |
| 385 DCHECK(heart_rate_visible_ != body_sensor_location_path_.empty()); | 380 DCHECK(heart_rate_visible_ != body_sensor_location_path_.empty()); |
| 386 DCHECK(heart_rate_visible_ != heart_rate_control_point_path_.empty()); | 381 DCHECK(heart_rate_visible_ != heart_rate_control_point_path_.empty()); |
| 387 DCHECK(heart_rate_visible_ == !!heart_rate_measurement_properties_.get()); | 382 DCHECK(heart_rate_visible_ == !!heart_rate_measurement_properties_.get()); |
| 388 DCHECK(heart_rate_visible_ == !!body_sensor_location_properties_.get()); | 383 DCHECK(heart_rate_visible_ == !!body_sensor_location_properties_.get()); |
| 389 DCHECK(heart_rate_visible_ == !!heart_rate_control_point_properties_.get()); | 384 DCHECK(heart_rate_visible_ == !!heart_rate_control_point_properties_.get()); |
| 390 return heart_rate_visible_; | 385 return heart_rate_visible_; |
| 391 } | 386 } |
| 392 | 387 |
| 393 } // namespace chromeos | 388 } // namespace chromeos |
| OLD | NEW |