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.
4
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 "testing/gtest/include/gtest/gtest.h"
27
28using device::BluetoothAdapter;
29using device::BluetoothDevice;
30using device::BluetoothGattCharacteristic;
31using device::BluetoothGattConnection;
32using device::BluetoothGattDescriptor;
33using device::BluetoothGattService;
34using device::BluetoothGattNotifySession;
35using device::BluetoothUUID;
36
37namespace chromeos {
38
39namespace {
40
41const BluetoothUUID kHeartRateMeasurementUUID(
42    FakeBluetoothGattCharacteristicClient::kHeartRateMeasurementUUID);
43const BluetoothUUID kBodySensorLocationUUID(
44    FakeBluetoothGattCharacteristicClient::kBodySensorLocationUUID);
45const BluetoothUUID kHeartRateControlPointUUID(
46    FakeBluetoothGattCharacteristicClient::kHeartRateControlPointUUID);
47
48// Compares GATT characteristic/descriptor values. Returns true, if the values
49// are equal.
50bool ValuesEqual(const std::vector<uint8>& value0,
51                 const std::vector<uint8>& value1) {
52  if (value0.size() != value1.size())
53    return false;
54  for (size_t i = 0; i < value0.size(); ++i)
55    if (value0[i] != value1[i])
56      return false;
57  return true;
58}
59
60class TestObserver : public BluetoothAdapter::Observer {
61 public:
62  TestObserver(scoped_refptr<BluetoothAdapter> adapter)
63      : gatt_service_added_count_(0),
64        gatt_service_removed_count_(0),
65        gatt_service_changed_count_(0),
66        gatt_discovery_complete_count_(0),
67        gatt_characteristic_added_count_(0),
68        gatt_characteristic_removed_count_(0),
69        gatt_characteristic_value_changed_count_(0),
70        gatt_descriptor_added_count_(0),
71        gatt_descriptor_removed_count_(0),
72        gatt_descriptor_value_changed_count_(0),
73        adapter_(adapter) {
74    adapter_->AddObserver(this);
75  }
76
77  virtual ~TestObserver() {
78    adapter_->RemoveObserver(this);
79  }
80
81  // BluetoothAdapter::Observer overrides.
82  virtual void GattServiceAdded(BluetoothAdapter* adapter,
83                                BluetoothDevice* device,
84                                BluetoothGattService* service) OVERRIDE {
85    ASSERT_EQ(adapter_.get(), adapter);
86    ASSERT_EQ(service->GetDevice(), device);
87
88    ++gatt_service_added_count_;
89    last_gatt_service_id_ = service->GetIdentifier();
90    last_gatt_service_uuid_ = service->GetUUID();
91
92    EXPECT_FALSE(service->IsLocal());
93    EXPECT_TRUE(service->IsPrimary());
94
95    EXPECT_EQ(device->GetGattService(last_gatt_service_id_), service);
96
97    QuitMessageLoop();
98  }
99
100  virtual void GattServiceRemoved(BluetoothAdapter* adapter,
101                                  BluetoothDevice* device,
102                                  BluetoothGattService* service) OVERRIDE {
103    ASSERT_EQ(adapter_.get(), adapter);
104    ASSERT_EQ(service->GetDevice(), device);
105
106    ++gatt_service_removed_count_;
107    last_gatt_service_id_ = service->GetIdentifier();
108    last_gatt_service_uuid_ = service->GetUUID();
109
110    EXPECT_FALSE(service->IsLocal());
111    EXPECT_TRUE(service->IsPrimary());
112
113    // The device should return NULL for this service.
114    EXPECT_FALSE(device->GetGattService(last_gatt_service_id_));
115
116    QuitMessageLoop();
117  }
118
119  virtual void GattDiscoveryCompleteForService(
120      BluetoothAdapter* adapter,
121      BluetoothGattService* service) OVERRIDE {
122    ASSERT_EQ(adapter_.get(), adapter);
123    ++gatt_discovery_complete_count_;
124
125    QuitMessageLoop();
126  }
127
128  virtual void GattServiceChanged(BluetoothAdapter* adapter,
129                                  BluetoothGattService* service) OVERRIDE {
130    ASSERT_EQ(adapter_.get(), adapter);
131    ++gatt_service_changed_count_;
132
133    QuitMessageLoop();
134  }
135
136  virtual void GattCharacteristicAdded(
137      BluetoothAdapter* adapter,
138      BluetoothGattCharacteristic* characteristic) OVERRIDE {
139    ASSERT_EQ(adapter_.get(), adapter);
140
141    ++gatt_characteristic_added_count_;
142    last_gatt_characteristic_id_ = characteristic->GetIdentifier();
143    last_gatt_characteristic_uuid_ = characteristic->GetUUID();
144
145    ASSERT_TRUE(characteristic->GetService());
146    EXPECT_EQ(characteristic->GetService()->GetCharacteristic(
147                  last_gatt_characteristic_id_),
148              characteristic);
149
150    QuitMessageLoop();
151  }
152
153  virtual void GattCharacteristicRemoved(
154      BluetoothAdapter* adapter,
155      BluetoothGattCharacteristic* characteristic) OVERRIDE {
156    ASSERT_EQ(adapter_.get(), adapter);
157
158    ++gatt_characteristic_removed_count_;
159    last_gatt_characteristic_id_ = characteristic->GetIdentifier();
160    last_gatt_characteristic_uuid_ = characteristic->GetUUID();
161
162    // The service should return NULL for this characteristic.
163    ASSERT_TRUE(characteristic->GetService());
164    EXPECT_FALSE(characteristic->GetService()->GetCharacteristic(
165        last_gatt_characteristic_id_));
166
167    QuitMessageLoop();
168  }
169
170  virtual void GattCharacteristicValueChanged(
171      BluetoothAdapter* adapter,
172      BluetoothGattCharacteristic* characteristic,
173      const std::vector<uint8>& value) OVERRIDE {
174    ASSERT_EQ(adapter_.get(), adapter);
175
176    ++gatt_characteristic_value_changed_count_;
177    last_gatt_characteristic_id_ = characteristic->GetIdentifier();
178    last_gatt_characteristic_uuid_ = characteristic->GetUUID();
179    last_changed_characteristic_value_ = value;
180
181    ASSERT_TRUE(characteristic->GetService());
182    EXPECT_EQ(characteristic->GetService()->GetCharacteristic(
183                  last_gatt_characteristic_id_),
184              characteristic);
185
186    QuitMessageLoop();
187  }
188
189  virtual void GattDescriptorAdded(
190      BluetoothAdapter* adapter,
191      BluetoothGattDescriptor* descriptor) OVERRIDE {
192    ASSERT_EQ(adapter_.get(), adapter);
193
194    ++gatt_descriptor_added_count_;
195    last_gatt_descriptor_id_ = descriptor->GetIdentifier();
196    last_gatt_descriptor_uuid_ = descriptor->GetUUID();
197
198    ASSERT_TRUE(descriptor->GetCharacteristic());
199    EXPECT_EQ(descriptor->GetCharacteristic()->GetDescriptor(
200                  last_gatt_descriptor_id_),
201              descriptor);
202
203    QuitMessageLoop();
204  }
205
206  virtual void GattDescriptorRemoved(
207      BluetoothAdapter* adapter,
208      BluetoothGattDescriptor* descriptor) OVERRIDE {
209    ASSERT_EQ(adapter_.get(), adapter);
210
211    ++gatt_descriptor_removed_count_;
212    last_gatt_descriptor_id_ = descriptor->GetIdentifier();
213    last_gatt_descriptor_uuid_ = descriptor->GetUUID();
214
215    // The characteristic should return NULL for this descriptor..
216    ASSERT_TRUE(descriptor->GetCharacteristic());
217    EXPECT_FALSE(descriptor->GetCharacteristic()->GetDescriptor(
218        last_gatt_descriptor_id_));
219
220    QuitMessageLoop();
221  }
222
223  virtual void GattDescriptorValueChanged(
224      BluetoothAdapter* adapter,
225      BluetoothGattDescriptor* descriptor,
226      const std::vector<uint8>& value) OVERRIDE {
227    ASSERT_EQ(adapter_.get(), adapter);
228
229    ++gatt_descriptor_value_changed_count_;
230    last_gatt_descriptor_id_ = descriptor->GetIdentifier();
231    last_gatt_descriptor_uuid_ = descriptor->GetUUID();
232    last_changed_descriptor_value_ = value;
233
234    ASSERT_TRUE(descriptor->GetCharacteristic());
235    EXPECT_EQ(descriptor->GetCharacteristic()->GetDescriptor(
236                  last_gatt_descriptor_id_),
237              descriptor);
238
239    QuitMessageLoop();
240  }
241
242  int gatt_service_added_count_;
243  int gatt_service_removed_count_;
244  int gatt_service_changed_count_;
245  int gatt_discovery_complete_count_;
246  int gatt_characteristic_added_count_;
247  int gatt_characteristic_removed_count_;
248  int gatt_characteristic_value_changed_count_;
249  int gatt_descriptor_added_count_;
250  int gatt_descriptor_removed_count_;
251  int gatt_descriptor_value_changed_count_;
252  std::string last_gatt_service_id_;
253  BluetoothUUID last_gatt_service_uuid_;
254  std::string last_gatt_characteristic_id_;
255  BluetoothUUID last_gatt_characteristic_uuid_;
256  std::vector<uint8> last_changed_characteristic_value_;
257  std::string last_gatt_descriptor_id_;
258  BluetoothUUID last_gatt_descriptor_uuid_;
259  std::vector<uint8> last_changed_descriptor_value_;
260
261 private:
262  // Some tests use a message loop since background processing is simulated;
263  // break out of those loops.
264  void QuitMessageLoop() {
265    if (base::MessageLoop::current() &&
266        base::MessageLoop::current()->is_running())
267      base::MessageLoop::current()->Quit();
268  }
269
270  scoped_refptr<BluetoothAdapter> adapter_;
271};
272
273}  // namespace
274
275class BluetoothGattChromeOSTest : public testing::Test {
276 public:
277  BluetoothGattChromeOSTest()
278      : fake_bluetooth_gatt_service_client_(NULL),
279        success_callback_count_(0),
280        error_callback_count_(0) {
281  }
282
283  virtual void SetUp() {
284    scoped_ptr<DBusThreadManagerSetter> dbus_setter =
285        chromeos::DBusThreadManager::GetSetterForTesting();
286    fake_bluetooth_device_client_ = new FakeBluetoothDeviceClient;
287    fake_bluetooth_gatt_service_client_ =
288        new FakeBluetoothGattServiceClient;
289    fake_bluetooth_gatt_characteristic_client_ =
290        new FakeBluetoothGattCharacteristicClient;
291    fake_bluetooth_gatt_descriptor_client_ =
292        new FakeBluetoothGattDescriptorClient;
293    dbus_setter->SetBluetoothDeviceClient(
294        scoped_ptr<BluetoothDeviceClient>(
295            fake_bluetooth_device_client_));
296    dbus_setter->SetBluetoothGattServiceClient(
297        scoped_ptr<BluetoothGattServiceClient>(
298            fake_bluetooth_gatt_service_client_));
299    dbus_setter->SetBluetoothGattCharacteristicClient(
300        scoped_ptr<BluetoothGattCharacteristicClient>(
301            fake_bluetooth_gatt_characteristic_client_));
302    dbus_setter->SetBluetoothGattDescriptorClient(
303        scoped_ptr<BluetoothGattDescriptorClient>(
304            fake_bluetooth_gatt_descriptor_client_));
305    dbus_setter->SetBluetoothAdapterClient(
306        scoped_ptr<BluetoothAdapterClient>(new FakeBluetoothAdapterClient));
307    dbus_setter->SetBluetoothInputClient(
308        scoped_ptr<BluetoothInputClient>(new FakeBluetoothInputClient));
309    dbus_setter->SetBluetoothAgentManagerClient(
310        scoped_ptr<BluetoothAgentManagerClient>(
311            new FakeBluetoothAgentManagerClient));
312
313    GetAdapter();
314
315    adapter_->SetPowered(
316        true,
317        base::Bind(&base::DoNothing),
318        base::Bind(&base::DoNothing));
319    ASSERT_TRUE(adapter_->IsPowered());
320  }
321
322  virtual void TearDown() {
323    adapter_ = NULL;
324    update_sessions_.clear();
325    gatt_conn_.reset();
326    DBusThreadManager::Shutdown();
327  }
328
329  void GetAdapter() {
330    device::BluetoothAdapterFactory::GetAdapter(
331        base::Bind(&BluetoothGattChromeOSTest::AdapterCallback,
332                   base::Unretained(this)));
333    ASSERT_TRUE(adapter_.get() != NULL);
334    ASSERT_TRUE(adapter_->IsInitialized());
335    ASSERT_TRUE(adapter_->IsPresent());
336  }
337
338  void AdapterCallback(scoped_refptr<BluetoothAdapter> adapter) {
339    adapter_ = adapter;
340  }
341
342  void SuccessCallback() {
343    ++success_callback_count_;
344  }
345
346  void ValueCallback(const std::vector<uint8>& value) {
347    ++success_callback_count_;
348    last_read_value_ = value;
349  }
350
351  void GattConnectionCallback(scoped_ptr<BluetoothGattConnection> conn) {
352    ++success_callback_count_;
353    gatt_conn_ = conn.Pass();
354  }
355
356  void NotifySessionCallback(scoped_ptr<BluetoothGattNotifySession> session) {
357    ++success_callback_count_;
358    update_sessions_.push_back(session.release());
359    QuitMessageLoop();
360  }
361
362  void ErrorCallback() {
363    ++error_callback_count_;
364  }
365
366  void DBusErrorCallback(const std::string& error_name,
367                         const std::string& error_message) {
368    ++error_callback_count_;
369  }
370
371  void ConnectErrorCallback(BluetoothDevice::ConnectErrorCode error) {
372    ++error_callback_count_;
373  }
374
375 protected:
376  void QuitMessageLoop() {
377    if (base::MessageLoop::current() &&
378        base::MessageLoop::current()->is_running())
379      base::MessageLoop::current()->Quit();
380  }
381
382  base::MessageLoop message_loop_;
383
384  FakeBluetoothDeviceClient* fake_bluetooth_device_client_;
385  FakeBluetoothGattServiceClient* fake_bluetooth_gatt_service_client_;
386  FakeBluetoothGattCharacteristicClient*
387      fake_bluetooth_gatt_characteristic_client_;
388  FakeBluetoothGattDescriptorClient* fake_bluetooth_gatt_descriptor_client_;
389  scoped_ptr<device::BluetoothGattConnection> gatt_conn_;
390  ScopedVector<BluetoothGattNotifySession> update_sessions_;
391  scoped_refptr<BluetoothAdapter> adapter_;
392
393  int success_callback_count_;
394  int error_callback_count_;
395  std::vector<uint8> last_read_value_;
396};
397
398TEST_F(BluetoothGattChromeOSTest, GattConnection) {
399  fake_bluetooth_device_client_->CreateDevice(
400      dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
401      dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
402  BluetoothDevice* device = adapter_->GetDevice(
403      FakeBluetoothDeviceClient::kLowEnergyAddress);
404  ASSERT_TRUE(device);
405  ASSERT_FALSE(device->IsConnected());
406  ASSERT_FALSE(gatt_conn_.get());
407  ASSERT_EQ(0, success_callback_count_);
408  ASSERT_EQ(0, error_callback_count_);
409
410  device->CreateGattConnection(
411      base::Bind(&BluetoothGattChromeOSTest::GattConnectionCallback,
412                 base::Unretained(this)),
413      base::Bind(&BluetoothGattChromeOSTest::ConnectErrorCallback,
414                 base::Unretained(this)));
415
416  EXPECT_EQ(1, success_callback_count_);
417  EXPECT_EQ(0, error_callback_count_);
418  EXPECT_TRUE(device->IsConnected());
419  ASSERT_TRUE(gatt_conn_.get());
420  EXPECT_TRUE(gatt_conn_->IsConnected());
421  EXPECT_EQ(FakeBluetoothDeviceClient::kLowEnergyAddress,
422            gatt_conn_->GetDeviceAddress());
423
424  gatt_conn_->Disconnect(
425      base::Bind(&BluetoothGattChromeOSTest::SuccessCallback,
426                 base::Unretained(this)));
427  EXPECT_EQ(2, success_callback_count_);
428  EXPECT_EQ(0, error_callback_count_);
429  EXPECT_TRUE(device->IsConnected());
430  EXPECT_FALSE(gatt_conn_->IsConnected());
431
432  device->CreateGattConnection(
433      base::Bind(&BluetoothGattChromeOSTest::GattConnectionCallback,
434                 base::Unretained(this)),
435      base::Bind(&BluetoothGattChromeOSTest::ConnectErrorCallback,
436                 base::Unretained(this)));
437
438  EXPECT_EQ(3, success_callback_count_);
439  EXPECT_EQ(0, error_callback_count_);
440  EXPECT_TRUE(device->IsConnected());
441  ASSERT_TRUE(gatt_conn_.get());
442  EXPECT_TRUE(gatt_conn_->IsConnected());
443
444  device->Disconnect(
445      base::Bind(&BluetoothGattChromeOSTest::SuccessCallback,
446                 base::Unretained(this)),
447      base::Bind(&BluetoothGattChromeOSTest::ErrorCallback,
448                 base::Unretained(this)));
449
450  EXPECT_EQ(4, success_callback_count_);
451  EXPECT_EQ(0, error_callback_count_);
452  ASSERT_TRUE(gatt_conn_.get());
453  EXPECT_FALSE(gatt_conn_->IsConnected());
454
455  device->CreateGattConnection(
456      base::Bind(&BluetoothGattChromeOSTest::GattConnectionCallback,
457                 base::Unretained(this)),
458      base::Bind(&BluetoothGattChromeOSTest::ConnectErrorCallback,
459                 base::Unretained(this)));
460
461  EXPECT_EQ(5, success_callback_count_);
462  EXPECT_EQ(0, error_callback_count_);
463  EXPECT_TRUE(device->IsConnected());
464  EXPECT_TRUE(gatt_conn_->IsConnected());
465
466  fake_bluetooth_device_client_->RemoveDevice(
467      dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
468      dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
469  ASSERT_TRUE(gatt_conn_.get());
470  EXPECT_FALSE(gatt_conn_->IsConnected());
471}
472
473TEST_F(BluetoothGattChromeOSTest, GattServiceAddedAndRemoved) {
474  // Create a fake LE device. We store the device pointer here because this is a
475  // test. It's unsafe to do this in production as the device might get deleted.
476  fake_bluetooth_device_client_->CreateDevice(
477      dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
478      dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
479  BluetoothDevice* device = adapter_->GetDevice(
480      FakeBluetoothDeviceClient::kLowEnergyAddress);
481  ASSERT_TRUE(device);
482
483  TestObserver observer(adapter_);
484
485  EXPECT_EQ(0, observer.gatt_service_added_count_);
486  EXPECT_EQ(0, observer.gatt_service_removed_count_);
487  EXPECT_TRUE(observer.last_gatt_service_id_.empty());
488  EXPECT_FALSE(observer.last_gatt_service_uuid_.IsValid());
489  EXPECT_TRUE(device->GetGattServices().empty());
490
491  // Expose the fake Heart Rate Service.
492  fake_bluetooth_gatt_service_client_->ExposeHeartRateService(
493      dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
494  EXPECT_EQ(1, observer.gatt_service_added_count_);
495  EXPECT_EQ(0, observer.gatt_service_removed_count_);
496  EXPECT_FALSE(observer.last_gatt_service_id_.empty());
497  EXPECT_EQ(1U, device->GetGattServices().size());
498  EXPECT_EQ(
499      BluetoothUUID(FakeBluetoothGattServiceClient::kHeartRateServiceUUID),
500      observer.last_gatt_service_uuid_);
501
502  BluetoothGattService* service =
503      device->GetGattService(observer.last_gatt_service_id_);
504  EXPECT_FALSE(service->IsLocal());
505  EXPECT_TRUE(service->IsPrimary());
506  EXPECT_EQ(service, device->GetGattServices()[0]);
507  EXPECT_EQ(service, device->GetGattService(service->GetIdentifier()));
508
509  EXPECT_EQ(observer.last_gatt_service_uuid_, service->GetUUID());
510
511  // Hide the service.
512  observer.last_gatt_service_uuid_ = BluetoothUUID();
513  observer.last_gatt_service_id_.clear();
514  fake_bluetooth_gatt_service_client_->HideHeartRateService();
515
516  EXPECT_EQ(1, observer.gatt_service_added_count_);
517  EXPECT_EQ(1, observer.gatt_service_removed_count_);
518  EXPECT_FALSE(observer.last_gatt_service_id_.empty());
519  EXPECT_TRUE(device->GetGattServices().empty());
520  EXPECT_EQ(
521      BluetoothUUID(FakeBluetoothGattServiceClient::kHeartRateServiceUUID),
522      observer.last_gatt_service_uuid_);
523
524  EXPECT_EQ(NULL, device->GetGattService(observer.last_gatt_service_id_));
525
526  // Expose the service again.
527  observer.last_gatt_service_uuid_ = BluetoothUUID();
528  observer.last_gatt_service_id_.clear();
529  fake_bluetooth_gatt_service_client_->ExposeHeartRateService(
530      dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
531  EXPECT_EQ(2, observer.gatt_service_added_count_);
532  EXPECT_EQ(1, observer.gatt_service_removed_count_);
533  EXPECT_FALSE(observer.last_gatt_service_id_.empty());
534  EXPECT_EQ(1U, device->GetGattServices().size());
535  EXPECT_EQ(
536      BluetoothUUID(FakeBluetoothGattServiceClient::kHeartRateServiceUUID),
537      observer.last_gatt_service_uuid_);
538
539  // The object |service| points to should have been deallocated. |device|
540  // should contain a brand new instance.
541  service = device->GetGattService(observer.last_gatt_service_id_);
542  EXPECT_EQ(service, device->GetGattServices()[0]);
543  EXPECT_FALSE(service->IsLocal());
544  EXPECT_TRUE(service->IsPrimary());
545
546  EXPECT_EQ(observer.last_gatt_service_uuid_, service->GetUUID());
547
548  // Remove the device. The observer should be notified of the removed service.
549  // |device| becomes invalid after this.
550  observer.last_gatt_service_uuid_ = BluetoothUUID();
551  observer.last_gatt_service_id_.clear();
552  fake_bluetooth_device_client_->RemoveDevice(
553      dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
554      dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
555
556  EXPECT_EQ(2, observer.gatt_service_added_count_);
557  EXPECT_EQ(2, observer.gatt_service_removed_count_);
558  EXPECT_FALSE(observer.last_gatt_service_id_.empty());
559  EXPECT_EQ(
560      BluetoothUUID(FakeBluetoothGattServiceClient::kHeartRateServiceUUID),
561      observer.last_gatt_service_uuid_);
562  EXPECT_EQ(
563      NULL, adapter_->GetDevice(FakeBluetoothDeviceClient::kLowEnergyAddress));
564}
565
566TEST_F(BluetoothGattChromeOSTest, GattCharacteristicAddedAndRemoved) {
567  fake_bluetooth_device_client_->CreateDevice(
568      dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
569      dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
570  BluetoothDevice* device = adapter_->GetDevice(
571      FakeBluetoothDeviceClient::kLowEnergyAddress);
572  ASSERT_TRUE(device);
573
574  TestObserver observer(adapter_);
575
576  // Expose the fake Heart Rate service. This will asynchronously expose
577  // characteristics.
578  fake_bluetooth_gatt_service_client_->ExposeHeartRateService(
579      dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
580  ASSERT_EQ(1, observer.gatt_service_added_count_);
581
582  BluetoothGattService* service =
583      device->GetGattService(observer.last_gatt_service_id_);
584
585  EXPECT_EQ(0, observer.gatt_service_changed_count_);
586  EXPECT_EQ(0, observer.gatt_discovery_complete_count_);
587  EXPECT_EQ(0, observer.gatt_characteristic_added_count_);
588  EXPECT_EQ(0, observer.gatt_characteristic_removed_count_);
589  EXPECT_EQ(0, observer.gatt_characteristic_value_changed_count_);
590  EXPECT_TRUE(service->GetCharacteristics().empty());
591
592  // Run the message loop so that the characteristics appear.
593  base::MessageLoop::current()->Run();
594
595  // 3 characteristics should appear. Only 1 of the characteristics sends
596  // value changed signals. Service changed should be fired once for
597  // descriptor added.
598  EXPECT_EQ(0, observer.gatt_service_changed_count_);
599  EXPECT_EQ(1, observer.gatt_discovery_complete_count_);
600  EXPECT_EQ(3, observer.gatt_characteristic_added_count_);
601  EXPECT_EQ(0, observer.gatt_characteristic_removed_count_);
602  EXPECT_EQ(0, observer.gatt_characteristic_value_changed_count_);
603  EXPECT_EQ(3U, service->GetCharacteristics().size());
604
605  // Hide the characteristics. 3 removed signals should be received.
606  fake_bluetooth_gatt_characteristic_client_->HideHeartRateCharacteristics();
607  EXPECT_EQ(0, observer.gatt_service_changed_count_);
608  EXPECT_EQ(3, observer.gatt_characteristic_added_count_);
609  EXPECT_EQ(3, observer.gatt_characteristic_removed_count_);
610  EXPECT_EQ(0, observer.gatt_characteristic_value_changed_count_);
611  EXPECT_TRUE(service->GetCharacteristics().empty());
612
613  // Re-expose the heart rate characteristics. We shouldn't get another
614  // GattDiscoveryCompleteForService call, since the service thinks that
615  // discovery is done. On the bluetoothd side, characteristics will be removed
616  // only if the service will also be subsequently removed.
617  fake_bluetooth_gatt_characteristic_client_->ExposeHeartRateCharacteristics(
618      fake_bluetooth_gatt_service_client_->GetHeartRateServicePath());
619  EXPECT_EQ(0, observer.gatt_service_changed_count_);
620  EXPECT_EQ(1, observer.gatt_discovery_complete_count_);
621  EXPECT_EQ(6, observer.gatt_characteristic_added_count_);
622  EXPECT_EQ(3, observer.gatt_characteristic_removed_count_);
623  EXPECT_EQ(0, observer.gatt_characteristic_value_changed_count_);
624  EXPECT_EQ(3U, service->GetCharacteristics().size());
625
626  // Hide the service. All characteristics should disappear.
627  fake_bluetooth_gatt_service_client_->HideHeartRateService();
628  EXPECT_EQ(0, observer.gatt_service_changed_count_);
629  EXPECT_EQ(6, observer.gatt_characteristic_added_count_);
630  EXPECT_EQ(6, observer.gatt_characteristic_removed_count_);
631  EXPECT_EQ(0, observer.gatt_characteristic_value_changed_count_);
632}
633
634TEST_F(BluetoothGattChromeOSTest, GattDescriptorAddedAndRemoved) {
635  fake_bluetooth_device_client_->CreateDevice(
636      dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
637      dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
638  BluetoothDevice* device = adapter_->GetDevice(
639      FakeBluetoothDeviceClient::kLowEnergyAddress);
640  ASSERT_TRUE(device);
641
642  TestObserver observer(adapter_);
643
644  // Expose the fake Heart Rate service. This will asynchronously expose
645  // characteristics.
646  fake_bluetooth_gatt_service_client_->ExposeHeartRateService(
647      dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
648  ASSERT_EQ(1, observer.gatt_service_added_count_);
649
650  BluetoothGattService* service =
651      device->GetGattService(observer.last_gatt_service_id_);
652
653  EXPECT_EQ(0, observer.gatt_service_changed_count_);
654  EXPECT_EQ(0, observer.gatt_descriptor_added_count_);
655  EXPECT_EQ(0, observer.gatt_descriptor_removed_count_);
656  EXPECT_EQ(0, observer.gatt_descriptor_value_changed_count_);
657
658  EXPECT_TRUE(service->GetCharacteristics().empty());
659
660  // Run the message loop so that the characteristics appear.
661  base::MessageLoop::current()->Run();
662  EXPECT_EQ(0, observer.gatt_service_changed_count_);
663
664  // Only the Heart Rate Measurement characteristic has a descriptor.
665  EXPECT_EQ(1, observer.gatt_descriptor_added_count_);
666  EXPECT_EQ(0, observer.gatt_descriptor_removed_count_);
667  EXPECT_EQ(0, observer.gatt_descriptor_value_changed_count_);
668
669  BluetoothGattCharacteristic* characteristic = service->GetCharacteristic(
670      fake_bluetooth_gatt_characteristic_client_->
671          GetBodySensorLocationPath().value());
672  ASSERT_TRUE(characteristic);
673  EXPECT_TRUE(characteristic->GetDescriptors().empty());
674
675  characteristic = service->GetCharacteristic(
676      fake_bluetooth_gatt_characteristic_client_->
677          GetHeartRateControlPointPath().value());
678  ASSERT_TRUE(characteristic);
679  EXPECT_TRUE(characteristic->GetDescriptors().empty());
680
681  characteristic = service->GetCharacteristic(
682      fake_bluetooth_gatt_characteristic_client_->
683          GetHeartRateMeasurementPath().value());
684  ASSERT_TRUE(characteristic);
685  EXPECT_EQ(1U, characteristic->GetDescriptors().size());
686
687  BluetoothGattDescriptor* descriptor = characteristic->GetDescriptors()[0];
688  EXPECT_FALSE(descriptor->IsLocal());
689  EXPECT_EQ(BluetoothGattDescriptor::ClientCharacteristicConfigurationUuid(),
690            descriptor->GetUUID());
691  EXPECT_EQ(descriptor->GetUUID(), observer.last_gatt_descriptor_uuid_);
692  EXPECT_EQ(descriptor->GetIdentifier(), observer.last_gatt_descriptor_id_);
693
694  // Hide the descriptor.
695  fake_bluetooth_gatt_descriptor_client_->HideDescriptor(
696      dbus::ObjectPath(descriptor->GetIdentifier()));
697  EXPECT_TRUE(characteristic->GetDescriptors().empty());
698  EXPECT_EQ(0, observer.gatt_service_changed_count_);
699  EXPECT_EQ(1, observer.gatt_descriptor_added_count_);
700  EXPECT_EQ(1, observer.gatt_descriptor_removed_count_);
701  EXPECT_EQ(0, observer.gatt_descriptor_value_changed_count_);
702
703  // Expose the descriptor again.
704  observer.last_gatt_descriptor_id_.clear();
705  observer.last_gatt_descriptor_uuid_ = BluetoothUUID();
706  fake_bluetooth_gatt_descriptor_client_->ExposeDescriptor(
707      dbus::ObjectPath(characteristic->GetIdentifier()),
708      FakeBluetoothGattDescriptorClient::
709          kClientCharacteristicConfigurationUUID);
710  EXPECT_EQ(0, observer.gatt_service_changed_count_);
711  EXPECT_EQ(1U, characteristic->GetDescriptors().size());
712  EXPECT_EQ(2, observer.gatt_descriptor_added_count_);
713  EXPECT_EQ(1, observer.gatt_descriptor_removed_count_);
714  EXPECT_EQ(0, observer.gatt_descriptor_value_changed_count_);
715
716  descriptor = characteristic->GetDescriptors()[0];
717  EXPECT_FALSE(descriptor->IsLocal());
718  EXPECT_EQ(BluetoothGattDescriptor::ClientCharacteristicConfigurationUuid(),
719            descriptor->GetUUID());
720  EXPECT_EQ(descriptor->GetUUID(), observer.last_gatt_descriptor_uuid_);
721  EXPECT_EQ(descriptor->GetIdentifier(), observer.last_gatt_descriptor_id_);
722}
723
724TEST_F(BluetoothGattChromeOSTest, AdapterAddedAfterGattService) {
725  // This unit test tests that all remote GATT objects are created for D-Bus
726  // objects that were already exposed.
727  adapter_ = NULL;
728  ASSERT_FALSE(device::BluetoothAdapterFactory::HasSharedInstanceForTesting());
729
730  // Create the fake D-Bus objects.
731  fake_bluetooth_device_client_->CreateDevice(
732      dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
733      dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
734  fake_bluetooth_gatt_service_client_->ExposeHeartRateService(
735      dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
736  while (!fake_bluetooth_gatt_characteristic_client_->IsHeartRateVisible())
737    base::RunLoop().RunUntilIdle();
738  ASSERT_TRUE(fake_bluetooth_gatt_service_client_->IsHeartRateVisible());
739  ASSERT_TRUE(fake_bluetooth_gatt_characteristic_client_->IsHeartRateVisible());
740
741  // Create the adapter. This should create all the GATT objects.
742  GetAdapter();
743  BluetoothDevice* device = adapter_->GetDevice(
744      FakeBluetoothDeviceClient::kLowEnergyAddress);
745  ASSERT_TRUE(device);
746  EXPECT_EQ(1U, device->GetGattServices().size());
747
748  BluetoothGattService* service = device->GetGattServices()[0];
749  ASSERT_TRUE(service);
750  EXPECT_FALSE(service->IsLocal());
751  EXPECT_TRUE(service->IsPrimary());
752  EXPECT_EQ(
753      BluetoothUUID(FakeBluetoothGattServiceClient::kHeartRateServiceUUID),
754      service->GetUUID());
755  EXPECT_EQ(service, device->GetGattServices()[0]);
756  EXPECT_EQ(service, device->GetGattService(service->GetIdentifier()));
757  EXPECT_FALSE(service->IsLocal());
758  EXPECT_EQ(3U, service->GetCharacteristics().size());
759
760  BluetoothGattCharacteristic* characteristic = service->GetCharacteristic(
761      fake_bluetooth_gatt_characteristic_client_->
762          GetBodySensorLocationPath().value());
763  ASSERT_TRUE(characteristic);
764  EXPECT_EQ(
765      BluetoothUUID(FakeBluetoothGattCharacteristicClient::
766          kBodySensorLocationUUID),
767      characteristic->GetUUID());
768  EXPECT_FALSE(characteristic->IsLocal());
769  EXPECT_TRUE(characteristic->GetDescriptors().empty());
770
771  characteristic = service->GetCharacteristic(
772      fake_bluetooth_gatt_characteristic_client_->
773          GetHeartRateControlPointPath().value());
774  ASSERT_TRUE(characteristic);
775  EXPECT_EQ(
776      BluetoothUUID(FakeBluetoothGattCharacteristicClient::
777          kHeartRateControlPointUUID),
778      characteristic->GetUUID());
779  EXPECT_FALSE(characteristic->IsLocal());
780  EXPECT_TRUE(characteristic->GetDescriptors().empty());
781
782  characteristic = service->GetCharacteristic(
783      fake_bluetooth_gatt_characteristic_client_->
784          GetHeartRateMeasurementPath().value());
785  ASSERT_TRUE(characteristic);
786  EXPECT_EQ(
787      BluetoothUUID(FakeBluetoothGattCharacteristicClient::
788          kHeartRateMeasurementUUID),
789      characteristic->GetUUID());
790  EXPECT_FALSE(characteristic->IsLocal());
791  EXPECT_EQ(1U, characteristic->GetDescriptors().size());
792
793  BluetoothGattDescriptor* descriptor = characteristic->GetDescriptors()[0];
794  ASSERT_TRUE(descriptor);
795  EXPECT_EQ(BluetoothGattDescriptor::ClientCharacteristicConfigurationUuid(),
796            descriptor->GetUUID());
797  EXPECT_FALSE(descriptor->IsLocal());
798}
799
800TEST_F(BluetoothGattChromeOSTest, GattCharacteristicValue) {
801  fake_bluetooth_device_client_->CreateDevice(
802      dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
803      dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
804  BluetoothDevice* device = adapter_->GetDevice(
805      FakeBluetoothDeviceClient::kLowEnergyAddress);
806  ASSERT_TRUE(device);
807
808  TestObserver observer(adapter_);
809
810  // Expose the fake Heart Rate service. This will asynchronously expose
811  // characteristics.
812  fake_bluetooth_gatt_service_client_->ExposeHeartRateService(
813      dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
814  ASSERT_EQ(1, observer.gatt_service_added_count_);
815
816  BluetoothGattService* service =
817      device->GetGattService(observer.last_gatt_service_id_);
818
819  EXPECT_EQ(0, observer.gatt_characteristic_value_changed_count_);
820
821  // Run the message loop so that the characteristics appear.
822  base::MessageLoop::current()->Run();
823
824  // Issue write request to non-writeable characteristics.
825  observer.last_gatt_characteristic_id_.clear();
826  observer.last_gatt_characteristic_uuid_ = BluetoothUUID();
827
828  std::vector<uint8> write_value;
829  write_value.push_back(0x01);
830  BluetoothGattCharacteristic* characteristic =
831      service->GetCharacteristic(fake_bluetooth_gatt_characteristic_client_->
832          GetHeartRateMeasurementPath().value());
833  ASSERT_TRUE(characteristic);
834  EXPECT_FALSE(characteristic->IsNotifying());
835  EXPECT_EQ(fake_bluetooth_gatt_characteristic_client_->
836                GetHeartRateMeasurementPath().value(),
837            characteristic->GetIdentifier());
838  EXPECT_EQ(kHeartRateMeasurementUUID, characteristic->GetUUID());
839  characteristic->WriteRemoteCharacteristic(
840      write_value,
841      base::Bind(&BluetoothGattChromeOSTest::SuccessCallback,
842                 base::Unretained(this)),
843      base::Bind(&BluetoothGattChromeOSTest::ErrorCallback,
844                 base::Unretained(this)));
845  EXPECT_TRUE(observer.last_gatt_characteristic_id_.empty());
846  EXPECT_FALSE(observer.last_gatt_characteristic_uuid_.IsValid());
847  EXPECT_EQ(0, success_callback_count_);
848  EXPECT_EQ(1, error_callback_count_);
849  EXPECT_EQ(0, observer.gatt_characteristic_value_changed_count_);
850
851  characteristic = service->GetCharacteristic(
852      fake_bluetooth_gatt_characteristic_client_->
853          GetBodySensorLocationPath().value());
854  ASSERT_TRUE(characteristic);
855  EXPECT_EQ(fake_bluetooth_gatt_characteristic_client_->
856                GetBodySensorLocationPath().value(),
857            characteristic->GetIdentifier());
858  EXPECT_EQ(kBodySensorLocationUUID, characteristic->GetUUID());
859  characteristic->WriteRemoteCharacteristic(
860      write_value,
861      base::Bind(&BluetoothGattChromeOSTest::SuccessCallback,
862                 base::Unretained(this)),
863      base::Bind(&BluetoothGattChromeOSTest::ErrorCallback,
864                 base::Unretained(this)));
865  EXPECT_TRUE(observer.last_gatt_characteristic_id_.empty());
866  EXPECT_FALSE(observer.last_gatt_characteristic_uuid_.IsValid());
867  EXPECT_EQ(0, success_callback_count_);
868  EXPECT_EQ(2, error_callback_count_);
869  EXPECT_EQ(0, observer.gatt_characteristic_value_changed_count_);
870
871  // Issue write request to writeable characteristic. The "Body Sensor Location"
872  // characteristic does not send notifications and WriteValue does not result
873  // in a CharacteristicValueChanged event, thus no such event should be
874  // received.
875  characteristic = service->GetCharacteristic(
876      fake_bluetooth_gatt_characteristic_client_->
877          GetHeartRateControlPointPath().value());
878  ASSERT_TRUE(characteristic);
879  EXPECT_EQ(fake_bluetooth_gatt_characteristic_client_->
880                GetHeartRateControlPointPath().value(),
881            characteristic->GetIdentifier());
882  EXPECT_EQ(kHeartRateControlPointUUID, characteristic->GetUUID());
883  characteristic->WriteRemoteCharacteristic(
884      write_value,
885      base::Bind(&BluetoothGattChromeOSTest::SuccessCallback,
886                 base::Unretained(this)),
887      base::Bind(&BluetoothGattChromeOSTest::ErrorCallback,
888                 base::Unretained(this)));
889  EXPECT_TRUE(observer.last_gatt_characteristic_id_.empty());
890  EXPECT_FALSE(observer.last_gatt_characteristic_uuid_.IsValid());
891  EXPECT_EQ(1, success_callback_count_);
892  EXPECT_EQ(2, error_callback_count_);
893  EXPECT_EQ(0, observer.gatt_characteristic_value_changed_count_);
894
895  // Issue a read request. A successful read results in a
896  // CharacteristicValueChanged notification.
897  characteristic = service->GetCharacteristic(
898      fake_bluetooth_gatt_characteristic_client_->
899          GetBodySensorLocationPath().value());
900  ASSERT_TRUE(characteristic);
901  EXPECT_EQ(fake_bluetooth_gatt_characteristic_client_->
902                GetBodySensorLocationPath().value(),
903            characteristic->GetIdentifier());
904  EXPECT_EQ(kBodySensorLocationUUID, characteristic->GetUUID());
905  characteristic->ReadRemoteCharacteristic(
906      base::Bind(&BluetoothGattChromeOSTest::ValueCallback,
907                 base::Unretained(this)),
908      base::Bind(&BluetoothGattChromeOSTest::ErrorCallback,
909                 base::Unretained(this)));
910  EXPECT_EQ(2, success_callback_count_);
911  EXPECT_EQ(2, error_callback_count_);
912  EXPECT_EQ(1, observer.gatt_characteristic_value_changed_count_);
913  EXPECT_TRUE(ValuesEqual(characteristic->GetValue(), last_read_value_));
914}
915
916TEST_F(BluetoothGattChromeOSTest, GattCharacteristicProperties) {
917  fake_bluetooth_device_client_->CreateDevice(
918      dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
919      dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
920  BluetoothDevice* device = adapter_->GetDevice(
921      FakeBluetoothDeviceClient::kLowEnergyAddress);
922  ASSERT_TRUE(device);
923
924  TestObserver observer(adapter_);
925
926  // Expose the fake Heart Rate service. This will asynchronously expose
927  // characteristics.
928  fake_bluetooth_gatt_service_client_->ExposeHeartRateService(
929      dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
930
931  BluetoothGattService* service =
932      device->GetGattService(observer.last_gatt_service_id_);
933
934  EXPECT_TRUE(service->GetCharacteristics().empty());
935
936  // Run the message loop so that the characteristics appear.
937  base::MessageLoop::current()->Run();
938
939  BluetoothGattCharacteristic *characteristic = service->GetCharacteristic(
940      fake_bluetooth_gatt_characteristic_client_->
941          GetBodySensorLocationPath().value());
942  EXPECT_EQ(BluetoothGattCharacteristic::kPropertyRead,
943            characteristic->GetProperties());
944
945  characteristic = service->GetCharacteristic(
946      fake_bluetooth_gatt_characteristic_client_->
947          GetHeartRateControlPointPath().value());
948  EXPECT_EQ(BluetoothGattCharacteristic::kPropertyWrite,
949            characteristic->GetProperties());
950
951  characteristic = service->GetCharacteristic(
952      fake_bluetooth_gatt_characteristic_client_->
953          GetHeartRateMeasurementPath().value());
954  EXPECT_EQ(BluetoothGattCharacteristic::kPropertyNotify,
955            characteristic->GetProperties());
956}
957
958TEST_F(BluetoothGattChromeOSTest, GattDescriptorValue) {
959  fake_bluetooth_device_client_->CreateDevice(
960      dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
961      dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
962  BluetoothDevice* device = adapter_->GetDevice(
963      FakeBluetoothDeviceClient::kLowEnergyAddress);
964  ASSERT_TRUE(device);
965
966  TestObserver observer(adapter_);
967
968  // Expose the fake Heart Rate service. This will asynchronously expose
969  // characteristics.
970  fake_bluetooth_gatt_service_client_->ExposeHeartRateService(
971      dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
972  ASSERT_EQ(1, observer.gatt_service_added_count_);
973
974  BluetoothGattService* service =
975      device->GetGattService(observer.last_gatt_service_id_);
976
977  EXPECT_EQ(0, observer.gatt_service_changed_count_);
978  EXPECT_EQ(0, observer.gatt_discovery_complete_count_);
979  EXPECT_EQ(0, observer.gatt_descriptor_value_changed_count_);
980  EXPECT_TRUE(service->GetCharacteristics().empty());
981
982  // Run the message loop so that the characteristics appear.
983  base::MessageLoop::current()->Run();
984  EXPECT_EQ(0, observer.gatt_service_changed_count_);
985  EXPECT_EQ(1, observer.gatt_discovery_complete_count_);
986
987  // Only the Heart Rate Measurement characteristic has a descriptor.
988  BluetoothGattCharacteristic* characteristic = service->GetCharacteristic(
989      fake_bluetooth_gatt_characteristic_client_->
990          GetHeartRateMeasurementPath().value());
991  ASSERT_TRUE(characteristic);
992  EXPECT_EQ(1U, characteristic->GetDescriptors().size());
993
994  BluetoothGattDescriptor* descriptor = characteristic->GetDescriptors()[0];
995  EXPECT_FALSE(descriptor->IsLocal());
996  EXPECT_EQ(BluetoothGattDescriptor::ClientCharacteristicConfigurationUuid(),
997            descriptor->GetUUID());
998
999  std::vector<uint8> desc_value;
1000  desc_value.push_back(1);
1001  desc_value.push_back(0);
1002
1003  /* The cached value will be empty until the first read request */
1004  EXPECT_FALSE(ValuesEqual(desc_value, descriptor->GetValue()));
1005  EXPECT_TRUE(descriptor->GetValue().empty());
1006
1007  EXPECT_EQ(0, success_callback_count_);
1008  EXPECT_EQ(0, error_callback_count_);
1009  EXPECT_TRUE(last_read_value_.empty());
1010
1011  // Read value. GattDescriptorValueChanged event will be sent after a
1012  // successful read.
1013  descriptor->ReadRemoteDescriptor(
1014      base::Bind(&BluetoothGattChromeOSTest::ValueCallback,
1015                 base::Unretained(this)),
1016      base::Bind(&BluetoothGattChromeOSTest::ErrorCallback,
1017                 base::Unretained(this)));
1018  EXPECT_EQ(1, success_callback_count_);
1019  EXPECT_EQ(0, error_callback_count_);
1020  EXPECT_TRUE(ValuesEqual(last_read_value_, descriptor->GetValue()));
1021  EXPECT_TRUE(ValuesEqual(desc_value, descriptor->GetValue()));
1022  EXPECT_EQ(0, observer.gatt_service_changed_count_);
1023  EXPECT_EQ(1, observer.gatt_descriptor_value_changed_count_);
1024
1025  // Write value. Writes to this descriptor will fail.
1026  desc_value[0] = 0x03;
1027  descriptor->WriteRemoteDescriptor(
1028      desc_value,
1029      base::Bind(&BluetoothGattChromeOSTest::SuccessCallback,
1030                 base::Unretained(this)),
1031      base::Bind(&BluetoothGattChromeOSTest::ErrorCallback,
1032                 base::Unretained(this)));
1033  EXPECT_EQ(1, success_callback_count_);
1034  EXPECT_EQ(1, error_callback_count_);
1035  EXPECT_TRUE(ValuesEqual(last_read_value_, descriptor->GetValue()));
1036  EXPECT_FALSE(ValuesEqual(desc_value, descriptor->GetValue()));
1037  EXPECT_EQ(0, observer.gatt_service_changed_count_);
1038  EXPECT_EQ(1, observer.gatt_descriptor_value_changed_count_);
1039
1040  // Read new value.
1041  descriptor->ReadRemoteDescriptor(
1042      base::Bind(&BluetoothGattChromeOSTest::ValueCallback,
1043                 base::Unretained(this)),
1044      base::Bind(&BluetoothGattChromeOSTest::ErrorCallback,
1045                 base::Unretained(this)));
1046  EXPECT_EQ(2, success_callback_count_);
1047  EXPECT_EQ(1, error_callback_count_);
1048  EXPECT_TRUE(ValuesEqual(last_read_value_, descriptor->GetValue()));
1049  EXPECT_FALSE(ValuesEqual(desc_value, descriptor->GetValue()));
1050  EXPECT_EQ(0, observer.gatt_service_changed_count_);
1051  EXPECT_EQ(2, observer.gatt_descriptor_value_changed_count_);
1052}
1053
1054TEST_F(BluetoothGattChromeOSTest, NotifySessions) {
1055  fake_bluetooth_device_client_->CreateDevice(
1056      dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
1057      dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
1058  BluetoothDevice* device =
1059      adapter_->GetDevice(FakeBluetoothDeviceClient::kLowEnergyAddress);
1060  ASSERT_TRUE(device);
1061
1062  TestObserver observer(adapter_);
1063
1064  // Expose the fake Heart Rate service. This will asynchronously expose
1065  // characteristics.
1066  fake_bluetooth_gatt_service_client_->ExposeHeartRateService(
1067      dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
1068  ASSERT_EQ(1, observer.gatt_service_added_count_);
1069
1070  BluetoothGattService* service =
1071      device->GetGattService(observer.last_gatt_service_id_);
1072
1073  EXPECT_EQ(0, observer.gatt_characteristic_value_changed_count_);
1074
1075  // Run the message loop so that the characteristics appear.
1076  base::MessageLoop::current()->Run();
1077
1078  BluetoothGattCharacteristic* characteristic = service->GetCharacteristic(
1079      fake_bluetooth_gatt_characteristic_client_->GetHeartRateMeasurementPath()
1080          .value());
1081  ASSERT_TRUE(characteristic);
1082  EXPECT_FALSE(characteristic->IsNotifying());
1083  EXPECT_TRUE(update_sessions_.empty());
1084
1085  // Request to start notifications.
1086  characteristic->StartNotifySession(
1087      base::Bind(&BluetoothGattChromeOSTest::NotifySessionCallback,
1088                 base::Unretained(this)),
1089      base::Bind(&BluetoothGattChromeOSTest::ErrorCallback,
1090                 base::Unretained(this)));
1091
1092  // The operation still hasn't completed but we should have received the first
1093  // notification.
1094  EXPECT_EQ(0, success_callback_count_);
1095  EXPECT_EQ(0, error_callback_count_);
1096  EXPECT_EQ(1, observer.gatt_characteristic_value_changed_count_);
1097  EXPECT_TRUE(update_sessions_.empty());
1098
1099  // Send a two more requests, which should get queued.
1100  characteristic->StartNotifySession(
1101      base::Bind(&BluetoothGattChromeOSTest::NotifySessionCallback,
1102                 base::Unretained(this)),
1103      base::Bind(&BluetoothGattChromeOSTest::ErrorCallback,
1104                 base::Unretained(this)));
1105  characteristic->StartNotifySession(
1106      base::Bind(&BluetoothGattChromeOSTest::NotifySessionCallback,
1107                 base::Unretained(this)),
1108      base::Bind(&BluetoothGattChromeOSTest::ErrorCallback,
1109                 base::Unretained(this)));
1110  EXPECT_EQ(0, success_callback_count_);
1111  EXPECT_EQ(0, error_callback_count_);
1112  EXPECT_EQ(1, observer.gatt_characteristic_value_changed_count_);
1113  EXPECT_TRUE(update_sessions_.empty());
1114  EXPECT_TRUE(characteristic->IsNotifying());
1115
1116  // Run the main loop. The initial call should complete. The queued call should
1117  // succeed immediately.
1118  base::MessageLoop::current()->Run();
1119
1120  EXPECT_EQ(3, success_callback_count_);
1121  EXPECT_EQ(0, error_callback_count_);
1122  EXPECT_EQ(1, observer.gatt_characteristic_value_changed_count_);
1123  EXPECT_EQ(3U, update_sessions_.size());
1124
1125  // Notifications should be getting sent regularly now.
1126  base::MessageLoop::current()->Run();
1127  EXPECT_GT(observer.gatt_characteristic_value_changed_count_, 1);
1128
1129  // Stop one of the sessions. The session should become inactive but the
1130  // characteristic should still be notifying.
1131  BluetoothGattNotifySession* session = update_sessions_[0];
1132  EXPECT_TRUE(session->IsActive());
1133  session->Stop(base::Bind(&BluetoothGattChromeOSTest::SuccessCallback,
1134                           base::Unretained(this)));
1135  EXPECT_EQ(4, success_callback_count_);
1136  EXPECT_EQ(0, error_callback_count_);
1137  EXPECT_FALSE(session->IsActive());
1138  EXPECT_EQ(characteristic->GetIdentifier(),
1139            session->GetCharacteristicIdentifier());
1140  EXPECT_TRUE(characteristic->IsNotifying());
1141
1142  // Delete another session. Characteristic should still be notifying.
1143  update_sessions_.pop_back();
1144  EXPECT_EQ(2U, update_sessions_.size());
1145  EXPECT_TRUE(characteristic->IsNotifying());
1146  EXPECT_FALSE(update_sessions_[0]->IsActive());
1147  EXPECT_TRUE(update_sessions_[1]->IsActive());
1148
1149  // Clear the last session.
1150  update_sessions_.clear();
1151  EXPECT_TRUE(update_sessions_.empty());
1152  EXPECT_FALSE(characteristic->IsNotifying());
1153
1154  success_callback_count_ = 0;
1155  observer.gatt_characteristic_value_changed_count_ = 0;
1156
1157  // Enable notifications again.
1158  characteristic->StartNotifySession(
1159      base::Bind(&BluetoothGattChromeOSTest::NotifySessionCallback,
1160                 base::Unretained(this)),
1161      base::Bind(&BluetoothGattChromeOSTest::ErrorCallback,
1162                 base::Unretained(this)));
1163  EXPECT_EQ(0, success_callback_count_);
1164  EXPECT_EQ(0, error_callback_count_);
1165  EXPECT_EQ(1, observer.gatt_characteristic_value_changed_count_);
1166  EXPECT_TRUE(update_sessions_.empty());
1167  EXPECT_TRUE(characteristic->IsNotifying());
1168
1169  // Run the message loop. Notifications should begin.
1170  base::MessageLoop::current()->Run();
1171
1172  EXPECT_EQ(1, success_callback_count_);
1173  EXPECT_EQ(0, error_callback_count_);
1174  EXPECT_EQ(1, observer.gatt_characteristic_value_changed_count_);
1175  EXPECT_EQ(1U, update_sessions_.size());
1176  EXPECT_TRUE(update_sessions_[0]->IsActive());
1177  EXPECT_TRUE(characteristic->IsNotifying());
1178
1179  // Check that notifications are happening.
1180  base::MessageLoop::current()->Run();
1181  EXPECT_GT(observer.gatt_characteristic_value_changed_count_, 1);
1182
1183  // Request another session. This should return immediately.
1184  characteristic->StartNotifySession(
1185      base::Bind(&BluetoothGattChromeOSTest::NotifySessionCallback,
1186                 base::Unretained(this)),
1187      base::Bind(&BluetoothGattChromeOSTest::ErrorCallback,
1188                 base::Unretained(this)));
1189  EXPECT_EQ(2, success_callback_count_);
1190  EXPECT_EQ(0, error_callback_count_);
1191  EXPECT_EQ(2U, update_sessions_.size());
1192  EXPECT_TRUE(update_sessions_[0]->IsActive());
1193  EXPECT_TRUE(update_sessions_[1]->IsActive());
1194  EXPECT_TRUE(characteristic->IsNotifying());
1195
1196  // Hide the characteristic. The sessions should become inactive.
1197  fake_bluetooth_gatt_characteristic_client_->HideHeartRateCharacteristics();
1198  EXPECT_EQ(2U, update_sessions_.size());
1199  EXPECT_FALSE(update_sessions_[0]->IsActive());
1200  EXPECT_FALSE(update_sessions_[1]->IsActive());
1201}
1202
1203TEST_F(BluetoothGattChromeOSTest, NotifySessionsMadeInactive) {
1204  fake_bluetooth_device_client_->CreateDevice(
1205      dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
1206      dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
1207  BluetoothDevice* device =
1208      adapter_->GetDevice(FakeBluetoothDeviceClient::kLowEnergyAddress);
1209  ASSERT_TRUE(device);
1210
1211  TestObserver observer(adapter_);
1212
1213  // Expose the fake Heart Rate service. This will asynchronously expose
1214  // characteristics.
1215  fake_bluetooth_gatt_service_client_->ExposeHeartRateService(
1216      dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
1217  ASSERT_EQ(1, observer.gatt_service_added_count_);
1218
1219  BluetoothGattService* service =
1220      device->GetGattService(observer.last_gatt_service_id_);
1221
1222  EXPECT_EQ(0, observer.gatt_characteristic_value_changed_count_);
1223
1224  // Run the message loop so that the characteristics appear.
1225  base::MessageLoop::current()->Run();
1226
1227  BluetoothGattCharacteristic* characteristic = service->GetCharacteristic(
1228      fake_bluetooth_gatt_characteristic_client_->GetHeartRateMeasurementPath()
1229          .value());
1230  ASSERT_TRUE(characteristic);
1231  EXPECT_FALSE(characteristic->IsNotifying());
1232  EXPECT_TRUE(update_sessions_.empty());
1233
1234  // Send several requests to start notifications.
1235  characteristic->StartNotifySession(
1236      base::Bind(&BluetoothGattChromeOSTest::NotifySessionCallback,
1237                 base::Unretained(this)),
1238      base::Bind(&BluetoothGattChromeOSTest::ErrorCallback,
1239                 base::Unretained(this)));
1240  characteristic->StartNotifySession(
1241      base::Bind(&BluetoothGattChromeOSTest::NotifySessionCallback,
1242                 base::Unretained(this)),
1243      base::Bind(&BluetoothGattChromeOSTest::ErrorCallback,
1244                 base::Unretained(this)));
1245  characteristic->StartNotifySession(
1246      base::Bind(&BluetoothGattChromeOSTest::NotifySessionCallback,
1247                 base::Unretained(this)),
1248      base::Bind(&BluetoothGattChromeOSTest::ErrorCallback,
1249                 base::Unretained(this)));
1250  characteristic->StartNotifySession(
1251      base::Bind(&BluetoothGattChromeOSTest::NotifySessionCallback,
1252                 base::Unretained(this)),
1253      base::Bind(&BluetoothGattChromeOSTest::ErrorCallback,
1254                 base::Unretained(this)));
1255
1256  // The operation still hasn't completed but we should have received the first
1257  // notification.
1258  EXPECT_EQ(0, success_callback_count_);
1259  EXPECT_EQ(0, error_callback_count_);
1260  EXPECT_EQ(1, observer.gatt_characteristic_value_changed_count_);
1261  EXPECT_TRUE(characteristic->IsNotifying());
1262  EXPECT_TRUE(update_sessions_.empty());
1263
1264  // Run the main loop. The initial call should complete. The queued calls
1265  // should succeed immediately.
1266  base::MessageLoop::current()->Run();
1267
1268  EXPECT_EQ(4, success_callback_count_);
1269  EXPECT_EQ(0, error_callback_count_);
1270  EXPECT_EQ(1, observer.gatt_characteristic_value_changed_count_);
1271  EXPECT_TRUE(characteristic->IsNotifying());
1272  EXPECT_EQ(4U, update_sessions_.size());
1273
1274  for (int i = 0; i < 4; i++)
1275    EXPECT_TRUE(update_sessions_[0]->IsActive());
1276
1277  // Stop notifications directly through the client. The sessions should get
1278  // marked as inactive.
1279  fake_bluetooth_gatt_characteristic_client_->StopNotify(
1280      fake_bluetooth_gatt_characteristic_client_->GetHeartRateMeasurementPath(),
1281      base::Bind(&BluetoothGattChromeOSTest::SuccessCallback,
1282                 base::Unretained(this)),
1283      base::Bind(&BluetoothGattChromeOSTest::DBusErrorCallback,
1284                 base::Unretained(this)));
1285  EXPECT_EQ(5, success_callback_count_);
1286  EXPECT_EQ(0, error_callback_count_);
1287  EXPECT_FALSE(characteristic->IsNotifying());
1288  EXPECT_EQ(4U, update_sessions_.size());
1289
1290  for (int i = 0; i < 4; i++)
1291    EXPECT_FALSE(update_sessions_[0]->IsActive());
1292
1293  // It should be possible to restart notifications and the call should reset
1294  // the session count and make a request through the client.
1295  update_sessions_.clear();
1296  success_callback_count_ = 0;
1297  observer.gatt_characteristic_value_changed_count_ = 0;
1298  characteristic->StartNotifySession(
1299      base::Bind(&BluetoothGattChromeOSTest::NotifySessionCallback,
1300                 base::Unretained(this)),
1301      base::Bind(&BluetoothGattChromeOSTest::ErrorCallback,
1302                 base::Unretained(this)));
1303
1304  EXPECT_EQ(0, success_callback_count_);
1305  EXPECT_EQ(0, error_callback_count_);
1306  EXPECT_EQ(1, observer.gatt_characteristic_value_changed_count_);
1307  EXPECT_TRUE(characteristic->IsNotifying());
1308  EXPECT_TRUE(update_sessions_.empty());
1309
1310  base::MessageLoop::current()->Run();
1311
1312  EXPECT_EQ(1, success_callback_count_);
1313  EXPECT_EQ(0, error_callback_count_);
1314  EXPECT_EQ(1, observer.gatt_characteristic_value_changed_count_);
1315  EXPECT_TRUE(characteristic->IsNotifying());
1316  EXPECT_EQ(1U, update_sessions_.size());
1317  EXPECT_TRUE(update_sessions_[0]->IsActive());
1318}
1319
1320}  // namespace chromeos
1321