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 // Allow writing to only certain characteristics that are defined with the | |
73 // write permission. | |
74 // TODO(armansito): Actually check against the permissions property instead of | |
75 // UUID, once that property is fully defined in the API. | |
76 if (uuid.value() != kHeartRateControlPointUUID) { | |
77 callback.Run(false); | |
78 return; | |
79 } | |
80 callback.Run(true); | |
81 property->ReplaceValueWithSetValue(); | |
82 } | 66 } |
83 | 67 |
84 FakeBluetoothGattCharacteristicClient::FakeBluetoothGattCharacteristicClient() | 68 FakeBluetoothGattCharacteristicClient::FakeBluetoothGattCharacteristicClient() |
85 : heart_rate_visible_(false), | 69 : heart_rate_visible_(false), |
86 calories_burned_(0), | 70 calories_burned_(0), |
87 weak_ptr_factory_(this) { | 71 weak_ptr_factory_(this) { |
88 } | 72 } |
89 | 73 |
90 FakeBluetoothGattCharacteristicClient:: | 74 FakeBluetoothGattCharacteristicClient:: |
91 ~FakeBluetoothGattCharacteristicClient() { | 75 ~FakeBluetoothGattCharacteristicClient() { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
124 DCHECK(body_sensor_location_properties_.get()); | 108 DCHECK(body_sensor_location_properties_.get()); |
125 return body_sensor_location_properties_.get(); | 109 return body_sensor_location_properties_.get(); |
126 } | 110 } |
127 if (object_path.value() == heart_rate_control_point_path_) { | 111 if (object_path.value() == heart_rate_control_point_path_) { |
128 DCHECK(heart_rate_control_point_properties_.get()); | 112 DCHECK(heart_rate_control_point_properties_.get()); |
129 return heart_rate_control_point_properties_.get(); | 113 return heart_rate_control_point_properties_.get(); |
130 } | 114 } |
131 return NULL; | 115 return NULL; |
132 } | 116 } |
133 | 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 |
134 void FakeBluetoothGattCharacteristicClient::ExposeHeartRateCharacteristics( | 173 void FakeBluetoothGattCharacteristicClient::ExposeHeartRateCharacteristics( |
135 const dbus::ObjectPath& service_path) { | 174 const dbus::ObjectPath& service_path) { |
136 if (IsHeartRateVisible()) { | 175 if (IsHeartRateVisible()) { |
137 VLOG(2) << "Fake Heart Rate characteristics are already visible."; | 176 VLOG(2) << "Fake Heart Rate characteristics are already visible."; |
138 return; | 177 return; |
139 } | 178 } |
140 | 179 |
141 VLOG(2) << "Exposing fake Heart Rate characteristics."; | 180 VLOG(2) << "Exposing fake Heart Rate characteristics."; |
142 | 181 |
143 // ==== Heart Rate Measurement Characteristic ==== | 182 // ==== Heart Rate Measurement Characteristic ==== |
144 heart_rate_measurement_path_ = | 183 heart_rate_measurement_path_ = |
145 service_path.value() + "/" + kHeartRateMeasurementPathComponent; | 184 service_path.value() + "/" + kHeartRateMeasurementPathComponent; |
146 heart_rate_measurement_properties_.reset(new Properties(base::Bind( | 185 heart_rate_measurement_properties_.reset(new Properties(base::Bind( |
147 &FakeBluetoothGattCharacteristicClient::OnPropertyChanged, | 186 &FakeBluetoothGattCharacteristicClient::OnPropertyChanged, |
148 weak_ptr_factory_.GetWeakPtr(), | 187 weak_ptr_factory_.GetWeakPtr(), |
149 dbus::ObjectPath(heart_rate_measurement_path_)))); | 188 dbus::ObjectPath(heart_rate_measurement_path_)))); |
150 heart_rate_measurement_properties_->uuid.ReplaceValue( | 189 heart_rate_measurement_properties_->uuid.ReplaceValue( |
151 kHeartRateMeasurementUUID); | 190 kHeartRateMeasurementUUID); |
152 heart_rate_measurement_properties_->service.ReplaceValue(service_path); | 191 heart_rate_measurement_properties_->service.ReplaceValue(service_path); |
153 | 192 |
154 // TODO(armansito): Fill out the flags field once bindings for the values have | 193 // TODO(armansito): Fill out the flags field once bindings for the values have |
155 // been added. For now, leave it empty. | 194 // been added. For now, leave it empty. |
156 | 195 |
157 std::vector<uint8> measurement_value = GetHeartRateMeasurementValue(); | |
158 heart_rate_measurement_properties_->value.ReplaceValue(measurement_value); | |
159 | |
160 // ==== Body Sensor Location Characteristic ==== | 196 // ==== Body Sensor Location Characteristic ==== |
161 body_sensor_location_path_ = | 197 body_sensor_location_path_ = |
162 service_path.value() + "/" + kBodySensorLocationPathComponent; | 198 service_path.value() + "/" + kBodySensorLocationPathComponent; |
163 body_sensor_location_properties_.reset(new Properties(base::Bind( | 199 body_sensor_location_properties_.reset(new Properties(base::Bind( |
164 &FakeBluetoothGattCharacteristicClient::OnPropertyChanged, | 200 &FakeBluetoothGattCharacteristicClient::OnPropertyChanged, |
165 weak_ptr_factory_.GetWeakPtr(), | 201 weak_ptr_factory_.GetWeakPtr(), |
166 dbus::ObjectPath(body_sensor_location_path_)))); | 202 dbus::ObjectPath(body_sensor_location_path_)))); |
167 body_sensor_location_properties_->uuid.ReplaceValue(kBodySensorLocationUUID); | 203 body_sensor_location_properties_->uuid.ReplaceValue(kBodySensorLocationUUID); |
168 body_sensor_location_properties_->service.ReplaceValue(service_path); | 204 body_sensor_location_properties_->service.ReplaceValue(service_path); |
169 | 205 |
170 // TODO(armansito): Fill out the flags field once bindings for the values have | 206 // TODO(armansito): Fill out the flags field once bindings for the values have |
171 // been added. For now, leave it empty. | 207 // been added. For now, leave it empty. |
172 | 208 |
173 // The sensor is in the "Other" location. | |
174 std::vector<uint8> body_sensor_location_value; | |
175 body_sensor_location_value.push_back(0); | |
176 body_sensor_location_properties_->value.ReplaceValue( | |
177 body_sensor_location_value); | |
178 | |
179 // ==== Heart Rate Control Point Characteristic ==== | 209 // ==== Heart Rate Control Point Characteristic ==== |
180 heart_rate_control_point_path_ = | 210 heart_rate_control_point_path_ = |
181 service_path.value() + "/" + kHeartRateControlPointPathComponent; | 211 service_path.value() + "/" + kHeartRateControlPointPathComponent; |
182 heart_rate_control_point_properties_.reset(new Properties(base::Bind( | 212 heart_rate_control_point_properties_.reset(new Properties(base::Bind( |
183 &FakeBluetoothGattCharacteristicClient::OnPropertyChanged, | 213 &FakeBluetoothGattCharacteristicClient::OnPropertyChanged, |
184 weak_ptr_factory_.GetWeakPtr(), | 214 weak_ptr_factory_.GetWeakPtr(), |
185 dbus::ObjectPath(heart_rate_control_point_path_)))); | 215 dbus::ObjectPath(heart_rate_control_point_path_)))); |
186 heart_rate_control_point_properties_->uuid.ReplaceValue( | 216 heart_rate_control_point_properties_->uuid.ReplaceValue( |
187 kHeartRateControlPointUUID); | 217 kHeartRateControlPointUUID); |
188 heart_rate_control_point_properties_->service.ReplaceValue(service_path); | 218 heart_rate_control_point_properties_->service.ReplaceValue(service_path); |
189 | 219 |
190 // TODO(armansito): Fill out the flags field once bindings for the values have | 220 // TODO(armansito): Fill out the flags field once bindings for the values have |
191 // been added. For now, leave it empty. | 221 // been added. For now, leave it empty. |
192 | 222 |
193 // Set the initial value to 0. Whenever this gets set to 1, we will reset the | |
194 // total calories burned and change the value back to 0. | |
195 std::vector<uint8> heart_rate_control_point_value; | |
196 heart_rate_control_point_value.push_back(0); | |
197 heart_rate_control_point_properties_->value.ReplaceValue( | |
198 heart_rate_control_point_value); | |
199 | |
200 heart_rate_visible_ = true; | 223 heart_rate_visible_ = true; |
201 | 224 |
202 NotifyCharacteristicAdded(dbus::ObjectPath(heart_rate_measurement_path_)); | 225 NotifyCharacteristicAdded(dbus::ObjectPath(heart_rate_measurement_path_)); |
203 NotifyCharacteristicAdded(dbus::ObjectPath(body_sensor_location_path_)); | 226 NotifyCharacteristicAdded(dbus::ObjectPath(body_sensor_location_path_)); |
204 NotifyCharacteristicAdded(dbus::ObjectPath(heart_rate_control_point_path_)); | 227 NotifyCharacteristicAdded(dbus::ObjectPath(heart_rate_control_point_path_)); |
205 | 228 |
206 // Set up notifications for heart rate measurement. | 229 // Set up notifications for heart rate measurement. |
207 // TODO(armansito): Do this based on the value of the "client characteristic | 230 // TODO(armansito): Do this based on the value of the "client characteristic |
208 // configuration" descriptor. Since it's still unclear how descriptors will | 231 // configuration" descriptor. Since it's still unclear how descriptors will |
209 // be handled by BlueZ, automatically set up notifications for now. | 232 // be handled by BlueZ, automatically set up notifications for now. |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
264 | 287 |
265 void FakeBluetoothGattCharacteristicClient::OnPropertyChanged( | 288 void FakeBluetoothGattCharacteristicClient::OnPropertyChanged( |
266 const dbus::ObjectPath& object_path, | 289 const dbus::ObjectPath& object_path, |
267 const std::string& property_name) { | 290 const std::string& property_name) { |
268 VLOG(2) << "Characteristic property changed: " << object_path.value() | 291 VLOG(2) << "Characteristic property changed: " << object_path.value() |
269 << ": " << property_name; | 292 << ": " << property_name; |
270 | 293 |
271 FOR_EACH_OBSERVER(BluetoothGattCharacteristicClient::Observer, observers_, | 294 FOR_EACH_OBSERVER(BluetoothGattCharacteristicClient::Observer, observers_, |
272 GattCharacteristicPropertyChanged( | 295 GattCharacteristicPropertyChanged( |
273 object_path, property_name)); | 296 object_path, property_name)); |
274 | |
275 // If the heart rate control point was set, reset the calories burned. | |
276 if (object_path.value() != heart_rate_control_point_path_) | |
277 return; | |
278 DCHECK(heart_rate_control_point_properties_.get()); | |
279 dbus::Property<std::vector<uint8> >* value_prop = | |
280 &heart_rate_control_point_properties_->value; | |
281 if (property_name != value_prop->name()) | |
282 return; | |
283 | |
284 std::vector<uint8> value = value_prop->value(); | |
285 DCHECK(value.size() == 1); | |
286 if (value[0] == 0) | |
287 return; | |
288 | |
289 DCHECK(value[0] == 1); | |
290 calories_burned_ = 0; | |
291 value[0] = 0; | |
292 value_prop->ReplaceValue(value); | |
293 } | 297 } |
294 | 298 |
295 void FakeBluetoothGattCharacteristicClient::NotifyCharacteristicAdded( | 299 void FakeBluetoothGattCharacteristicClient::NotifyCharacteristicAdded( |
296 const dbus::ObjectPath& object_path) { | 300 const dbus::ObjectPath& object_path) { |
297 VLOG(2) << "GATT characteristic added: " << object_path.value(); | 301 VLOG(2) << "GATT characteristic added: " << object_path.value(); |
298 FOR_EACH_OBSERVER(BluetoothGattCharacteristicClient::Observer, observers_, | 302 FOR_EACH_OBSERVER(BluetoothGattCharacteristicClient::Observer, observers_, |
299 GattCharacteristicAdded(object_path)); | 303 GattCharacteristicAdded(object_path)); |
300 } | 304 } |
301 | 305 |
302 void FakeBluetoothGattCharacteristicClient::NotifyCharacteristicRemoved( | 306 void FakeBluetoothGattCharacteristicClient::NotifyCharacteristicRemoved( |
303 const dbus::ObjectPath& object_path) { | 307 const dbus::ObjectPath& object_path) { |
304 VLOG(2) << "GATT characteristic removed: " << object_path.value(); | 308 VLOG(2) << "GATT characteristic removed: " << object_path.value(); |
305 FOR_EACH_OBSERVER(BluetoothGattCharacteristicClient::Observer, observers_, | 309 FOR_EACH_OBSERVER(BluetoothGattCharacteristicClient::Observer, observers_, |
306 GattCharacteristicRemoved(object_path)); | 310 GattCharacteristicRemoved(object_path)); |
307 } | 311 } |
308 | 312 |
309 void FakeBluetoothGattCharacteristicClient:: | 313 void FakeBluetoothGattCharacteristicClient:: |
310 ScheduleHeartRateMeasurementValueChange() { | 314 ScheduleHeartRateMeasurementValueChange() { |
311 if (!IsHeartRateVisible()) | 315 if (!IsHeartRateVisible()) |
312 return; | 316 return; |
313 VLOG(2) << "Updating heart rate value."; | 317 VLOG(2) << "Updating heart rate value."; |
314 std::vector<uint8> measurement = GetHeartRateMeasurementValue(); | 318 std::vector<uint8> measurement = GetHeartRateMeasurementValue(); |
315 heart_rate_measurement_properties_->value.ReplaceValue(measurement); | 319 |
| 320 FOR_EACH_OBSERVER( |
| 321 BluetoothGattCharacteristicClient::Observer, |
| 322 observers_, |
| 323 GattCharacteristicValueUpdated( |
| 324 dbus::ObjectPath(heart_rate_measurement_path_), measurement)); |
316 | 325 |
317 base::MessageLoop::current()->PostDelayedTask( | 326 base::MessageLoop::current()->PostDelayedTask( |
318 FROM_HERE, | 327 FROM_HERE, |
319 base::Bind(&FakeBluetoothGattCharacteristicClient:: | 328 base::Bind(&FakeBluetoothGattCharacteristicClient:: |
320 ScheduleHeartRateMeasurementValueChange, | 329 ScheduleHeartRateMeasurementValueChange, |
321 weak_ptr_factory_.GetWeakPtr()), | 330 weak_ptr_factory_.GetWeakPtr()), |
322 base::TimeDelta::FromMilliseconds( | 331 base::TimeDelta::FromMilliseconds( |
323 kHeartRateMeasurementNotificationIntervalMs)); | 332 kHeartRateMeasurementNotificationIntervalMs)); |
324 } | 333 } |
325 | 334 |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
369 DCHECK(heart_rate_visible_ != heart_rate_measurement_path_.empty()); | 378 DCHECK(heart_rate_visible_ != heart_rate_measurement_path_.empty()); |
370 DCHECK(heart_rate_visible_ != body_sensor_location_path_.empty()); | 379 DCHECK(heart_rate_visible_ != body_sensor_location_path_.empty()); |
371 DCHECK(heart_rate_visible_ != heart_rate_control_point_path_.empty()); | 380 DCHECK(heart_rate_visible_ != heart_rate_control_point_path_.empty()); |
372 DCHECK(heart_rate_visible_ == !!heart_rate_measurement_properties_.get()); | 381 DCHECK(heart_rate_visible_ == !!heart_rate_measurement_properties_.get()); |
373 DCHECK(heart_rate_visible_ == !!body_sensor_location_properties_.get()); | 382 DCHECK(heart_rate_visible_ == !!body_sensor_location_properties_.get()); |
374 DCHECK(heart_rate_visible_ == !!heart_rate_control_point_properties_.get()); | 383 DCHECK(heart_rate_visible_ == !!heart_rate_control_point_properties_.get()); |
375 return heart_rate_visible_; | 384 return heart_rate_visible_; |
376 } | 385 } |
377 | 386 |
378 } // namespace chromeos | 387 } // namespace chromeos |
OLD | NEW |