Linux: Depend on liberation-fonts package for RPMs.
[chromium-blink-merge.git] / device / bluetooth / bluetooth_gatt_chromeos_unittest.cc
blobc81acea20d6dc823a3c8d1a5fba0df54d0680b3b
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
3 // found in the LICENSE file.
5 #include "base/memory/scoped_vector.h"
6 #include "base/message_loop/message_loop.h"
7 #include "base/run_loop.h"
8 #include "chromeos/dbus/dbus_thread_manager.h"
9 #include "chromeos/dbus/fake_bluetooth_adapter_client.h"
10 #include "chromeos/dbus/fake_bluetooth_agent_manager_client.h"
11 #include "chromeos/dbus/fake_bluetooth_device_client.h"
12 #include "chromeos/dbus/fake_bluetooth_gatt_characteristic_client.h"
13 #include "chromeos/dbus/fake_bluetooth_gatt_descriptor_client.h"
14 #include "chromeos/dbus/fake_bluetooth_gatt_service_client.h"
15 #include "chromeos/dbus/fake_bluetooth_input_client.h"
16 #include "dbus/object_path.h"
17 #include "device/bluetooth/bluetooth_adapter.h"
18 #include "device/bluetooth/bluetooth_adapter_factory.h"
19 #include "device/bluetooth/bluetooth_device.h"
20 #include "device/bluetooth/bluetooth_gatt_characteristic.h"
21 #include "device/bluetooth/bluetooth_gatt_connection.h"
22 #include "device/bluetooth/bluetooth_gatt_descriptor.h"
23 #include "device/bluetooth/bluetooth_gatt_notify_session.h"
24 #include "device/bluetooth/bluetooth_gatt_service.h"
25 #include "device/bluetooth/bluetooth_uuid.h"
26 #include "device/bluetooth/test/test_bluetooth_adapter_observer.h"
27 #include "testing/gtest/include/gtest/gtest.h"
29 using device::BluetoothAdapter;
30 using device::BluetoothDevice;
31 using device::BluetoothGattCharacteristic;
32 using device::BluetoothGattConnection;
33 using device::BluetoothGattDescriptor;
34 using device::BluetoothGattService;
35 using device::BluetoothGattNotifySession;
36 using device::BluetoothUUID;
37 using device::TestBluetoothAdapterObserver;
39 namespace chromeos {
41 namespace {
43 const BluetoothUUID kHeartRateMeasurementUUID(
44 FakeBluetoothGattCharacteristicClient::kHeartRateMeasurementUUID);
45 const BluetoothUUID kBodySensorLocationUUID(
46 FakeBluetoothGattCharacteristicClient::kBodySensorLocationUUID);
47 const BluetoothUUID kHeartRateControlPointUUID(
48 FakeBluetoothGattCharacteristicClient::kHeartRateControlPointUUID);
50 // Compares GATT characteristic/descriptor values. Returns true, if the values
51 // are equal.
52 bool ValuesEqual(const std::vector<uint8>& value0,
53 const std::vector<uint8>& value1) {
54 if (value0.size() != value1.size())
55 return false;
56 for (size_t i = 0; i < value0.size(); ++i)
57 if (value0[i] != value1[i])
58 return false;
59 return true;
62 } // namespace
64 class BluetoothGattChromeOSTest : public testing::Test {
65 public:
66 BluetoothGattChromeOSTest()
67 : fake_bluetooth_gatt_service_client_(NULL),
68 success_callback_count_(0),
69 error_callback_count_(0) {
72 void SetUp() override {
73 scoped_ptr<DBusThreadManagerSetter> dbus_setter =
74 chromeos::DBusThreadManager::GetSetterForTesting();
75 fake_bluetooth_device_client_ = new FakeBluetoothDeviceClient;
76 fake_bluetooth_gatt_service_client_ =
77 new FakeBluetoothGattServiceClient;
78 fake_bluetooth_gatt_characteristic_client_ =
79 new FakeBluetoothGattCharacteristicClient;
80 fake_bluetooth_gatt_descriptor_client_ =
81 new FakeBluetoothGattDescriptorClient;
82 dbus_setter->SetBluetoothDeviceClient(
83 scoped_ptr<BluetoothDeviceClient>(
84 fake_bluetooth_device_client_));
85 dbus_setter->SetBluetoothGattServiceClient(
86 scoped_ptr<BluetoothGattServiceClient>(
87 fake_bluetooth_gatt_service_client_));
88 dbus_setter->SetBluetoothGattCharacteristicClient(
89 scoped_ptr<BluetoothGattCharacteristicClient>(
90 fake_bluetooth_gatt_characteristic_client_));
91 dbus_setter->SetBluetoothGattDescriptorClient(
92 scoped_ptr<BluetoothGattDescriptorClient>(
93 fake_bluetooth_gatt_descriptor_client_));
94 dbus_setter->SetBluetoothAdapterClient(
95 scoped_ptr<BluetoothAdapterClient>(new FakeBluetoothAdapterClient));
96 dbus_setter->SetBluetoothInputClient(
97 scoped_ptr<BluetoothInputClient>(new FakeBluetoothInputClient));
98 dbus_setter->SetBluetoothAgentManagerClient(
99 scoped_ptr<BluetoothAgentManagerClient>(
100 new FakeBluetoothAgentManagerClient));
102 GetAdapter();
104 adapter_->SetPowered(
105 true,
106 base::Bind(&base::DoNothing),
107 base::Bind(&base::DoNothing));
108 ASSERT_TRUE(adapter_->IsPowered());
111 void TearDown() override {
112 adapter_ = NULL;
113 update_sessions_.clear();
114 gatt_conn_.reset();
115 DBusThreadManager::Shutdown();
118 void GetAdapter() {
119 device::BluetoothAdapterFactory::GetAdapter(
120 base::Bind(&BluetoothGattChromeOSTest::AdapterCallback,
121 base::Unretained(this)));
122 ASSERT_TRUE(adapter_.get() != NULL);
123 ASSERT_TRUE(adapter_->IsInitialized());
124 ASSERT_TRUE(adapter_->IsPresent());
127 void AdapterCallback(scoped_refptr<BluetoothAdapter> adapter) {
128 adapter_ = adapter;
131 void SuccessCallback() {
132 ++success_callback_count_;
135 void ValueCallback(const std::vector<uint8>& value) {
136 ++success_callback_count_;
137 last_read_value_ = value;
140 void GattConnectionCallback(scoped_ptr<BluetoothGattConnection> conn) {
141 ++success_callback_count_;
142 gatt_conn_ = conn.Pass();
145 void NotifySessionCallback(scoped_ptr<BluetoothGattNotifySession> session) {
146 ++success_callback_count_;
147 update_sessions_.push_back(session.release());
148 QuitMessageLoop();
151 void ServiceErrorCallback(BluetoothGattService::GattErrorCode err) {
152 ++error_callback_count_;
153 last_service_error_ = err;
156 void ErrorCallback() {
157 ++error_callback_count_;
160 void DBusErrorCallback(const std::string& error_name,
161 const std::string& error_message) {
162 ++error_callback_count_;
165 void ConnectErrorCallback(BluetoothDevice::ConnectErrorCode error) {
166 ++error_callback_count_;
169 protected:
170 void QuitMessageLoop() {
171 if (base::MessageLoop::current() &&
172 base::MessageLoop::current()->is_running())
173 base::MessageLoop::current()->Quit();
176 base::MessageLoop message_loop_;
178 FakeBluetoothDeviceClient* fake_bluetooth_device_client_;
179 FakeBluetoothGattServiceClient* fake_bluetooth_gatt_service_client_;
180 FakeBluetoothGattCharacteristicClient*
181 fake_bluetooth_gatt_characteristic_client_;
182 FakeBluetoothGattDescriptorClient* fake_bluetooth_gatt_descriptor_client_;
183 scoped_ptr<device::BluetoothGattConnection> gatt_conn_;
184 ScopedVector<BluetoothGattNotifySession> update_sessions_;
185 scoped_refptr<BluetoothAdapter> adapter_;
187 int success_callback_count_;
188 int error_callback_count_;
189 std::vector<uint8> last_read_value_;
190 BluetoothGattService::GattErrorCode last_service_error_;
193 TEST_F(BluetoothGattChromeOSTest, GattConnection) {
194 fake_bluetooth_device_client_->CreateDevice(
195 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
196 dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
197 BluetoothDevice* device = adapter_->GetDevice(
198 FakeBluetoothDeviceClient::kLowEnergyAddress);
199 ASSERT_TRUE(device);
200 ASSERT_FALSE(device->IsConnected());
201 ASSERT_FALSE(gatt_conn_.get());
202 ASSERT_EQ(0, success_callback_count_);
203 ASSERT_EQ(0, error_callback_count_);
205 device->CreateGattConnection(
206 base::Bind(&BluetoothGattChromeOSTest::GattConnectionCallback,
207 base::Unretained(this)),
208 base::Bind(&BluetoothGattChromeOSTest::ConnectErrorCallback,
209 base::Unretained(this)));
211 EXPECT_EQ(1, success_callback_count_);
212 EXPECT_EQ(0, error_callback_count_);
213 EXPECT_TRUE(device->IsConnected());
214 ASSERT_TRUE(gatt_conn_.get());
215 EXPECT_TRUE(gatt_conn_->IsConnected());
216 EXPECT_EQ(FakeBluetoothDeviceClient::kLowEnergyAddress,
217 gatt_conn_->GetDeviceAddress());
219 gatt_conn_->Disconnect();
220 EXPECT_TRUE(device->IsConnected());
221 EXPECT_FALSE(gatt_conn_->IsConnected());
223 device->CreateGattConnection(
224 base::Bind(&BluetoothGattChromeOSTest::GattConnectionCallback,
225 base::Unretained(this)),
226 base::Bind(&BluetoothGattChromeOSTest::ConnectErrorCallback,
227 base::Unretained(this)));
229 EXPECT_EQ(2, success_callback_count_);
230 EXPECT_EQ(0, error_callback_count_);
231 EXPECT_TRUE(device->IsConnected());
232 ASSERT_TRUE(gatt_conn_.get());
233 EXPECT_TRUE(gatt_conn_->IsConnected());
235 device->Disconnect(
236 base::Bind(&BluetoothGattChromeOSTest::SuccessCallback,
237 base::Unretained(this)),
238 base::Bind(&BluetoothGattChromeOSTest::ErrorCallback,
239 base::Unretained(this)));
241 EXPECT_EQ(3, success_callback_count_);
242 EXPECT_EQ(0, error_callback_count_);
243 ASSERT_TRUE(gatt_conn_.get());
244 EXPECT_FALSE(gatt_conn_->IsConnected());
246 device->CreateGattConnection(
247 base::Bind(&BluetoothGattChromeOSTest::GattConnectionCallback,
248 base::Unretained(this)),
249 base::Bind(&BluetoothGattChromeOSTest::ConnectErrorCallback,
250 base::Unretained(this)));
252 EXPECT_EQ(4, success_callback_count_);
253 EXPECT_EQ(0, error_callback_count_);
254 EXPECT_TRUE(device->IsConnected());
255 EXPECT_TRUE(gatt_conn_->IsConnected());
257 fake_bluetooth_device_client_->RemoveDevice(
258 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
259 dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
260 ASSERT_TRUE(gatt_conn_.get());
261 EXPECT_FALSE(gatt_conn_->IsConnected());
264 TEST_F(BluetoothGattChromeOSTest, GattServiceAddedAndRemoved) {
265 // Create a fake LE device. We store the device pointer here because this is a
266 // test. It's unsafe to do this in production as the device might get deleted.
267 fake_bluetooth_device_client_->CreateDevice(
268 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
269 dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
270 BluetoothDevice* device = adapter_->GetDevice(
271 FakeBluetoothDeviceClient::kLowEnergyAddress);
272 ASSERT_TRUE(device);
274 TestBluetoothAdapterObserver observer(adapter_);
276 EXPECT_EQ(0, observer.gatt_service_added_count());
277 EXPECT_EQ(0, observer.gatt_service_removed_count());
278 EXPECT_TRUE(observer.last_gatt_service_id().empty());
279 EXPECT_FALSE(observer.last_gatt_service_uuid().IsValid());
280 EXPECT_TRUE(device->GetGattServices().empty());
282 // Expose the fake Heart Rate Service.
283 fake_bluetooth_gatt_service_client_->ExposeHeartRateService(
284 dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
285 EXPECT_EQ(1, observer.gatt_service_added_count());
286 EXPECT_EQ(0, observer.gatt_service_removed_count());
287 EXPECT_FALSE(observer.last_gatt_service_id().empty());
288 EXPECT_EQ(1U, device->GetGattServices().size());
289 EXPECT_EQ(
290 BluetoothUUID(FakeBluetoothGattServiceClient::kHeartRateServiceUUID),
291 observer.last_gatt_service_uuid());
293 BluetoothGattService* service =
294 device->GetGattService(observer.last_gatt_service_id());
295 EXPECT_FALSE(service->IsLocal());
296 EXPECT_TRUE(service->IsPrimary());
297 EXPECT_EQ(service, device->GetGattServices()[0]);
298 EXPECT_EQ(service, device->GetGattService(service->GetIdentifier()));
300 EXPECT_EQ(observer.last_gatt_service_uuid(), service->GetUUID());
302 // Hide the service.
303 observer.last_gatt_service_uuid() = BluetoothUUID();
304 observer.last_gatt_service_id().clear();
305 fake_bluetooth_gatt_service_client_->HideHeartRateService();
307 EXPECT_EQ(1, observer.gatt_service_added_count());
308 EXPECT_EQ(1, observer.gatt_service_removed_count());
309 EXPECT_FALSE(observer.last_gatt_service_id().empty());
310 EXPECT_TRUE(device->GetGattServices().empty());
311 EXPECT_EQ(
312 BluetoothUUID(FakeBluetoothGattServiceClient::kHeartRateServiceUUID),
313 observer.last_gatt_service_uuid());
315 EXPECT_EQ(NULL, device->GetGattService(observer.last_gatt_service_id()));
317 // Expose the service again.
318 observer.last_gatt_service_uuid() = BluetoothUUID();
319 observer.last_gatt_service_id().clear();
320 fake_bluetooth_gatt_service_client_->ExposeHeartRateService(
321 dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
322 EXPECT_EQ(2, observer.gatt_service_added_count());
323 EXPECT_EQ(1, observer.gatt_service_removed_count());
324 EXPECT_FALSE(observer.last_gatt_service_id().empty());
325 EXPECT_EQ(1U, device->GetGattServices().size());
326 EXPECT_EQ(
327 BluetoothUUID(FakeBluetoothGattServiceClient::kHeartRateServiceUUID),
328 observer.last_gatt_service_uuid());
330 // The object |service| points to should have been deallocated. |device|
331 // should contain a brand new instance.
332 service = device->GetGattService(observer.last_gatt_service_id());
333 EXPECT_EQ(service, device->GetGattServices()[0]);
334 EXPECT_FALSE(service->IsLocal());
335 EXPECT_TRUE(service->IsPrimary());
337 EXPECT_EQ(observer.last_gatt_service_uuid(), service->GetUUID());
339 // Remove the device. The observer should be notified of the removed service.
340 // |device| becomes invalid after this.
341 observer.last_gatt_service_uuid() = BluetoothUUID();
342 observer.last_gatt_service_id().clear();
343 fake_bluetooth_device_client_->RemoveDevice(
344 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
345 dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
347 EXPECT_EQ(2, observer.gatt_service_added_count());
348 EXPECT_EQ(2, observer.gatt_service_removed_count());
349 EXPECT_FALSE(observer.last_gatt_service_id().empty());
350 EXPECT_EQ(
351 BluetoothUUID(FakeBluetoothGattServiceClient::kHeartRateServiceUUID),
352 observer.last_gatt_service_uuid());
353 EXPECT_EQ(
354 NULL, adapter_->GetDevice(FakeBluetoothDeviceClient::kLowEnergyAddress));
357 TEST_F(BluetoothGattChromeOSTest, GattCharacteristicAddedAndRemoved) {
358 fake_bluetooth_device_client_->CreateDevice(
359 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
360 dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
361 BluetoothDevice* device = adapter_->GetDevice(
362 FakeBluetoothDeviceClient::kLowEnergyAddress);
363 ASSERT_TRUE(device);
365 TestBluetoothAdapterObserver observer(adapter_);
367 // Expose the fake Heart Rate service. This will asynchronously expose
368 // characteristics.
369 fake_bluetooth_gatt_service_client_->ExposeHeartRateService(
370 dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
371 ASSERT_EQ(1, observer.gatt_service_added_count());
373 BluetoothGattService* service =
374 device->GetGattService(observer.last_gatt_service_id());
376 EXPECT_EQ(0, observer.gatt_service_changed_count());
377 EXPECT_EQ(0, observer.gatt_discovery_complete_count());
378 EXPECT_EQ(0, observer.gatt_characteristic_added_count());
379 EXPECT_EQ(0, observer.gatt_characteristic_removed_count());
380 EXPECT_EQ(0, observer.gatt_characteristic_value_changed_count());
381 EXPECT_TRUE(service->GetCharacteristics().empty());
383 // Run the message loop so that the characteristics appear.
384 base::MessageLoop::current()->Run();
386 // 3 characteristics should appear. Only 1 of the characteristics sends
387 // value changed signals. Service changed should be fired once for
388 // descriptor added.
389 EXPECT_EQ(0, observer.gatt_service_changed_count());
390 EXPECT_EQ(1, observer.gatt_discovery_complete_count());
391 EXPECT_EQ(3, observer.gatt_characteristic_added_count());
392 EXPECT_EQ(0, observer.gatt_characteristic_removed_count());
393 EXPECT_EQ(0, observer.gatt_characteristic_value_changed_count());
394 EXPECT_EQ(3U, service->GetCharacteristics().size());
396 // Hide the characteristics. 3 removed signals should be received.
397 fake_bluetooth_gatt_characteristic_client_->HideHeartRateCharacteristics();
398 EXPECT_EQ(0, observer.gatt_service_changed_count());
399 EXPECT_EQ(3, observer.gatt_characteristic_added_count());
400 EXPECT_EQ(3, observer.gatt_characteristic_removed_count());
401 EXPECT_EQ(0, observer.gatt_characteristic_value_changed_count());
402 EXPECT_TRUE(service->GetCharacteristics().empty());
404 // Re-expose the heart rate characteristics. We shouldn't get another
405 // GattDiscoveryCompleteForService call, since the service thinks that
406 // discovery is done. On the bluetoothd side, characteristics will be removed
407 // only if the service will also be subsequently removed.
408 fake_bluetooth_gatt_characteristic_client_->ExposeHeartRateCharacteristics(
409 fake_bluetooth_gatt_service_client_->GetHeartRateServicePath());
410 EXPECT_EQ(0, observer.gatt_service_changed_count());
411 EXPECT_EQ(1, observer.gatt_discovery_complete_count());
412 EXPECT_EQ(6, observer.gatt_characteristic_added_count());
413 EXPECT_EQ(3, observer.gatt_characteristic_removed_count());
414 EXPECT_EQ(0, observer.gatt_characteristic_value_changed_count());
415 EXPECT_EQ(3U, service->GetCharacteristics().size());
417 // Hide the service. All characteristics should disappear.
418 fake_bluetooth_gatt_service_client_->HideHeartRateService();
419 EXPECT_EQ(0, observer.gatt_service_changed_count());
420 EXPECT_EQ(6, observer.gatt_characteristic_added_count());
421 EXPECT_EQ(6, observer.gatt_characteristic_removed_count());
422 EXPECT_EQ(0, observer.gatt_characteristic_value_changed_count());
425 TEST_F(BluetoothGattChromeOSTest, GattDescriptorAddedAndRemoved) {
426 fake_bluetooth_device_client_->CreateDevice(
427 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
428 dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
429 BluetoothDevice* device = adapter_->GetDevice(
430 FakeBluetoothDeviceClient::kLowEnergyAddress);
431 ASSERT_TRUE(device);
433 TestBluetoothAdapterObserver observer(adapter_);
435 // Expose the fake Heart Rate service. This will asynchronously expose
436 // characteristics.
437 fake_bluetooth_gatt_service_client_->ExposeHeartRateService(
438 dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
439 ASSERT_EQ(1, observer.gatt_service_added_count());
441 BluetoothGattService* service =
442 device->GetGattService(observer.last_gatt_service_id());
444 EXPECT_EQ(0, observer.gatt_service_changed_count());
445 EXPECT_EQ(0, observer.gatt_descriptor_added_count());
446 EXPECT_EQ(0, observer.gatt_descriptor_removed_count());
447 EXPECT_EQ(0, observer.gatt_descriptor_value_changed_count());
449 EXPECT_TRUE(service->GetCharacteristics().empty());
451 // Run the message loop so that the characteristics appear.
452 base::MessageLoop::current()->Run();
453 EXPECT_EQ(0, observer.gatt_service_changed_count());
455 // Only the Heart Rate Measurement characteristic has a descriptor.
456 EXPECT_EQ(1, observer.gatt_descriptor_added_count());
457 EXPECT_EQ(0, observer.gatt_descriptor_removed_count());
458 EXPECT_EQ(0, observer.gatt_descriptor_value_changed_count());
460 BluetoothGattCharacteristic* characteristic = service->GetCharacteristic(
461 fake_bluetooth_gatt_characteristic_client_->
462 GetBodySensorLocationPath().value());
463 ASSERT_TRUE(characteristic);
464 EXPECT_TRUE(characteristic->GetDescriptors().empty());
466 characteristic = service->GetCharacteristic(
467 fake_bluetooth_gatt_characteristic_client_->
468 GetHeartRateControlPointPath().value());
469 ASSERT_TRUE(characteristic);
470 EXPECT_TRUE(characteristic->GetDescriptors().empty());
472 characteristic = service->GetCharacteristic(
473 fake_bluetooth_gatt_characteristic_client_->
474 GetHeartRateMeasurementPath().value());
475 ASSERT_TRUE(characteristic);
476 EXPECT_EQ(1U, characteristic->GetDescriptors().size());
478 BluetoothGattDescriptor* descriptor = characteristic->GetDescriptors()[0];
479 EXPECT_FALSE(descriptor->IsLocal());
480 EXPECT_EQ(BluetoothGattDescriptor::ClientCharacteristicConfigurationUuid(),
481 descriptor->GetUUID());
482 EXPECT_EQ(descriptor->GetUUID(), observer.last_gatt_descriptor_uuid());
483 EXPECT_EQ(descriptor->GetIdentifier(), observer.last_gatt_descriptor_id());
485 // Hide the descriptor.
486 fake_bluetooth_gatt_descriptor_client_->HideDescriptor(
487 dbus::ObjectPath(descriptor->GetIdentifier()));
488 EXPECT_TRUE(characteristic->GetDescriptors().empty());
489 EXPECT_EQ(0, observer.gatt_service_changed_count());
490 EXPECT_EQ(1, observer.gatt_descriptor_added_count());
491 EXPECT_EQ(1, observer.gatt_descriptor_removed_count());
492 EXPECT_EQ(0, observer.gatt_descriptor_value_changed_count());
494 // Expose the descriptor again.
495 observer.last_gatt_descriptor_id().clear();
496 observer.last_gatt_descriptor_uuid() = BluetoothUUID();
497 fake_bluetooth_gatt_descriptor_client_->ExposeDescriptor(
498 dbus::ObjectPath(characteristic->GetIdentifier()),
499 FakeBluetoothGattDescriptorClient::
500 kClientCharacteristicConfigurationUUID);
501 EXPECT_EQ(0, observer.gatt_service_changed_count());
502 EXPECT_EQ(1U, characteristic->GetDescriptors().size());
503 EXPECT_EQ(2, observer.gatt_descriptor_added_count());
504 EXPECT_EQ(1, observer.gatt_descriptor_removed_count());
505 EXPECT_EQ(0, observer.gatt_descriptor_value_changed_count());
507 descriptor = characteristic->GetDescriptors()[0];
508 EXPECT_FALSE(descriptor->IsLocal());
509 EXPECT_EQ(BluetoothGattDescriptor::ClientCharacteristicConfigurationUuid(),
510 descriptor->GetUUID());
511 EXPECT_EQ(descriptor->GetUUID(), observer.last_gatt_descriptor_uuid());
512 EXPECT_EQ(descriptor->GetIdentifier(), observer.last_gatt_descriptor_id());
515 TEST_F(BluetoothGattChromeOSTest, AdapterAddedAfterGattService) {
516 // This unit test tests that all remote GATT objects are created for D-Bus
517 // objects that were already exposed.
518 adapter_ = NULL;
519 ASSERT_FALSE(device::BluetoothAdapterFactory::HasSharedInstanceForTesting());
521 // Create the fake D-Bus objects.
522 fake_bluetooth_device_client_->CreateDevice(
523 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
524 dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
525 fake_bluetooth_gatt_service_client_->ExposeHeartRateService(
526 dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
527 while (!fake_bluetooth_gatt_characteristic_client_->IsHeartRateVisible())
528 base::RunLoop().RunUntilIdle();
529 ASSERT_TRUE(fake_bluetooth_gatt_service_client_->IsHeartRateVisible());
530 ASSERT_TRUE(fake_bluetooth_gatt_characteristic_client_->IsHeartRateVisible());
532 // Create the adapter. This should create all the GATT objects.
533 GetAdapter();
534 BluetoothDevice* device = adapter_->GetDevice(
535 FakeBluetoothDeviceClient::kLowEnergyAddress);
536 ASSERT_TRUE(device);
537 EXPECT_EQ(1U, device->GetGattServices().size());
539 BluetoothGattService* service = device->GetGattServices()[0];
540 ASSERT_TRUE(service);
541 EXPECT_FALSE(service->IsLocal());
542 EXPECT_TRUE(service->IsPrimary());
543 EXPECT_EQ(
544 BluetoothUUID(FakeBluetoothGattServiceClient::kHeartRateServiceUUID),
545 service->GetUUID());
546 EXPECT_EQ(service, device->GetGattServices()[0]);
547 EXPECT_EQ(service, device->GetGattService(service->GetIdentifier()));
548 EXPECT_FALSE(service->IsLocal());
549 EXPECT_EQ(3U, service->GetCharacteristics().size());
551 BluetoothGattCharacteristic* characteristic = service->GetCharacteristic(
552 fake_bluetooth_gatt_characteristic_client_->
553 GetBodySensorLocationPath().value());
554 ASSERT_TRUE(characteristic);
555 EXPECT_EQ(
556 BluetoothUUID(FakeBluetoothGattCharacteristicClient::
557 kBodySensorLocationUUID),
558 characteristic->GetUUID());
559 EXPECT_FALSE(characteristic->IsLocal());
560 EXPECT_TRUE(characteristic->GetDescriptors().empty());
562 characteristic = service->GetCharacteristic(
563 fake_bluetooth_gatt_characteristic_client_->
564 GetHeartRateControlPointPath().value());
565 ASSERT_TRUE(characteristic);
566 EXPECT_EQ(
567 BluetoothUUID(FakeBluetoothGattCharacteristicClient::
568 kHeartRateControlPointUUID),
569 characteristic->GetUUID());
570 EXPECT_FALSE(characteristic->IsLocal());
571 EXPECT_TRUE(characteristic->GetDescriptors().empty());
573 characteristic = service->GetCharacteristic(
574 fake_bluetooth_gatt_characteristic_client_->
575 GetHeartRateMeasurementPath().value());
576 ASSERT_TRUE(characteristic);
577 EXPECT_EQ(
578 BluetoothUUID(FakeBluetoothGattCharacteristicClient::
579 kHeartRateMeasurementUUID),
580 characteristic->GetUUID());
581 EXPECT_FALSE(characteristic->IsLocal());
582 EXPECT_EQ(1U, characteristic->GetDescriptors().size());
584 BluetoothGattDescriptor* descriptor = characteristic->GetDescriptors()[0];
585 ASSERT_TRUE(descriptor);
586 EXPECT_EQ(BluetoothGattDescriptor::ClientCharacteristicConfigurationUuid(),
587 descriptor->GetUUID());
588 EXPECT_FALSE(descriptor->IsLocal());
591 TEST_F(BluetoothGattChromeOSTest, GattCharacteristicValue) {
592 fake_bluetooth_device_client_->CreateDevice(
593 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
594 dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
595 BluetoothDevice* device = adapter_->GetDevice(
596 FakeBluetoothDeviceClient::kLowEnergyAddress);
597 ASSERT_TRUE(device);
599 TestBluetoothAdapterObserver observer(adapter_);
601 // Expose the fake Heart Rate service. This will asynchronously expose
602 // characteristics.
603 fake_bluetooth_gatt_service_client_->ExposeHeartRateService(
604 dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
605 ASSERT_EQ(1, observer.gatt_service_added_count());
607 BluetoothGattService* service =
608 device->GetGattService(observer.last_gatt_service_id());
610 EXPECT_EQ(0, observer.gatt_characteristic_value_changed_count());
612 // Run the message loop so that the characteristics appear.
613 base::MessageLoop::current()->Run();
615 // Issue write request to non-writable characteristics.
616 observer.Reset();
618 std::vector<uint8> write_value;
619 write_value.push_back(0x01);
620 BluetoothGattCharacteristic* characteristic =
621 service->GetCharacteristic(fake_bluetooth_gatt_characteristic_client_->
622 GetHeartRateMeasurementPath().value());
623 ASSERT_TRUE(characteristic);
624 EXPECT_FALSE(characteristic->IsNotifying());
625 EXPECT_EQ(fake_bluetooth_gatt_characteristic_client_->
626 GetHeartRateMeasurementPath().value(),
627 characteristic->GetIdentifier());
628 EXPECT_EQ(kHeartRateMeasurementUUID, characteristic->GetUUID());
629 characteristic->WriteRemoteCharacteristic(
630 write_value,
631 base::Bind(&BluetoothGattChromeOSTest::SuccessCallback,
632 base::Unretained(this)),
633 base::Bind(&BluetoothGattChromeOSTest::ServiceErrorCallback,
634 base::Unretained(this)));
635 EXPECT_TRUE(observer.last_gatt_characteristic_id().empty());
636 EXPECT_FALSE(observer.last_gatt_characteristic_uuid().IsValid());
637 EXPECT_EQ(0, success_callback_count_);
638 EXPECT_EQ(1, error_callback_count_);
639 EXPECT_EQ(BluetoothGattService::GATT_ERROR_NOT_SUPPORTED,
640 last_service_error_);
641 EXPECT_EQ(0, observer.gatt_characteristic_value_changed_count());
643 characteristic = service->GetCharacteristic(
644 fake_bluetooth_gatt_characteristic_client_->
645 GetBodySensorLocationPath().value());
646 ASSERT_TRUE(characteristic);
647 EXPECT_EQ(fake_bluetooth_gatt_characteristic_client_->
648 GetBodySensorLocationPath().value(),
649 characteristic->GetIdentifier());
650 EXPECT_EQ(kBodySensorLocationUUID, characteristic->GetUUID());
651 characteristic->WriteRemoteCharacteristic(
652 write_value,
653 base::Bind(&BluetoothGattChromeOSTest::SuccessCallback,
654 base::Unretained(this)),
655 base::Bind(&BluetoothGattChromeOSTest::ServiceErrorCallback,
656 base::Unretained(this)));
657 EXPECT_TRUE(observer.last_gatt_characteristic_id().empty());
658 EXPECT_FALSE(observer.last_gatt_characteristic_uuid().IsValid());
659 EXPECT_EQ(0, success_callback_count_);
660 EXPECT_EQ(2, error_callback_count_);
661 EXPECT_EQ(BluetoothGattService::GATT_ERROR_NOT_PERMITTED,
662 last_service_error_);
663 EXPECT_EQ(0, observer.gatt_characteristic_value_changed_count());
665 // Issue write request to writable characteristic. The "Body Sensor Location"
666 // characteristic does not send notifications and WriteValue does not result
667 // in a CharacteristicValueChanged event, thus no such event should be
668 // received.
669 characteristic = service->GetCharacteristic(
670 fake_bluetooth_gatt_characteristic_client_->
671 GetHeartRateControlPointPath().value());
672 ASSERT_TRUE(characteristic);
673 EXPECT_EQ(fake_bluetooth_gatt_characteristic_client_->
674 GetHeartRateControlPointPath().value(),
675 characteristic->GetIdentifier());
676 EXPECT_EQ(kHeartRateControlPointUUID, characteristic->GetUUID());
677 characteristic->WriteRemoteCharacteristic(
678 write_value,
679 base::Bind(&BluetoothGattChromeOSTest::SuccessCallback,
680 base::Unretained(this)),
681 base::Bind(&BluetoothGattChromeOSTest::ServiceErrorCallback,
682 base::Unretained(this)));
683 EXPECT_TRUE(observer.last_gatt_characteristic_id().empty());
684 EXPECT_FALSE(observer.last_gatt_characteristic_uuid().IsValid());
685 EXPECT_EQ(1, success_callback_count_);
686 EXPECT_EQ(2, error_callback_count_);
687 EXPECT_EQ(0, observer.gatt_characteristic_value_changed_count());
689 // Issue some invalid write requests to the characteristic.
690 // The value should still not change.
692 std::vector<uint8> invalid_write_length;
693 invalid_write_length.push_back(0x01);
694 invalid_write_length.push_back(0x00);
695 characteristic->WriteRemoteCharacteristic(
696 invalid_write_length,
697 base::Bind(&BluetoothGattChromeOSTest::SuccessCallback,
698 base::Unretained(this)),
699 base::Bind(&BluetoothGattChromeOSTest::ServiceErrorCallback,
700 base::Unretained(this)));
701 EXPECT_EQ(1, success_callback_count_);
702 EXPECT_EQ(3, error_callback_count_);
703 EXPECT_EQ(BluetoothGattService::GATT_ERROR_INVALID_LENGTH,
704 last_service_error_);
705 EXPECT_EQ(0, observer.gatt_characteristic_value_changed_count());
707 std::vector<uint8> invalid_write_value;
708 invalid_write_value.push_back(0x02);
709 characteristic->WriteRemoteCharacteristic(
710 invalid_write_value,
711 base::Bind(&BluetoothGattChromeOSTest::SuccessCallback,
712 base::Unretained(this)),
713 base::Bind(&BluetoothGattChromeOSTest::ServiceErrorCallback,
714 base::Unretained(this)));
715 EXPECT_EQ(1, success_callback_count_);
716 EXPECT_EQ(4, error_callback_count_);
717 EXPECT_EQ(BluetoothGattService::GATT_ERROR_FAILED, last_service_error_);
718 EXPECT_EQ(0, observer.gatt_characteristic_value_changed_count());
720 // Issue a read request. A successful read results in a
721 // CharacteristicValueChanged notification.
722 characteristic = service->GetCharacteristic(
723 fake_bluetooth_gatt_characteristic_client_->
724 GetBodySensorLocationPath().value());
725 ASSERT_TRUE(characteristic);
726 EXPECT_EQ(fake_bluetooth_gatt_characteristic_client_->
727 GetBodySensorLocationPath().value(),
728 characteristic->GetIdentifier());
729 EXPECT_EQ(kBodySensorLocationUUID, characteristic->GetUUID());
730 characteristic->ReadRemoteCharacteristic(
731 base::Bind(&BluetoothGattChromeOSTest::ValueCallback,
732 base::Unretained(this)),
733 base::Bind(&BluetoothGattChromeOSTest::ServiceErrorCallback,
734 base::Unretained(this)));
735 EXPECT_EQ(2, success_callback_count_);
736 EXPECT_EQ(4, error_callback_count_);
737 EXPECT_EQ(1, observer.gatt_characteristic_value_changed_count());
738 EXPECT_TRUE(ValuesEqual(characteristic->GetValue(), last_read_value_));
740 // Test long-running actions.
741 fake_bluetooth_gatt_characteristic_client_->SetExtraProcessing(1);
742 characteristic = service->GetCharacteristic(
743 fake_bluetooth_gatt_characteristic_client_->GetBodySensorLocationPath()
744 .value());
745 ASSERT_TRUE(characteristic);
746 EXPECT_EQ(
747 fake_bluetooth_gatt_characteristic_client_->GetBodySensorLocationPath()
748 .value(),
749 characteristic->GetIdentifier());
750 EXPECT_EQ(kBodySensorLocationUUID, characteristic->GetUUID());
751 characteristic->ReadRemoteCharacteristic(
752 base::Bind(&BluetoothGattChromeOSTest::ValueCallback,
753 base::Unretained(this)),
754 base::Bind(&BluetoothGattChromeOSTest::ServiceErrorCallback,
755 base::Unretained(this)));
757 // Callback counts shouldn't change, this one will be delayed until after
758 // tne next one.
759 EXPECT_EQ(2, success_callback_count_);
760 EXPECT_EQ(4, error_callback_count_);
761 EXPECT_EQ(1, observer.gatt_characteristic_value_changed_count());
763 // Next read should error because IN_PROGRESS
764 characteristic->ReadRemoteCharacteristic(
765 base::Bind(&BluetoothGattChromeOSTest::ValueCallback,
766 base::Unretained(this)),
767 base::Bind(&BluetoothGattChromeOSTest::ServiceErrorCallback,
768 base::Unretained(this)));
769 EXPECT_EQ(5, error_callback_count_);
770 EXPECT_EQ(BluetoothGattService::GATT_ERROR_IN_PROGRESS, last_service_error_);
772 // But previous call finished.
773 EXPECT_EQ(3, success_callback_count_);
774 EXPECT_EQ(2, observer.gatt_characteristic_value_changed_count());
775 EXPECT_TRUE(ValuesEqual(characteristic->GetValue(), last_read_value_));
776 fake_bluetooth_gatt_characteristic_client_->SetExtraProcessing(0);
778 // Test unauthorized actions.
779 fake_bluetooth_gatt_characteristic_client_->SetAuthorized(false);
780 characteristic->ReadRemoteCharacteristic(
781 base::Bind(&BluetoothGattChromeOSTest::ValueCallback,
782 base::Unretained(this)),
783 base::Bind(&BluetoothGattChromeOSTest::ServiceErrorCallback,
784 base::Unretained(this)));
785 EXPECT_EQ(3, success_callback_count_);
786 EXPECT_EQ(6, error_callback_count_);
787 EXPECT_EQ(BluetoothGattService::GATT_ERROR_NOT_AUTHORIZED,
788 last_service_error_);
789 EXPECT_EQ(2, observer.gatt_characteristic_value_changed_count());
790 fake_bluetooth_gatt_characteristic_client_->SetAuthorized(true);
792 // Test unauthenticated / needs login.
793 fake_bluetooth_gatt_characteristic_client_->SetAuthenticated(false);
794 characteristic->ReadRemoteCharacteristic(
795 base::Bind(&BluetoothGattChromeOSTest::ValueCallback,
796 base::Unretained(this)),
797 base::Bind(&BluetoothGattChromeOSTest::ServiceErrorCallback,
798 base::Unretained(this)));
799 EXPECT_EQ(3, success_callback_count_);
800 EXPECT_EQ(7, error_callback_count_);
801 EXPECT_EQ(BluetoothGattService::GATT_ERROR_NOT_PAIRED, last_service_error_);
802 EXPECT_EQ(2, observer.gatt_characteristic_value_changed_count());
803 fake_bluetooth_gatt_characteristic_client_->SetAuthenticated(true);
806 TEST_F(BluetoothGattChromeOSTest, GattCharacteristicProperties) {
807 fake_bluetooth_device_client_->CreateDevice(
808 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
809 dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
810 BluetoothDevice* device = adapter_->GetDevice(
811 FakeBluetoothDeviceClient::kLowEnergyAddress);
812 ASSERT_TRUE(device);
814 TestBluetoothAdapterObserver observer(adapter_);
816 // Expose the fake Heart Rate service. This will asynchronously expose
817 // characteristics.
818 fake_bluetooth_gatt_service_client_->ExposeHeartRateService(
819 dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
821 BluetoothGattService* service =
822 device->GetGattService(observer.last_gatt_service_id());
824 EXPECT_TRUE(service->GetCharacteristics().empty());
826 // Run the message loop so that the characteristics appear.
827 base::MessageLoop::current()->Run();
829 BluetoothGattCharacteristic *characteristic = service->GetCharacteristic(
830 fake_bluetooth_gatt_characteristic_client_->
831 GetBodySensorLocationPath().value());
832 EXPECT_EQ(BluetoothGattCharacteristic::PROPERTY_READ,
833 characteristic->GetProperties());
835 characteristic = service->GetCharacteristic(
836 fake_bluetooth_gatt_characteristic_client_->
837 GetHeartRateControlPointPath().value());
838 EXPECT_EQ(BluetoothGattCharacteristic::PROPERTY_WRITE,
839 characteristic->GetProperties());
841 characteristic = service->GetCharacteristic(
842 fake_bluetooth_gatt_characteristic_client_->
843 GetHeartRateMeasurementPath().value());
844 EXPECT_EQ(BluetoothGattCharacteristic::PROPERTY_NOTIFY,
845 characteristic->GetProperties());
848 TEST_F(BluetoothGattChromeOSTest, GattDescriptorValue) {
849 fake_bluetooth_device_client_->CreateDevice(
850 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
851 dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
852 BluetoothDevice* device = adapter_->GetDevice(
853 FakeBluetoothDeviceClient::kLowEnergyAddress);
854 ASSERT_TRUE(device);
856 TestBluetoothAdapterObserver observer(adapter_);
858 // Expose the fake Heart Rate service. This will asynchronously expose
859 // characteristics.
860 fake_bluetooth_gatt_service_client_->ExposeHeartRateService(
861 dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
862 ASSERT_EQ(1, observer.gatt_service_added_count());
864 BluetoothGattService* service =
865 device->GetGattService(observer.last_gatt_service_id());
867 EXPECT_EQ(0, observer.gatt_service_changed_count());
868 EXPECT_EQ(0, observer.gatt_discovery_complete_count());
869 EXPECT_EQ(0, observer.gatt_descriptor_value_changed_count());
870 EXPECT_TRUE(service->GetCharacteristics().empty());
872 // Run the message loop so that the characteristics appear.
873 base::MessageLoop::current()->Run();
874 EXPECT_EQ(0, observer.gatt_service_changed_count());
875 EXPECT_EQ(1, observer.gatt_discovery_complete_count());
877 // Only the Heart Rate Measurement characteristic has a descriptor.
878 BluetoothGattCharacteristic* characteristic = service->GetCharacteristic(
879 fake_bluetooth_gatt_characteristic_client_->
880 GetHeartRateMeasurementPath().value());
881 ASSERT_TRUE(characteristic);
882 EXPECT_EQ(1U, characteristic->GetDescriptors().size());
883 EXPECT_FALSE(characteristic->IsNotifying());
885 BluetoothGattDescriptor* descriptor = characteristic->GetDescriptors()[0];
886 EXPECT_FALSE(descriptor->IsLocal());
887 EXPECT_EQ(BluetoothGattDescriptor::ClientCharacteristicConfigurationUuid(),
888 descriptor->GetUUID());
890 std::vector<uint8_t> desc_value = {0x00, 0x00};
892 /* The cached value will be empty until the first read request */
893 EXPECT_FALSE(ValuesEqual(desc_value, descriptor->GetValue()));
894 EXPECT_TRUE(descriptor->GetValue().empty());
896 EXPECT_EQ(0, success_callback_count_);
897 EXPECT_EQ(0, error_callback_count_);
898 EXPECT_TRUE(last_read_value_.empty());
900 // Read value. GattDescriptorValueChanged event will be sent after a
901 // successful read.
902 descriptor->ReadRemoteDescriptor(
903 base::Bind(&BluetoothGattChromeOSTest::ValueCallback,
904 base::Unretained(this)),
905 base::Bind(&BluetoothGattChromeOSTest::ServiceErrorCallback,
906 base::Unretained(this)));
907 EXPECT_EQ(1, success_callback_count_);
908 EXPECT_EQ(0, error_callback_count_);
909 EXPECT_TRUE(ValuesEqual(last_read_value_, descriptor->GetValue()));
910 EXPECT_TRUE(ValuesEqual(desc_value, descriptor->GetValue()));
911 EXPECT_EQ(0, observer.gatt_service_changed_count());
912 EXPECT_EQ(1, observer.gatt_descriptor_value_changed_count());
914 // Write value. Writes to this descriptor will fail.
915 desc_value[0] = 0x03;
916 descriptor->WriteRemoteDescriptor(
917 desc_value,
918 base::Bind(&BluetoothGattChromeOSTest::SuccessCallback,
919 base::Unretained(this)),
920 base::Bind(&BluetoothGattChromeOSTest::ServiceErrorCallback,
921 base::Unretained(this)));
922 EXPECT_EQ(1, success_callback_count_);
923 EXPECT_EQ(1, error_callback_count_);
924 EXPECT_EQ(BluetoothGattService::GATT_ERROR_NOT_PERMITTED,
925 last_service_error_);
926 EXPECT_TRUE(ValuesEqual(last_read_value_, descriptor->GetValue()));
927 EXPECT_FALSE(ValuesEqual(desc_value, descriptor->GetValue()));
928 EXPECT_EQ(0, observer.gatt_service_changed_count());
929 EXPECT_EQ(1, observer.gatt_descriptor_value_changed_count());
931 // Read value. The value should remain unchanged.
932 descriptor->ReadRemoteDescriptor(
933 base::Bind(&BluetoothGattChromeOSTest::ValueCallback,
934 base::Unretained(this)),
935 base::Bind(&BluetoothGattChromeOSTest::ServiceErrorCallback,
936 base::Unretained(this)));
937 EXPECT_EQ(2, success_callback_count_);
938 EXPECT_EQ(1, error_callback_count_);
939 EXPECT_TRUE(ValuesEqual(last_read_value_, descriptor->GetValue()));
940 EXPECT_FALSE(ValuesEqual(desc_value, descriptor->GetValue()));
941 EXPECT_EQ(0, observer.gatt_service_changed_count());
942 EXPECT_EQ(1, observer.gatt_descriptor_value_changed_count());
944 // Start notifications on the descriptor's characteristic. The descriptor
945 // value should change.
946 characteristic->StartNotifySession(
947 base::Bind(&BluetoothGattChromeOSTest::NotifySessionCallback,
948 base::Unretained(this)),
949 base::Bind(&BluetoothGattChromeOSTest::ServiceErrorCallback,
950 base::Unretained(this)));
951 base::MessageLoop::current()->Run();
952 EXPECT_EQ(3, success_callback_count_);
953 EXPECT_EQ(1, error_callback_count_);
954 EXPECT_EQ(1U, update_sessions_.size());
955 EXPECT_TRUE(characteristic->IsNotifying());
957 // Read the new descriptor value. We should receive a value updated event.
958 descriptor->ReadRemoteDescriptor(
959 base::Bind(&BluetoothGattChromeOSTest::ValueCallback,
960 base::Unretained(this)),
961 base::Bind(&BluetoothGattChromeOSTest::ServiceErrorCallback,
962 base::Unretained(this)));
963 EXPECT_EQ(4, success_callback_count_);
964 EXPECT_EQ(1, error_callback_count_);
965 EXPECT_TRUE(ValuesEqual(last_read_value_, descriptor->GetValue()));
966 EXPECT_FALSE(ValuesEqual(desc_value, descriptor->GetValue()));
967 EXPECT_EQ(0, observer.gatt_service_changed_count());
968 EXPECT_EQ(2, observer.gatt_descriptor_value_changed_count());
971 TEST_F(BluetoothGattChromeOSTest, NotifySessions) {
972 fake_bluetooth_device_client_->CreateDevice(
973 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
974 dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
975 BluetoothDevice* device =
976 adapter_->GetDevice(FakeBluetoothDeviceClient::kLowEnergyAddress);
977 ASSERT_TRUE(device);
979 TestBluetoothAdapterObserver observer(adapter_);
981 // Expose the fake Heart Rate service. This will asynchronously expose
982 // characteristics.
983 fake_bluetooth_gatt_service_client_->ExposeHeartRateService(
984 dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
985 ASSERT_EQ(1, observer.gatt_service_added_count());
987 BluetoothGattService* service =
988 device->GetGattService(observer.last_gatt_service_id());
990 EXPECT_EQ(0, observer.gatt_characteristic_value_changed_count());
992 // Run the message loop so that the characteristics appear.
993 base::MessageLoop::current()->Run();
995 BluetoothGattCharacteristic* characteristic = service->GetCharacteristic(
996 fake_bluetooth_gatt_characteristic_client_->GetHeartRateMeasurementPath()
997 .value());
998 ASSERT_TRUE(characteristic);
999 EXPECT_FALSE(characteristic->IsNotifying());
1000 EXPECT_TRUE(update_sessions_.empty());
1002 // Request to start notifications.
1003 characteristic->StartNotifySession(
1004 base::Bind(&BluetoothGattChromeOSTest::NotifySessionCallback,
1005 base::Unretained(this)),
1006 base::Bind(&BluetoothGattChromeOSTest::ServiceErrorCallback,
1007 base::Unretained(this)));
1009 // The operation still hasn't completed but we should have received the first
1010 // notification.
1011 EXPECT_EQ(0, success_callback_count_);
1012 EXPECT_EQ(0, error_callback_count_);
1013 EXPECT_EQ(1, observer.gatt_characteristic_value_changed_count());
1014 EXPECT_TRUE(update_sessions_.empty());
1016 // Send a two more requests, which should get queued.
1017 characteristic->StartNotifySession(
1018 base::Bind(&BluetoothGattChromeOSTest::NotifySessionCallback,
1019 base::Unretained(this)),
1020 base::Bind(&BluetoothGattChromeOSTest::ServiceErrorCallback,
1021 base::Unretained(this)));
1022 characteristic->StartNotifySession(
1023 base::Bind(&BluetoothGattChromeOSTest::NotifySessionCallback,
1024 base::Unretained(this)),
1025 base::Bind(&BluetoothGattChromeOSTest::ServiceErrorCallback,
1026 base::Unretained(this)));
1027 EXPECT_EQ(0, success_callback_count_);
1028 EXPECT_EQ(0, error_callback_count_);
1029 EXPECT_EQ(1, observer.gatt_characteristic_value_changed_count());
1030 EXPECT_TRUE(update_sessions_.empty());
1031 EXPECT_TRUE(characteristic->IsNotifying());
1033 // Run the main loop. The initial call should complete. The queued call should
1034 // succeed immediately.
1035 base::MessageLoop::current()->Run();
1037 EXPECT_EQ(3, success_callback_count_);
1038 EXPECT_EQ(0, error_callback_count_);
1039 EXPECT_EQ(1, observer.gatt_characteristic_value_changed_count());
1040 EXPECT_EQ(3U, update_sessions_.size());
1042 // Notifications should be getting sent regularly now.
1043 base::MessageLoop::current()->Run();
1044 EXPECT_GT(observer.gatt_characteristic_value_changed_count(), 1);
1046 // Stop one of the sessions. The session should become inactive but the
1047 // characteristic should still be notifying.
1048 BluetoothGattNotifySession* session = update_sessions_[0];
1049 EXPECT_TRUE(session->IsActive());
1050 session->Stop(base::Bind(&BluetoothGattChromeOSTest::SuccessCallback,
1051 base::Unretained(this)));
1052 EXPECT_EQ(4, success_callback_count_);
1053 EXPECT_EQ(0, error_callback_count_);
1054 EXPECT_FALSE(session->IsActive());
1055 EXPECT_EQ(characteristic->GetIdentifier(),
1056 session->GetCharacteristicIdentifier());
1057 EXPECT_TRUE(characteristic->IsNotifying());
1059 // Delete another session. Characteristic should still be notifying.
1060 update_sessions_.pop_back();
1061 EXPECT_EQ(2U, update_sessions_.size());
1062 EXPECT_TRUE(characteristic->IsNotifying());
1063 EXPECT_FALSE(update_sessions_[0]->IsActive());
1064 EXPECT_TRUE(update_sessions_[1]->IsActive());
1066 // Clear the last session.
1067 update_sessions_.clear();
1068 EXPECT_TRUE(update_sessions_.empty());
1069 EXPECT_FALSE(characteristic->IsNotifying());
1071 success_callback_count_ = 0;
1072 observer.Reset();
1074 // Enable notifications again.
1075 characteristic->StartNotifySession(
1076 base::Bind(&BluetoothGattChromeOSTest::NotifySessionCallback,
1077 base::Unretained(this)),
1078 base::Bind(&BluetoothGattChromeOSTest::ServiceErrorCallback,
1079 base::Unretained(this)));
1080 EXPECT_EQ(0, success_callback_count_);
1081 EXPECT_EQ(0, error_callback_count_);
1082 EXPECT_EQ(1, observer.gatt_characteristic_value_changed_count());
1083 EXPECT_TRUE(update_sessions_.empty());
1084 EXPECT_TRUE(characteristic->IsNotifying());
1086 // Run the message loop. Notifications should begin.
1087 base::MessageLoop::current()->Run();
1089 EXPECT_EQ(1, success_callback_count_);
1090 EXPECT_EQ(0, error_callback_count_);
1091 EXPECT_EQ(1, observer.gatt_characteristic_value_changed_count());
1092 EXPECT_EQ(1U, update_sessions_.size());
1093 EXPECT_TRUE(update_sessions_[0]->IsActive());
1094 EXPECT_TRUE(characteristic->IsNotifying());
1096 // Check that notifications are happening.
1097 base::MessageLoop::current()->Run();
1098 EXPECT_GT(observer.gatt_characteristic_value_changed_count(), 1);
1100 // Request another session. This should return immediately.
1101 characteristic->StartNotifySession(
1102 base::Bind(&BluetoothGattChromeOSTest::NotifySessionCallback,
1103 base::Unretained(this)),
1104 base::Bind(&BluetoothGattChromeOSTest::ServiceErrorCallback,
1105 base::Unretained(this)));
1106 EXPECT_EQ(2, success_callback_count_);
1107 EXPECT_EQ(0, error_callback_count_);
1108 EXPECT_EQ(2U, update_sessions_.size());
1109 EXPECT_TRUE(update_sessions_[0]->IsActive());
1110 EXPECT_TRUE(update_sessions_[1]->IsActive());
1111 EXPECT_TRUE(characteristic->IsNotifying());
1113 // Hide the characteristic. The sessions should become inactive.
1114 fake_bluetooth_gatt_characteristic_client_->HideHeartRateCharacteristics();
1115 EXPECT_EQ(2U, update_sessions_.size());
1116 EXPECT_FALSE(update_sessions_[0]->IsActive());
1117 EXPECT_FALSE(update_sessions_[1]->IsActive());
1120 TEST_F(BluetoothGattChromeOSTest, NotifySessionsMadeInactive) {
1121 fake_bluetooth_device_client_->CreateDevice(
1122 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
1123 dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
1124 BluetoothDevice* device =
1125 adapter_->GetDevice(FakeBluetoothDeviceClient::kLowEnergyAddress);
1126 ASSERT_TRUE(device);
1128 TestBluetoothAdapterObserver observer(adapter_);
1130 // Expose the fake Heart Rate service. This will asynchronously expose
1131 // characteristics.
1132 fake_bluetooth_gatt_service_client_->ExposeHeartRateService(
1133 dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
1134 ASSERT_EQ(1, observer.gatt_service_added_count());
1136 BluetoothGattService* service =
1137 device->GetGattService(observer.last_gatt_service_id());
1139 EXPECT_EQ(0, observer.gatt_characteristic_value_changed_count());
1141 // Run the message loop so that the characteristics appear.
1142 base::MessageLoop::current()->Run();
1144 BluetoothGattCharacteristic* characteristic = service->GetCharacteristic(
1145 fake_bluetooth_gatt_characteristic_client_->GetHeartRateMeasurementPath()
1146 .value());
1147 ASSERT_TRUE(characteristic);
1148 EXPECT_FALSE(characteristic->IsNotifying());
1149 EXPECT_TRUE(update_sessions_.empty());
1151 // Send several requests to start notifications.
1152 characteristic->StartNotifySession(
1153 base::Bind(&BluetoothGattChromeOSTest::NotifySessionCallback,
1154 base::Unretained(this)),
1155 base::Bind(&BluetoothGattChromeOSTest::ServiceErrorCallback,
1156 base::Unretained(this)));
1157 characteristic->StartNotifySession(
1158 base::Bind(&BluetoothGattChromeOSTest::NotifySessionCallback,
1159 base::Unretained(this)),
1160 base::Bind(&BluetoothGattChromeOSTest::ServiceErrorCallback,
1161 base::Unretained(this)));
1162 characteristic->StartNotifySession(
1163 base::Bind(&BluetoothGattChromeOSTest::NotifySessionCallback,
1164 base::Unretained(this)),
1165 base::Bind(&BluetoothGattChromeOSTest::ServiceErrorCallback,
1166 base::Unretained(this)));
1167 characteristic->StartNotifySession(
1168 base::Bind(&BluetoothGattChromeOSTest::NotifySessionCallback,
1169 base::Unretained(this)),
1170 base::Bind(&BluetoothGattChromeOSTest::ServiceErrorCallback,
1171 base::Unretained(this)));
1173 // The operation still hasn't completed but we should have received the first
1174 // notification.
1175 EXPECT_EQ(0, success_callback_count_);
1176 EXPECT_EQ(0, error_callback_count_);
1177 EXPECT_EQ(1, observer.gatt_characteristic_value_changed_count());
1178 EXPECT_TRUE(characteristic->IsNotifying());
1179 EXPECT_TRUE(update_sessions_.empty());
1181 // Run the main loop. The initial call should complete. The queued calls
1182 // should succeed immediately.
1183 base::MessageLoop::current()->Run();
1185 EXPECT_EQ(4, success_callback_count_);
1186 EXPECT_EQ(0, error_callback_count_);
1187 EXPECT_EQ(1, observer.gatt_characteristic_value_changed_count());
1188 EXPECT_TRUE(characteristic->IsNotifying());
1189 EXPECT_EQ(4U, update_sessions_.size());
1191 for (int i = 0; i < 4; i++)
1192 EXPECT_TRUE(update_sessions_[0]->IsActive());
1194 // Stop notifications directly through the client. The sessions should get
1195 // marked as inactive.
1196 fake_bluetooth_gatt_characteristic_client_->StopNotify(
1197 fake_bluetooth_gatt_characteristic_client_->GetHeartRateMeasurementPath(),
1198 base::Bind(&BluetoothGattChromeOSTest::SuccessCallback,
1199 base::Unretained(this)),
1200 base::Bind(&BluetoothGattChromeOSTest::DBusErrorCallback,
1201 base::Unretained(this)));
1202 EXPECT_EQ(5, success_callback_count_);
1203 EXPECT_EQ(0, error_callback_count_);
1204 EXPECT_FALSE(characteristic->IsNotifying());
1205 EXPECT_EQ(4U, update_sessions_.size());
1207 for (int i = 0; i < 4; i++)
1208 EXPECT_FALSE(update_sessions_[0]->IsActive());
1210 // It should be possible to restart notifications and the call should reset
1211 // the session count and make a request through the client.
1212 update_sessions_.clear();
1213 success_callback_count_ = 0;
1214 observer.Reset();
1215 characteristic->StartNotifySession(
1216 base::Bind(&BluetoothGattChromeOSTest::NotifySessionCallback,
1217 base::Unretained(this)),
1218 base::Bind(&BluetoothGattChromeOSTest::ServiceErrorCallback,
1219 base::Unretained(this)));
1221 EXPECT_EQ(0, success_callback_count_);
1222 EXPECT_EQ(0, error_callback_count_);
1223 EXPECT_EQ(1, observer.gatt_characteristic_value_changed_count());
1224 EXPECT_TRUE(characteristic->IsNotifying());
1225 EXPECT_TRUE(update_sessions_.empty());
1227 base::MessageLoop::current()->Run();
1229 EXPECT_EQ(1, success_callback_count_);
1230 EXPECT_EQ(0, error_callback_count_);
1231 EXPECT_EQ(1, observer.gatt_characteristic_value_changed_count());
1232 EXPECT_TRUE(characteristic->IsNotifying());
1233 EXPECT_EQ(1U, update_sessions_.size());
1234 EXPECT_TRUE(update_sessions_[0]->IsActive());
1237 } // namespace chromeos