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
;
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
52 bool ValuesEqual(const std::vector
<uint8
>& value0
,
53 const std::vector
<uint8
>& value1
) {
54 if (value0
.size() != value1
.size())
56 for (size_t i
= 0; i
< value0
.size(); ++i
)
57 if (value0
[i
] != value1
[i
])
64 class BluetoothGattChromeOSTest
: public testing::Test
{
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
));
104 adapter_
->SetPowered(
106 base::Bind(&base::DoNothing
),
107 base::Bind(&base::DoNothing
));
108 ASSERT_TRUE(adapter_
->IsPowered());
111 void TearDown() override
{
113 update_sessions_
.clear();
115 DBusThreadManager::Shutdown();
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
) {
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());
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_
;
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
);
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 base::Bind(&BluetoothGattChromeOSTest::SuccessCallback
,
221 base::Unretained(this)));
222 EXPECT_EQ(2, success_callback_count_
);
223 EXPECT_EQ(0, error_callback_count_
);
224 EXPECT_TRUE(device
->IsConnected());
225 EXPECT_FALSE(gatt_conn_
->IsConnected());
227 device
->CreateGattConnection(
228 base::Bind(&BluetoothGattChromeOSTest::GattConnectionCallback
,
229 base::Unretained(this)),
230 base::Bind(&BluetoothGattChromeOSTest::ConnectErrorCallback
,
231 base::Unretained(this)));
233 EXPECT_EQ(3, success_callback_count_
);
234 EXPECT_EQ(0, error_callback_count_
);
235 EXPECT_TRUE(device
->IsConnected());
236 ASSERT_TRUE(gatt_conn_
.get());
237 EXPECT_TRUE(gatt_conn_
->IsConnected());
240 base::Bind(&BluetoothGattChromeOSTest::SuccessCallback
,
241 base::Unretained(this)),
242 base::Bind(&BluetoothGattChromeOSTest::ErrorCallback
,
243 base::Unretained(this)));
245 EXPECT_EQ(4, success_callback_count_
);
246 EXPECT_EQ(0, error_callback_count_
);
247 ASSERT_TRUE(gatt_conn_
.get());
248 EXPECT_FALSE(gatt_conn_
->IsConnected());
250 device
->CreateGattConnection(
251 base::Bind(&BluetoothGattChromeOSTest::GattConnectionCallback
,
252 base::Unretained(this)),
253 base::Bind(&BluetoothGattChromeOSTest::ConnectErrorCallback
,
254 base::Unretained(this)));
256 EXPECT_EQ(5, success_callback_count_
);
257 EXPECT_EQ(0, error_callback_count_
);
258 EXPECT_TRUE(device
->IsConnected());
259 EXPECT_TRUE(gatt_conn_
->IsConnected());
261 fake_bluetooth_device_client_
->RemoveDevice(
262 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath
),
263 dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath
));
264 ASSERT_TRUE(gatt_conn_
.get());
265 EXPECT_FALSE(gatt_conn_
->IsConnected());
268 TEST_F(BluetoothGattChromeOSTest
, GattServiceAddedAndRemoved
) {
269 // Create a fake LE device. We store the device pointer here because this is a
270 // test. It's unsafe to do this in production as the device might get deleted.
271 fake_bluetooth_device_client_
->CreateDevice(
272 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath
),
273 dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath
));
274 BluetoothDevice
* device
= adapter_
->GetDevice(
275 FakeBluetoothDeviceClient::kLowEnergyAddress
);
278 TestBluetoothAdapterObserver
observer(adapter_
);
280 EXPECT_EQ(0, observer
.gatt_service_added_count());
281 EXPECT_EQ(0, observer
.gatt_service_removed_count());
282 EXPECT_TRUE(observer
.last_gatt_service_id().empty());
283 EXPECT_FALSE(observer
.last_gatt_service_uuid().IsValid());
284 EXPECT_TRUE(device
->GetGattServices().empty());
286 // Expose the fake Heart Rate Service.
287 fake_bluetooth_gatt_service_client_
->ExposeHeartRateService(
288 dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath
));
289 EXPECT_EQ(1, observer
.gatt_service_added_count());
290 EXPECT_EQ(0, observer
.gatt_service_removed_count());
291 EXPECT_FALSE(observer
.last_gatt_service_id().empty());
292 EXPECT_EQ(1U, device
->GetGattServices().size());
294 BluetoothUUID(FakeBluetoothGattServiceClient::kHeartRateServiceUUID
),
295 observer
.last_gatt_service_uuid());
297 BluetoothGattService
* service
=
298 device
->GetGattService(observer
.last_gatt_service_id());
299 EXPECT_FALSE(service
->IsLocal());
300 EXPECT_TRUE(service
->IsPrimary());
301 EXPECT_EQ(service
, device
->GetGattServices()[0]);
302 EXPECT_EQ(service
, device
->GetGattService(service
->GetIdentifier()));
304 EXPECT_EQ(observer
.last_gatt_service_uuid(), service
->GetUUID());
307 observer
.last_gatt_service_uuid() = BluetoothUUID();
308 observer
.last_gatt_service_id().clear();
309 fake_bluetooth_gatt_service_client_
->HideHeartRateService();
311 EXPECT_EQ(1, observer
.gatt_service_added_count());
312 EXPECT_EQ(1, observer
.gatt_service_removed_count());
313 EXPECT_FALSE(observer
.last_gatt_service_id().empty());
314 EXPECT_TRUE(device
->GetGattServices().empty());
316 BluetoothUUID(FakeBluetoothGattServiceClient::kHeartRateServiceUUID
),
317 observer
.last_gatt_service_uuid());
319 EXPECT_EQ(NULL
, device
->GetGattService(observer
.last_gatt_service_id()));
321 // Expose the service again.
322 observer
.last_gatt_service_uuid() = BluetoothUUID();
323 observer
.last_gatt_service_id().clear();
324 fake_bluetooth_gatt_service_client_
->ExposeHeartRateService(
325 dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath
));
326 EXPECT_EQ(2, observer
.gatt_service_added_count());
327 EXPECT_EQ(1, observer
.gatt_service_removed_count());
328 EXPECT_FALSE(observer
.last_gatt_service_id().empty());
329 EXPECT_EQ(1U, device
->GetGattServices().size());
331 BluetoothUUID(FakeBluetoothGattServiceClient::kHeartRateServiceUUID
),
332 observer
.last_gatt_service_uuid());
334 // The object |service| points to should have been deallocated. |device|
335 // should contain a brand new instance.
336 service
= device
->GetGattService(observer
.last_gatt_service_id());
337 EXPECT_EQ(service
, device
->GetGattServices()[0]);
338 EXPECT_FALSE(service
->IsLocal());
339 EXPECT_TRUE(service
->IsPrimary());
341 EXPECT_EQ(observer
.last_gatt_service_uuid(), service
->GetUUID());
343 // Remove the device. The observer should be notified of the removed service.
344 // |device| becomes invalid after this.
345 observer
.last_gatt_service_uuid() = BluetoothUUID();
346 observer
.last_gatt_service_id().clear();
347 fake_bluetooth_device_client_
->RemoveDevice(
348 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath
),
349 dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath
));
351 EXPECT_EQ(2, observer
.gatt_service_added_count());
352 EXPECT_EQ(2, observer
.gatt_service_removed_count());
353 EXPECT_FALSE(observer
.last_gatt_service_id().empty());
355 BluetoothUUID(FakeBluetoothGattServiceClient::kHeartRateServiceUUID
),
356 observer
.last_gatt_service_uuid());
358 NULL
, adapter_
->GetDevice(FakeBluetoothDeviceClient::kLowEnergyAddress
));
361 TEST_F(BluetoothGattChromeOSTest
, GattCharacteristicAddedAndRemoved
) {
362 fake_bluetooth_device_client_
->CreateDevice(
363 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath
),
364 dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath
));
365 BluetoothDevice
* device
= adapter_
->GetDevice(
366 FakeBluetoothDeviceClient::kLowEnergyAddress
);
369 TestBluetoothAdapterObserver
observer(adapter_
);
371 // Expose the fake Heart Rate service. This will asynchronously expose
373 fake_bluetooth_gatt_service_client_
->ExposeHeartRateService(
374 dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath
));
375 ASSERT_EQ(1, observer
.gatt_service_added_count());
377 BluetoothGattService
* service
=
378 device
->GetGattService(observer
.last_gatt_service_id());
380 EXPECT_EQ(0, observer
.gatt_service_changed_count());
381 EXPECT_EQ(0, observer
.gatt_discovery_complete_count());
382 EXPECT_EQ(0, observer
.gatt_characteristic_added_count());
383 EXPECT_EQ(0, observer
.gatt_characteristic_removed_count());
384 EXPECT_EQ(0, observer
.gatt_characteristic_value_changed_count());
385 EXPECT_TRUE(service
->GetCharacteristics().empty());
387 // Run the message loop so that the characteristics appear.
388 base::MessageLoop::current()->Run();
390 // 3 characteristics should appear. Only 1 of the characteristics sends
391 // value changed signals. Service changed should be fired once for
393 EXPECT_EQ(0, observer
.gatt_service_changed_count());
394 EXPECT_EQ(1, observer
.gatt_discovery_complete_count());
395 EXPECT_EQ(3, observer
.gatt_characteristic_added_count());
396 EXPECT_EQ(0, observer
.gatt_characteristic_removed_count());
397 EXPECT_EQ(0, observer
.gatt_characteristic_value_changed_count());
398 EXPECT_EQ(3U, service
->GetCharacteristics().size());
400 // Hide the characteristics. 3 removed signals should be received.
401 fake_bluetooth_gatt_characteristic_client_
->HideHeartRateCharacteristics();
402 EXPECT_EQ(0, observer
.gatt_service_changed_count());
403 EXPECT_EQ(3, observer
.gatt_characteristic_added_count());
404 EXPECT_EQ(3, observer
.gatt_characteristic_removed_count());
405 EXPECT_EQ(0, observer
.gatt_characteristic_value_changed_count());
406 EXPECT_TRUE(service
->GetCharacteristics().empty());
408 // Re-expose the heart rate characteristics. We shouldn't get another
409 // GattDiscoveryCompleteForService call, since the service thinks that
410 // discovery is done. On the bluetoothd side, characteristics will be removed
411 // only if the service will also be subsequently removed.
412 fake_bluetooth_gatt_characteristic_client_
->ExposeHeartRateCharacteristics(
413 fake_bluetooth_gatt_service_client_
->GetHeartRateServicePath());
414 EXPECT_EQ(0, observer
.gatt_service_changed_count());
415 EXPECT_EQ(1, observer
.gatt_discovery_complete_count());
416 EXPECT_EQ(6, observer
.gatt_characteristic_added_count());
417 EXPECT_EQ(3, observer
.gatt_characteristic_removed_count());
418 EXPECT_EQ(0, observer
.gatt_characteristic_value_changed_count());
419 EXPECT_EQ(3U, service
->GetCharacteristics().size());
421 // Hide the service. All characteristics should disappear.
422 fake_bluetooth_gatt_service_client_
->HideHeartRateService();
423 EXPECT_EQ(0, observer
.gatt_service_changed_count());
424 EXPECT_EQ(6, observer
.gatt_characteristic_added_count());
425 EXPECT_EQ(6, observer
.gatt_characteristic_removed_count());
426 EXPECT_EQ(0, observer
.gatt_characteristic_value_changed_count());
429 TEST_F(BluetoothGattChromeOSTest
, GattDescriptorAddedAndRemoved
) {
430 fake_bluetooth_device_client_
->CreateDevice(
431 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath
),
432 dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath
));
433 BluetoothDevice
* device
= adapter_
->GetDevice(
434 FakeBluetoothDeviceClient::kLowEnergyAddress
);
437 TestBluetoothAdapterObserver
observer(adapter_
);
439 // Expose the fake Heart Rate service. This will asynchronously expose
441 fake_bluetooth_gatt_service_client_
->ExposeHeartRateService(
442 dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath
));
443 ASSERT_EQ(1, observer
.gatt_service_added_count());
445 BluetoothGattService
* service
=
446 device
->GetGattService(observer
.last_gatt_service_id());
448 EXPECT_EQ(0, observer
.gatt_service_changed_count());
449 EXPECT_EQ(0, observer
.gatt_descriptor_added_count());
450 EXPECT_EQ(0, observer
.gatt_descriptor_removed_count());
451 EXPECT_EQ(0, observer
.gatt_descriptor_value_changed_count());
453 EXPECT_TRUE(service
->GetCharacteristics().empty());
455 // Run the message loop so that the characteristics appear.
456 base::MessageLoop::current()->Run();
457 EXPECT_EQ(0, observer
.gatt_service_changed_count());
459 // Only the Heart Rate Measurement characteristic has a descriptor.
460 EXPECT_EQ(1, observer
.gatt_descriptor_added_count());
461 EXPECT_EQ(0, observer
.gatt_descriptor_removed_count());
462 EXPECT_EQ(0, observer
.gatt_descriptor_value_changed_count());
464 BluetoothGattCharacteristic
* characteristic
= service
->GetCharacteristic(
465 fake_bluetooth_gatt_characteristic_client_
->
466 GetBodySensorLocationPath().value());
467 ASSERT_TRUE(characteristic
);
468 EXPECT_TRUE(characteristic
->GetDescriptors().empty());
470 characteristic
= service
->GetCharacteristic(
471 fake_bluetooth_gatt_characteristic_client_
->
472 GetHeartRateControlPointPath().value());
473 ASSERT_TRUE(characteristic
);
474 EXPECT_TRUE(characteristic
->GetDescriptors().empty());
476 characteristic
= service
->GetCharacteristic(
477 fake_bluetooth_gatt_characteristic_client_
->
478 GetHeartRateMeasurementPath().value());
479 ASSERT_TRUE(characteristic
);
480 EXPECT_EQ(1U, characteristic
->GetDescriptors().size());
482 BluetoothGattDescriptor
* descriptor
= characteristic
->GetDescriptors()[0];
483 EXPECT_FALSE(descriptor
->IsLocal());
484 EXPECT_EQ(BluetoothGattDescriptor::ClientCharacteristicConfigurationUuid(),
485 descriptor
->GetUUID());
486 EXPECT_EQ(descriptor
->GetUUID(), observer
.last_gatt_descriptor_uuid());
487 EXPECT_EQ(descriptor
->GetIdentifier(), observer
.last_gatt_descriptor_id());
489 // Hide the descriptor.
490 fake_bluetooth_gatt_descriptor_client_
->HideDescriptor(
491 dbus::ObjectPath(descriptor
->GetIdentifier()));
492 EXPECT_TRUE(characteristic
->GetDescriptors().empty());
493 EXPECT_EQ(0, observer
.gatt_service_changed_count());
494 EXPECT_EQ(1, observer
.gatt_descriptor_added_count());
495 EXPECT_EQ(1, observer
.gatt_descriptor_removed_count());
496 EXPECT_EQ(0, observer
.gatt_descriptor_value_changed_count());
498 // Expose the descriptor again.
499 observer
.last_gatt_descriptor_id().clear();
500 observer
.last_gatt_descriptor_uuid() = BluetoothUUID();
501 fake_bluetooth_gatt_descriptor_client_
->ExposeDescriptor(
502 dbus::ObjectPath(characteristic
->GetIdentifier()),
503 FakeBluetoothGattDescriptorClient::
504 kClientCharacteristicConfigurationUUID
);
505 EXPECT_EQ(0, observer
.gatt_service_changed_count());
506 EXPECT_EQ(1U, characteristic
->GetDescriptors().size());
507 EXPECT_EQ(2, observer
.gatt_descriptor_added_count());
508 EXPECT_EQ(1, observer
.gatt_descriptor_removed_count());
509 EXPECT_EQ(0, observer
.gatt_descriptor_value_changed_count());
511 descriptor
= characteristic
->GetDescriptors()[0];
512 EXPECT_FALSE(descriptor
->IsLocal());
513 EXPECT_EQ(BluetoothGattDescriptor::ClientCharacteristicConfigurationUuid(),
514 descriptor
->GetUUID());
515 EXPECT_EQ(descriptor
->GetUUID(), observer
.last_gatt_descriptor_uuid());
516 EXPECT_EQ(descriptor
->GetIdentifier(), observer
.last_gatt_descriptor_id());
519 TEST_F(BluetoothGattChromeOSTest
, AdapterAddedAfterGattService
) {
520 // This unit test tests that all remote GATT objects are created for D-Bus
521 // objects that were already exposed.
523 ASSERT_FALSE(device::BluetoothAdapterFactory::HasSharedInstanceForTesting());
525 // Create the fake D-Bus objects.
526 fake_bluetooth_device_client_
->CreateDevice(
527 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath
),
528 dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath
));
529 fake_bluetooth_gatt_service_client_
->ExposeHeartRateService(
530 dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath
));
531 while (!fake_bluetooth_gatt_characteristic_client_
->IsHeartRateVisible())
532 base::RunLoop().RunUntilIdle();
533 ASSERT_TRUE(fake_bluetooth_gatt_service_client_
->IsHeartRateVisible());
534 ASSERT_TRUE(fake_bluetooth_gatt_characteristic_client_
->IsHeartRateVisible());
536 // Create the adapter. This should create all the GATT objects.
538 BluetoothDevice
* device
= adapter_
->GetDevice(
539 FakeBluetoothDeviceClient::kLowEnergyAddress
);
541 EXPECT_EQ(1U, device
->GetGattServices().size());
543 BluetoothGattService
* service
= device
->GetGattServices()[0];
544 ASSERT_TRUE(service
);
545 EXPECT_FALSE(service
->IsLocal());
546 EXPECT_TRUE(service
->IsPrimary());
548 BluetoothUUID(FakeBluetoothGattServiceClient::kHeartRateServiceUUID
),
550 EXPECT_EQ(service
, device
->GetGattServices()[0]);
551 EXPECT_EQ(service
, device
->GetGattService(service
->GetIdentifier()));
552 EXPECT_FALSE(service
->IsLocal());
553 EXPECT_EQ(3U, service
->GetCharacteristics().size());
555 BluetoothGattCharacteristic
* characteristic
= service
->GetCharacteristic(
556 fake_bluetooth_gatt_characteristic_client_
->
557 GetBodySensorLocationPath().value());
558 ASSERT_TRUE(characteristic
);
560 BluetoothUUID(FakeBluetoothGattCharacteristicClient::
561 kBodySensorLocationUUID
),
562 characteristic
->GetUUID());
563 EXPECT_FALSE(characteristic
->IsLocal());
564 EXPECT_TRUE(characteristic
->GetDescriptors().empty());
566 characteristic
= service
->GetCharacteristic(
567 fake_bluetooth_gatt_characteristic_client_
->
568 GetHeartRateControlPointPath().value());
569 ASSERT_TRUE(characteristic
);
571 BluetoothUUID(FakeBluetoothGattCharacteristicClient::
572 kHeartRateControlPointUUID
),
573 characteristic
->GetUUID());
574 EXPECT_FALSE(characteristic
->IsLocal());
575 EXPECT_TRUE(characteristic
->GetDescriptors().empty());
577 characteristic
= service
->GetCharacteristic(
578 fake_bluetooth_gatt_characteristic_client_
->
579 GetHeartRateMeasurementPath().value());
580 ASSERT_TRUE(characteristic
);
582 BluetoothUUID(FakeBluetoothGattCharacteristicClient::
583 kHeartRateMeasurementUUID
),
584 characteristic
->GetUUID());
585 EXPECT_FALSE(characteristic
->IsLocal());
586 EXPECT_EQ(1U, characteristic
->GetDescriptors().size());
588 BluetoothGattDescriptor
* descriptor
= characteristic
->GetDescriptors()[0];
589 ASSERT_TRUE(descriptor
);
590 EXPECT_EQ(BluetoothGattDescriptor::ClientCharacteristicConfigurationUuid(),
591 descriptor
->GetUUID());
592 EXPECT_FALSE(descriptor
->IsLocal());
595 TEST_F(BluetoothGattChromeOSTest
, GattCharacteristicValue
) {
596 fake_bluetooth_device_client_
->CreateDevice(
597 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath
),
598 dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath
));
599 BluetoothDevice
* device
= adapter_
->GetDevice(
600 FakeBluetoothDeviceClient::kLowEnergyAddress
);
603 TestBluetoothAdapterObserver
observer(adapter_
);
605 // Expose the fake Heart Rate service. This will asynchronously expose
607 fake_bluetooth_gatt_service_client_
->ExposeHeartRateService(
608 dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath
));
609 ASSERT_EQ(1, observer
.gatt_service_added_count());
611 BluetoothGattService
* service
=
612 device
->GetGattService(observer
.last_gatt_service_id());
614 EXPECT_EQ(0, observer
.gatt_characteristic_value_changed_count());
616 // Run the message loop so that the characteristics appear.
617 base::MessageLoop::current()->Run();
619 // Issue write request to non-writable characteristics.
622 std::vector
<uint8
> write_value
;
623 write_value
.push_back(0x01);
624 BluetoothGattCharacteristic
* characteristic
=
625 service
->GetCharacteristic(fake_bluetooth_gatt_characteristic_client_
->
626 GetHeartRateMeasurementPath().value());
627 ASSERT_TRUE(characteristic
);
628 EXPECT_FALSE(characteristic
->IsNotifying());
629 EXPECT_EQ(fake_bluetooth_gatt_characteristic_client_
->
630 GetHeartRateMeasurementPath().value(),
631 characteristic
->GetIdentifier());
632 EXPECT_EQ(kHeartRateMeasurementUUID
, characteristic
->GetUUID());
633 characteristic
->WriteRemoteCharacteristic(
635 base::Bind(&BluetoothGattChromeOSTest::SuccessCallback
,
636 base::Unretained(this)),
637 base::Bind(&BluetoothGattChromeOSTest::ServiceErrorCallback
,
638 base::Unretained(this)));
639 EXPECT_TRUE(observer
.last_gatt_characteristic_id().empty());
640 EXPECT_FALSE(observer
.last_gatt_characteristic_uuid().IsValid());
641 EXPECT_EQ(0, success_callback_count_
);
642 EXPECT_EQ(1, error_callback_count_
);
643 EXPECT_EQ(BluetoothGattService::GATT_ERROR_NOT_SUPPORTED
,
644 last_service_error_
);
645 EXPECT_EQ(0, observer
.gatt_characteristic_value_changed_count());
647 characteristic
= service
->GetCharacteristic(
648 fake_bluetooth_gatt_characteristic_client_
->
649 GetBodySensorLocationPath().value());
650 ASSERT_TRUE(characteristic
);
651 EXPECT_EQ(fake_bluetooth_gatt_characteristic_client_
->
652 GetBodySensorLocationPath().value(),
653 characteristic
->GetIdentifier());
654 EXPECT_EQ(kBodySensorLocationUUID
, characteristic
->GetUUID());
655 characteristic
->WriteRemoteCharacteristic(
657 base::Bind(&BluetoothGattChromeOSTest::SuccessCallback
,
658 base::Unretained(this)),
659 base::Bind(&BluetoothGattChromeOSTest::ServiceErrorCallback
,
660 base::Unretained(this)));
661 EXPECT_TRUE(observer
.last_gatt_characteristic_id().empty());
662 EXPECT_FALSE(observer
.last_gatt_characteristic_uuid().IsValid());
663 EXPECT_EQ(0, success_callback_count_
);
664 EXPECT_EQ(2, error_callback_count_
);
665 EXPECT_EQ(BluetoothGattService::GATT_ERROR_NOT_PERMITTED
,
666 last_service_error_
);
667 EXPECT_EQ(0, observer
.gatt_characteristic_value_changed_count());
669 // Issue write request to writable characteristic. The "Body Sensor Location"
670 // characteristic does not send notifications and WriteValue does not result
671 // in a CharacteristicValueChanged event, thus no such event should be
673 characteristic
= service
->GetCharacteristic(
674 fake_bluetooth_gatt_characteristic_client_
->
675 GetHeartRateControlPointPath().value());
676 ASSERT_TRUE(characteristic
);
677 EXPECT_EQ(fake_bluetooth_gatt_characteristic_client_
->
678 GetHeartRateControlPointPath().value(),
679 characteristic
->GetIdentifier());
680 EXPECT_EQ(kHeartRateControlPointUUID
, characteristic
->GetUUID());
681 characteristic
->WriteRemoteCharacteristic(
683 base::Bind(&BluetoothGattChromeOSTest::SuccessCallback
,
684 base::Unretained(this)),
685 base::Bind(&BluetoothGattChromeOSTest::ServiceErrorCallback
,
686 base::Unretained(this)));
687 EXPECT_TRUE(observer
.last_gatt_characteristic_id().empty());
688 EXPECT_FALSE(observer
.last_gatt_characteristic_uuid().IsValid());
689 EXPECT_EQ(1, success_callback_count_
);
690 EXPECT_EQ(2, error_callback_count_
);
691 EXPECT_EQ(0, observer
.gatt_characteristic_value_changed_count());
693 // Issue some invalid write requests to the characteristic.
694 // The value should still not change.
696 std::vector
<uint8
> invalid_write_length
;
697 invalid_write_length
.push_back(0x01);
698 invalid_write_length
.push_back(0x00);
699 characteristic
->WriteRemoteCharacteristic(
700 invalid_write_length
,
701 base::Bind(&BluetoothGattChromeOSTest::SuccessCallback
,
702 base::Unretained(this)),
703 base::Bind(&BluetoothGattChromeOSTest::ServiceErrorCallback
,
704 base::Unretained(this)));
705 EXPECT_EQ(1, success_callback_count_
);
706 EXPECT_EQ(3, error_callback_count_
);
707 EXPECT_EQ(BluetoothGattService::GATT_ERROR_INVALID_LENGTH
,
708 last_service_error_
);
709 EXPECT_EQ(0, observer
.gatt_characteristic_value_changed_count());
711 std::vector
<uint8
> invalid_write_value
;
712 invalid_write_value
.push_back(0x02);
713 characteristic
->WriteRemoteCharacteristic(
715 base::Bind(&BluetoothGattChromeOSTest::SuccessCallback
,
716 base::Unretained(this)),
717 base::Bind(&BluetoothGattChromeOSTest::ServiceErrorCallback
,
718 base::Unretained(this)));
719 EXPECT_EQ(1, success_callback_count_
);
720 EXPECT_EQ(4, error_callback_count_
);
721 EXPECT_EQ(BluetoothGattService::GATT_ERROR_FAILED
, last_service_error_
);
722 EXPECT_EQ(0, observer
.gatt_characteristic_value_changed_count());
724 // Issue a read request. A successful read results in a
725 // CharacteristicValueChanged notification.
726 characteristic
= service
->GetCharacteristic(
727 fake_bluetooth_gatt_characteristic_client_
->
728 GetBodySensorLocationPath().value());
729 ASSERT_TRUE(characteristic
);
730 EXPECT_EQ(fake_bluetooth_gatt_characteristic_client_
->
731 GetBodySensorLocationPath().value(),
732 characteristic
->GetIdentifier());
733 EXPECT_EQ(kBodySensorLocationUUID
, characteristic
->GetUUID());
734 characteristic
->ReadRemoteCharacteristic(
735 base::Bind(&BluetoothGattChromeOSTest::ValueCallback
,
736 base::Unretained(this)),
737 base::Bind(&BluetoothGattChromeOSTest::ServiceErrorCallback
,
738 base::Unretained(this)));
739 EXPECT_EQ(2, success_callback_count_
);
740 EXPECT_EQ(4, error_callback_count_
);
741 EXPECT_EQ(1, observer
.gatt_characteristic_value_changed_count());
742 EXPECT_TRUE(ValuesEqual(characteristic
->GetValue(), last_read_value_
));
744 // Test long-running actions.
745 fake_bluetooth_gatt_characteristic_client_
->SetExtraProcessing(1);
746 characteristic
= service
->GetCharacteristic(
747 fake_bluetooth_gatt_characteristic_client_
->GetBodySensorLocationPath()
749 ASSERT_TRUE(characteristic
);
751 fake_bluetooth_gatt_characteristic_client_
->GetBodySensorLocationPath()
753 characteristic
->GetIdentifier());
754 EXPECT_EQ(kBodySensorLocationUUID
, characteristic
->GetUUID());
755 characteristic
->ReadRemoteCharacteristic(
756 base::Bind(&BluetoothGattChromeOSTest::ValueCallback
,
757 base::Unretained(this)),
758 base::Bind(&BluetoothGattChromeOSTest::ServiceErrorCallback
,
759 base::Unretained(this)));
761 // Callback counts shouldn't change, this one will be delayed until after
763 EXPECT_EQ(2, success_callback_count_
);
764 EXPECT_EQ(4, error_callback_count_
);
765 EXPECT_EQ(1, observer
.gatt_characteristic_value_changed_count());
767 // Next read should error because IN_PROGRESS
768 characteristic
->ReadRemoteCharacteristic(
769 base::Bind(&BluetoothGattChromeOSTest::ValueCallback
,
770 base::Unretained(this)),
771 base::Bind(&BluetoothGattChromeOSTest::ServiceErrorCallback
,
772 base::Unretained(this)));
773 EXPECT_EQ(5, error_callback_count_
);
774 EXPECT_EQ(BluetoothGattService::GATT_ERROR_IN_PROGRESS
, last_service_error_
);
776 // But previous call finished.
777 EXPECT_EQ(3, success_callback_count_
);
778 EXPECT_EQ(2, observer
.gatt_characteristic_value_changed_count());
779 EXPECT_TRUE(ValuesEqual(characteristic
->GetValue(), last_read_value_
));
780 fake_bluetooth_gatt_characteristic_client_
->SetExtraProcessing(0);
782 // Test unauthorized actions.
783 fake_bluetooth_gatt_characteristic_client_
->SetAuthorized(false);
784 characteristic
->ReadRemoteCharacteristic(
785 base::Bind(&BluetoothGattChromeOSTest::ValueCallback
,
786 base::Unretained(this)),
787 base::Bind(&BluetoothGattChromeOSTest::ServiceErrorCallback
,
788 base::Unretained(this)));
789 EXPECT_EQ(3, success_callback_count_
);
790 EXPECT_EQ(6, error_callback_count_
);
791 EXPECT_EQ(BluetoothGattService::GATT_ERROR_NOT_AUTHORIZED
,
792 last_service_error_
);
793 EXPECT_EQ(2, observer
.gatt_characteristic_value_changed_count());
794 fake_bluetooth_gatt_characteristic_client_
->SetAuthorized(true);
796 // Test unauthenticated / needs login.
797 fake_bluetooth_gatt_characteristic_client_
->SetAuthenticated(false);
798 characteristic
->ReadRemoteCharacteristic(
799 base::Bind(&BluetoothGattChromeOSTest::ValueCallback
,
800 base::Unretained(this)),
801 base::Bind(&BluetoothGattChromeOSTest::ServiceErrorCallback
,
802 base::Unretained(this)));
803 EXPECT_EQ(3, success_callback_count_
);
804 EXPECT_EQ(7, error_callback_count_
);
805 EXPECT_EQ(BluetoothGattService::GATT_ERROR_NOT_PAIRED
, last_service_error_
);
806 EXPECT_EQ(2, observer
.gatt_characteristic_value_changed_count());
807 fake_bluetooth_gatt_characteristic_client_
->SetAuthenticated(true);
810 TEST_F(BluetoothGattChromeOSTest
, GattCharacteristicProperties
) {
811 fake_bluetooth_device_client_
->CreateDevice(
812 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath
),
813 dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath
));
814 BluetoothDevice
* device
= adapter_
->GetDevice(
815 FakeBluetoothDeviceClient::kLowEnergyAddress
);
818 TestBluetoothAdapterObserver
observer(adapter_
);
820 // Expose the fake Heart Rate service. This will asynchronously expose
822 fake_bluetooth_gatt_service_client_
->ExposeHeartRateService(
823 dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath
));
825 BluetoothGattService
* service
=
826 device
->GetGattService(observer
.last_gatt_service_id());
828 EXPECT_TRUE(service
->GetCharacteristics().empty());
830 // Run the message loop so that the characteristics appear.
831 base::MessageLoop::current()->Run();
833 BluetoothGattCharacteristic
*characteristic
= service
->GetCharacteristic(
834 fake_bluetooth_gatt_characteristic_client_
->
835 GetBodySensorLocationPath().value());
836 EXPECT_EQ(BluetoothGattCharacteristic::PROPERTY_READ
,
837 characteristic
->GetProperties());
839 characteristic
= service
->GetCharacteristic(
840 fake_bluetooth_gatt_characteristic_client_
->
841 GetHeartRateControlPointPath().value());
842 EXPECT_EQ(BluetoothGattCharacteristic::PROPERTY_WRITE
,
843 characteristic
->GetProperties());
845 characteristic
= service
->GetCharacteristic(
846 fake_bluetooth_gatt_characteristic_client_
->
847 GetHeartRateMeasurementPath().value());
848 EXPECT_EQ(BluetoothGattCharacteristic::PROPERTY_NOTIFY
,
849 characteristic
->GetProperties());
852 TEST_F(BluetoothGattChromeOSTest
, GattDescriptorValue
) {
853 fake_bluetooth_device_client_
->CreateDevice(
854 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath
),
855 dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath
));
856 BluetoothDevice
* device
= adapter_
->GetDevice(
857 FakeBluetoothDeviceClient::kLowEnergyAddress
);
860 TestBluetoothAdapterObserver
observer(adapter_
);
862 // Expose the fake Heart Rate service. This will asynchronously expose
864 fake_bluetooth_gatt_service_client_
->ExposeHeartRateService(
865 dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath
));
866 ASSERT_EQ(1, observer
.gatt_service_added_count());
868 BluetoothGattService
* service
=
869 device
->GetGattService(observer
.last_gatt_service_id());
871 EXPECT_EQ(0, observer
.gatt_service_changed_count());
872 EXPECT_EQ(0, observer
.gatt_discovery_complete_count());
873 EXPECT_EQ(0, observer
.gatt_descriptor_value_changed_count());
874 EXPECT_TRUE(service
->GetCharacteristics().empty());
876 // Run the message loop so that the characteristics appear.
877 base::MessageLoop::current()->Run();
878 EXPECT_EQ(0, observer
.gatt_service_changed_count());
879 EXPECT_EQ(1, observer
.gatt_discovery_complete_count());
881 // Only the Heart Rate Measurement characteristic has a descriptor.
882 BluetoothGattCharacteristic
* characteristic
= service
->GetCharacteristic(
883 fake_bluetooth_gatt_characteristic_client_
->
884 GetHeartRateMeasurementPath().value());
885 ASSERT_TRUE(characteristic
);
886 EXPECT_EQ(1U, characteristic
->GetDescriptors().size());
887 EXPECT_FALSE(characteristic
->IsNotifying());
889 BluetoothGattDescriptor
* descriptor
= characteristic
->GetDescriptors()[0];
890 EXPECT_FALSE(descriptor
->IsLocal());
891 EXPECT_EQ(BluetoothGattDescriptor::ClientCharacteristicConfigurationUuid(),
892 descriptor
->GetUUID());
894 std::vector
<uint8_t> desc_value
= {0x00, 0x00};
896 /* The cached value will be empty until the first read request */
897 EXPECT_FALSE(ValuesEqual(desc_value
, descriptor
->GetValue()));
898 EXPECT_TRUE(descriptor
->GetValue().empty());
900 EXPECT_EQ(0, success_callback_count_
);
901 EXPECT_EQ(0, error_callback_count_
);
902 EXPECT_TRUE(last_read_value_
.empty());
904 // Read value. GattDescriptorValueChanged event will be sent after a
906 descriptor
->ReadRemoteDescriptor(
907 base::Bind(&BluetoothGattChromeOSTest::ValueCallback
,
908 base::Unretained(this)),
909 base::Bind(&BluetoothGattChromeOSTest::ServiceErrorCallback
,
910 base::Unretained(this)));
911 EXPECT_EQ(1, success_callback_count_
);
912 EXPECT_EQ(0, error_callback_count_
);
913 EXPECT_TRUE(ValuesEqual(last_read_value_
, descriptor
->GetValue()));
914 EXPECT_TRUE(ValuesEqual(desc_value
, descriptor
->GetValue()));
915 EXPECT_EQ(0, observer
.gatt_service_changed_count());
916 EXPECT_EQ(1, observer
.gatt_descriptor_value_changed_count());
918 // Write value. Writes to this descriptor will fail.
919 desc_value
[0] = 0x03;
920 descriptor
->WriteRemoteDescriptor(
922 base::Bind(&BluetoothGattChromeOSTest::SuccessCallback
,
923 base::Unretained(this)),
924 base::Bind(&BluetoothGattChromeOSTest::ServiceErrorCallback
,
925 base::Unretained(this)));
926 EXPECT_EQ(1, success_callback_count_
);
927 EXPECT_EQ(1, error_callback_count_
);
928 EXPECT_EQ(BluetoothGattService::GATT_ERROR_NOT_PERMITTED
,
929 last_service_error_
);
930 EXPECT_TRUE(ValuesEqual(last_read_value_
, descriptor
->GetValue()));
931 EXPECT_FALSE(ValuesEqual(desc_value
, descriptor
->GetValue()));
932 EXPECT_EQ(0, observer
.gatt_service_changed_count());
933 EXPECT_EQ(1, observer
.gatt_descriptor_value_changed_count());
935 // Read value. The value should remain unchanged.
936 descriptor
->ReadRemoteDescriptor(
937 base::Bind(&BluetoothGattChromeOSTest::ValueCallback
,
938 base::Unretained(this)),
939 base::Bind(&BluetoothGattChromeOSTest::ServiceErrorCallback
,
940 base::Unretained(this)));
941 EXPECT_EQ(2, success_callback_count_
);
942 EXPECT_EQ(1, error_callback_count_
);
943 EXPECT_TRUE(ValuesEqual(last_read_value_
, descriptor
->GetValue()));
944 EXPECT_FALSE(ValuesEqual(desc_value
, descriptor
->GetValue()));
945 EXPECT_EQ(0, observer
.gatt_service_changed_count());
946 EXPECT_EQ(1, observer
.gatt_descriptor_value_changed_count());
948 // Start notifications on the descriptor's characteristic. The descriptor
949 // value should change.
950 characteristic
->StartNotifySession(
951 base::Bind(&BluetoothGattChromeOSTest::NotifySessionCallback
,
952 base::Unretained(this)),
953 base::Bind(&BluetoothGattChromeOSTest::ServiceErrorCallback
,
954 base::Unretained(this)));
955 base::MessageLoop::current()->Run();
956 EXPECT_EQ(3, success_callback_count_
);
957 EXPECT_EQ(1, error_callback_count_
);
958 EXPECT_EQ(1U, update_sessions_
.size());
959 EXPECT_TRUE(characteristic
->IsNotifying());
961 // Read the new descriptor value. We should receive a value updated event.
962 descriptor
->ReadRemoteDescriptor(
963 base::Bind(&BluetoothGattChromeOSTest::ValueCallback
,
964 base::Unretained(this)),
965 base::Bind(&BluetoothGattChromeOSTest::ServiceErrorCallback
,
966 base::Unretained(this)));
967 EXPECT_EQ(4, success_callback_count_
);
968 EXPECT_EQ(1, error_callback_count_
);
969 EXPECT_TRUE(ValuesEqual(last_read_value_
, descriptor
->GetValue()));
970 EXPECT_FALSE(ValuesEqual(desc_value
, descriptor
->GetValue()));
971 EXPECT_EQ(0, observer
.gatt_service_changed_count());
972 EXPECT_EQ(2, observer
.gatt_descriptor_value_changed_count());
975 TEST_F(BluetoothGattChromeOSTest
, NotifySessions
) {
976 fake_bluetooth_device_client_
->CreateDevice(
977 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath
),
978 dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath
));
979 BluetoothDevice
* device
=
980 adapter_
->GetDevice(FakeBluetoothDeviceClient::kLowEnergyAddress
);
983 TestBluetoothAdapterObserver
observer(adapter_
);
985 // Expose the fake Heart Rate service. This will asynchronously expose
987 fake_bluetooth_gatt_service_client_
->ExposeHeartRateService(
988 dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath
));
989 ASSERT_EQ(1, observer
.gatt_service_added_count());
991 BluetoothGattService
* service
=
992 device
->GetGattService(observer
.last_gatt_service_id());
994 EXPECT_EQ(0, observer
.gatt_characteristic_value_changed_count());
996 // Run the message loop so that the characteristics appear.
997 base::MessageLoop::current()->Run();
999 BluetoothGattCharacteristic
* characteristic
= service
->GetCharacteristic(
1000 fake_bluetooth_gatt_characteristic_client_
->GetHeartRateMeasurementPath()
1002 ASSERT_TRUE(characteristic
);
1003 EXPECT_FALSE(characteristic
->IsNotifying());
1004 EXPECT_TRUE(update_sessions_
.empty());
1006 // Request to start notifications.
1007 characteristic
->StartNotifySession(
1008 base::Bind(&BluetoothGattChromeOSTest::NotifySessionCallback
,
1009 base::Unretained(this)),
1010 base::Bind(&BluetoothGattChromeOSTest::ServiceErrorCallback
,
1011 base::Unretained(this)));
1013 // The operation still hasn't completed but we should have received the first
1015 EXPECT_EQ(0, success_callback_count_
);
1016 EXPECT_EQ(0, error_callback_count_
);
1017 EXPECT_EQ(1, observer
.gatt_characteristic_value_changed_count());
1018 EXPECT_TRUE(update_sessions_
.empty());
1020 // Send a two more requests, which should get queued.
1021 characteristic
->StartNotifySession(
1022 base::Bind(&BluetoothGattChromeOSTest::NotifySessionCallback
,
1023 base::Unretained(this)),
1024 base::Bind(&BluetoothGattChromeOSTest::ServiceErrorCallback
,
1025 base::Unretained(this)));
1026 characteristic
->StartNotifySession(
1027 base::Bind(&BluetoothGattChromeOSTest::NotifySessionCallback
,
1028 base::Unretained(this)),
1029 base::Bind(&BluetoothGattChromeOSTest::ServiceErrorCallback
,
1030 base::Unretained(this)));
1031 EXPECT_EQ(0, success_callback_count_
);
1032 EXPECT_EQ(0, error_callback_count_
);
1033 EXPECT_EQ(1, observer
.gatt_characteristic_value_changed_count());
1034 EXPECT_TRUE(update_sessions_
.empty());
1035 EXPECT_TRUE(characteristic
->IsNotifying());
1037 // Run the main loop. The initial call should complete. The queued call should
1038 // succeed immediately.
1039 base::MessageLoop::current()->Run();
1041 EXPECT_EQ(3, success_callback_count_
);
1042 EXPECT_EQ(0, error_callback_count_
);
1043 EXPECT_EQ(1, observer
.gatt_characteristic_value_changed_count());
1044 EXPECT_EQ(3U, update_sessions_
.size());
1046 // Notifications should be getting sent regularly now.
1047 base::MessageLoop::current()->Run();
1048 EXPECT_GT(observer
.gatt_characteristic_value_changed_count(), 1);
1050 // Stop one of the sessions. The session should become inactive but the
1051 // characteristic should still be notifying.
1052 BluetoothGattNotifySession
* session
= update_sessions_
[0];
1053 EXPECT_TRUE(session
->IsActive());
1054 session
->Stop(base::Bind(&BluetoothGattChromeOSTest::SuccessCallback
,
1055 base::Unretained(this)));
1056 EXPECT_EQ(4, success_callback_count_
);
1057 EXPECT_EQ(0, error_callback_count_
);
1058 EXPECT_FALSE(session
->IsActive());
1059 EXPECT_EQ(characteristic
->GetIdentifier(),
1060 session
->GetCharacteristicIdentifier());
1061 EXPECT_TRUE(characteristic
->IsNotifying());
1063 // Delete another session. Characteristic should still be notifying.
1064 update_sessions_
.pop_back();
1065 EXPECT_EQ(2U, update_sessions_
.size());
1066 EXPECT_TRUE(characteristic
->IsNotifying());
1067 EXPECT_FALSE(update_sessions_
[0]->IsActive());
1068 EXPECT_TRUE(update_sessions_
[1]->IsActive());
1070 // Clear the last session.
1071 update_sessions_
.clear();
1072 EXPECT_TRUE(update_sessions_
.empty());
1073 EXPECT_FALSE(characteristic
->IsNotifying());
1075 success_callback_count_
= 0;
1078 // Enable notifications again.
1079 characteristic
->StartNotifySession(
1080 base::Bind(&BluetoothGattChromeOSTest::NotifySessionCallback
,
1081 base::Unretained(this)),
1082 base::Bind(&BluetoothGattChromeOSTest::ServiceErrorCallback
,
1083 base::Unretained(this)));
1084 EXPECT_EQ(0, success_callback_count_
);
1085 EXPECT_EQ(0, error_callback_count_
);
1086 EXPECT_EQ(1, observer
.gatt_characteristic_value_changed_count());
1087 EXPECT_TRUE(update_sessions_
.empty());
1088 EXPECT_TRUE(characteristic
->IsNotifying());
1090 // Run the message loop. Notifications should begin.
1091 base::MessageLoop::current()->Run();
1093 EXPECT_EQ(1, success_callback_count_
);
1094 EXPECT_EQ(0, error_callback_count_
);
1095 EXPECT_EQ(1, observer
.gatt_characteristic_value_changed_count());
1096 EXPECT_EQ(1U, update_sessions_
.size());
1097 EXPECT_TRUE(update_sessions_
[0]->IsActive());
1098 EXPECT_TRUE(characteristic
->IsNotifying());
1100 // Check that notifications are happening.
1101 base::MessageLoop::current()->Run();
1102 EXPECT_GT(observer
.gatt_characteristic_value_changed_count(), 1);
1104 // Request another session. This should return immediately.
1105 characteristic
->StartNotifySession(
1106 base::Bind(&BluetoothGattChromeOSTest::NotifySessionCallback
,
1107 base::Unretained(this)),
1108 base::Bind(&BluetoothGattChromeOSTest::ServiceErrorCallback
,
1109 base::Unretained(this)));
1110 EXPECT_EQ(2, success_callback_count_
);
1111 EXPECT_EQ(0, error_callback_count_
);
1112 EXPECT_EQ(2U, update_sessions_
.size());
1113 EXPECT_TRUE(update_sessions_
[0]->IsActive());
1114 EXPECT_TRUE(update_sessions_
[1]->IsActive());
1115 EXPECT_TRUE(characteristic
->IsNotifying());
1117 // Hide the characteristic. The sessions should become inactive.
1118 fake_bluetooth_gatt_characteristic_client_
->HideHeartRateCharacteristics();
1119 EXPECT_EQ(2U, update_sessions_
.size());
1120 EXPECT_FALSE(update_sessions_
[0]->IsActive());
1121 EXPECT_FALSE(update_sessions_
[1]->IsActive());
1124 TEST_F(BluetoothGattChromeOSTest
, NotifySessionsMadeInactive
) {
1125 fake_bluetooth_device_client_
->CreateDevice(
1126 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath
),
1127 dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath
));
1128 BluetoothDevice
* device
=
1129 adapter_
->GetDevice(FakeBluetoothDeviceClient::kLowEnergyAddress
);
1130 ASSERT_TRUE(device
);
1132 TestBluetoothAdapterObserver
observer(adapter_
);
1134 // Expose the fake Heart Rate service. This will asynchronously expose
1136 fake_bluetooth_gatt_service_client_
->ExposeHeartRateService(
1137 dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath
));
1138 ASSERT_EQ(1, observer
.gatt_service_added_count());
1140 BluetoothGattService
* service
=
1141 device
->GetGattService(observer
.last_gatt_service_id());
1143 EXPECT_EQ(0, observer
.gatt_characteristic_value_changed_count());
1145 // Run the message loop so that the characteristics appear.
1146 base::MessageLoop::current()->Run();
1148 BluetoothGattCharacteristic
* characteristic
= service
->GetCharacteristic(
1149 fake_bluetooth_gatt_characteristic_client_
->GetHeartRateMeasurementPath()
1151 ASSERT_TRUE(characteristic
);
1152 EXPECT_FALSE(characteristic
->IsNotifying());
1153 EXPECT_TRUE(update_sessions_
.empty());
1155 // Send several requests to start notifications.
1156 characteristic
->StartNotifySession(
1157 base::Bind(&BluetoothGattChromeOSTest::NotifySessionCallback
,
1158 base::Unretained(this)),
1159 base::Bind(&BluetoothGattChromeOSTest::ServiceErrorCallback
,
1160 base::Unretained(this)));
1161 characteristic
->StartNotifySession(
1162 base::Bind(&BluetoothGattChromeOSTest::NotifySessionCallback
,
1163 base::Unretained(this)),
1164 base::Bind(&BluetoothGattChromeOSTest::ServiceErrorCallback
,
1165 base::Unretained(this)));
1166 characteristic
->StartNotifySession(
1167 base::Bind(&BluetoothGattChromeOSTest::NotifySessionCallback
,
1168 base::Unretained(this)),
1169 base::Bind(&BluetoothGattChromeOSTest::ServiceErrorCallback
,
1170 base::Unretained(this)));
1171 characteristic
->StartNotifySession(
1172 base::Bind(&BluetoothGattChromeOSTest::NotifySessionCallback
,
1173 base::Unretained(this)),
1174 base::Bind(&BluetoothGattChromeOSTest::ServiceErrorCallback
,
1175 base::Unretained(this)));
1177 // The operation still hasn't completed but we should have received the first
1179 EXPECT_EQ(0, success_callback_count_
);
1180 EXPECT_EQ(0, error_callback_count_
);
1181 EXPECT_EQ(1, observer
.gatt_characteristic_value_changed_count());
1182 EXPECT_TRUE(characteristic
->IsNotifying());
1183 EXPECT_TRUE(update_sessions_
.empty());
1185 // Run the main loop. The initial call should complete. The queued calls
1186 // should succeed immediately.
1187 base::MessageLoop::current()->Run();
1189 EXPECT_EQ(4, success_callback_count_
);
1190 EXPECT_EQ(0, error_callback_count_
);
1191 EXPECT_EQ(1, observer
.gatt_characteristic_value_changed_count());
1192 EXPECT_TRUE(characteristic
->IsNotifying());
1193 EXPECT_EQ(4U, update_sessions_
.size());
1195 for (int i
= 0; i
< 4; i
++)
1196 EXPECT_TRUE(update_sessions_
[0]->IsActive());
1198 // Stop notifications directly through the client. The sessions should get
1199 // marked as inactive.
1200 fake_bluetooth_gatt_characteristic_client_
->StopNotify(
1201 fake_bluetooth_gatt_characteristic_client_
->GetHeartRateMeasurementPath(),
1202 base::Bind(&BluetoothGattChromeOSTest::SuccessCallback
,
1203 base::Unretained(this)),
1204 base::Bind(&BluetoothGattChromeOSTest::DBusErrorCallback
,
1205 base::Unretained(this)));
1206 EXPECT_EQ(5, success_callback_count_
);
1207 EXPECT_EQ(0, error_callback_count_
);
1208 EXPECT_FALSE(characteristic
->IsNotifying());
1209 EXPECT_EQ(4U, update_sessions_
.size());
1211 for (int i
= 0; i
< 4; i
++)
1212 EXPECT_FALSE(update_sessions_
[0]->IsActive());
1214 // It should be possible to restart notifications and the call should reset
1215 // the session count and make a request through the client.
1216 update_sessions_
.clear();
1217 success_callback_count_
= 0;
1219 characteristic
->StartNotifySession(
1220 base::Bind(&BluetoothGattChromeOSTest::NotifySessionCallback
,
1221 base::Unretained(this)),
1222 base::Bind(&BluetoothGattChromeOSTest::ServiceErrorCallback
,
1223 base::Unretained(this)));
1225 EXPECT_EQ(0, success_callback_count_
);
1226 EXPECT_EQ(0, error_callback_count_
);
1227 EXPECT_EQ(1, observer
.gatt_characteristic_value_changed_count());
1228 EXPECT_TRUE(characteristic
->IsNotifying());
1229 EXPECT_TRUE(update_sessions_
.empty());
1231 base::MessageLoop::current()->Run();
1233 EXPECT_EQ(1, success_callback_count_
);
1234 EXPECT_EQ(0, error_callback_count_
);
1235 EXPECT_EQ(1, observer
.gatt_characteristic_value_changed_count());
1236 EXPECT_TRUE(characteristic
->IsNotifying());
1237 EXPECT_EQ(1U, update_sessions_
.size());
1238 EXPECT_TRUE(update_sessions_
[0]->IsActive());
1241 } // namespace chromeos