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 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());
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
);
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());
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());
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());
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());
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());
351 BluetoothUUID(FakeBluetoothGattServiceClient::kHeartRateServiceUUID
),
352 observer
.last_gatt_service_uuid());
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
);
365 TestBluetoothAdapterObserver
observer(adapter_
);
367 // Expose the fake Heart Rate service. This will asynchronously expose
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
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
);
433 TestBluetoothAdapterObserver
observer(adapter_
);
435 // Expose the fake Heart Rate service. This will asynchronously expose
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.
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.
534 BluetoothDevice
* device
= adapter_
->GetDevice(
535 FakeBluetoothDeviceClient::kLowEnergyAddress
);
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());
544 BluetoothUUID(FakeBluetoothGattServiceClient::kHeartRateServiceUUID
),
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
);
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
);
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
);
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
);
599 TestBluetoothAdapterObserver
observer(adapter_
);
601 // Expose the fake Heart Rate service. This will asynchronously expose
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.
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(
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(
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
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(
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(
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()
745 ASSERT_TRUE(characteristic
);
747 fake_bluetooth_gatt_characteristic_client_
->GetBodySensorLocationPath()
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
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
);
814 TestBluetoothAdapterObserver
observer(adapter_
);
816 // Expose the fake Heart Rate service. This will asynchronously expose
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
);
856 TestBluetoothAdapterObserver
observer(adapter_
);
858 // Expose the fake Heart Rate service. This will asynchronously expose
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
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(
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
);
979 TestBluetoothAdapterObserver
observer(adapter_
);
981 // Expose the fake Heart Rate service. This will asynchronously expose
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()
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
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;
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
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()
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
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;
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