1c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// Copyright 2014 The Chromium Authors. All rights reserved.
2c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// found in the LICENSE file.
4c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
5c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "device/bluetooth/bluetooth_remote_gatt_service_chromeos.h"
6c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
7c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "base/logging.h"
8a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "base/strings/stringprintf.h"
9c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "chromeos/dbus/bluetooth_gatt_service_client.h"
10c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "chromeos/dbus/dbus_thread_manager.h"
11116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "device/bluetooth/bluetooth_adapter_chromeos.h"
125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "device/bluetooth/bluetooth_device_chromeos.h"
13a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "device/bluetooth/bluetooth_remote_gatt_characteristic_chromeos.h"
14010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "device/bluetooth/bluetooth_remote_gatt_descriptor_chromeos.h"
15c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
16c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochnamespace chromeos {
17c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
18c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochBluetoothRemoteGattServiceChromeOS::BluetoothRemoteGattServiceChromeOS(
19116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    BluetoothAdapterChromeOS* adapter,
20c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    BluetoothDeviceChromeOS* device,
21c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const dbus::ObjectPath& object_path)
22c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    : object_path_(object_path),
23116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      adapter_(adapter),
24c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      device_(device),
255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      discovery_complete_(false),
26c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      weak_ptr_factory_(this) {
27c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  VLOG(1) << "Creating remote GATT service with identifier: "
28c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          << object_path.value() << ", UUID: " << GetUUID().canonical_value();
29116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK(adapter_);
30116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
31c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DBusThreadManager::Get()->GetBluetoothGattServiceClient()->AddObserver(this);
32a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()->
33a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      AddObserver(this);
34a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
35a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // Add all known GATT characteristics.
36a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  const std::vector<dbus::ObjectPath>& gatt_chars =
37a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()->
38a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch          GetCharacteristics();
39a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  for (std::vector<dbus::ObjectPath>::const_iterator iter = gatt_chars.begin();
40a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch       iter != gatt_chars.end(); ++iter)
41a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    GattCharacteristicAdded(*iter);
42c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
43c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
44c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochBluetoothRemoteGattServiceChromeOS::~BluetoothRemoteGattServiceChromeOS() {
45c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DBusThreadManager::Get()->GetBluetoothGattServiceClient()->
46c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      RemoveObserver(this);
47a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()->
48a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      RemoveObserver(this);
49a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
50a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // Clean up all the characteristics. Copy the characteristics list here and
51a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // clear the original so that when we send GattCharacteristicRemoved(),
52a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // GetCharacteristics() returns no characteristics.
53a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  CharacteristicMap characteristics = characteristics_;
54a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  characteristics_.clear();
55a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  for (CharacteristicMap::iterator iter = characteristics.begin();
56a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch       iter != characteristics.end(); ++iter) {
575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    DCHECK(adapter_);
585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    adapter_->NotifyGattCharacteristicRemoved(iter->second);
595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
60a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    delete iter->second;
61a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
62a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
63a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
64c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochstd::string BluetoothRemoteGattServiceChromeOS::GetIdentifier() const {
65c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return object_path_.value();
66c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
67c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
68c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochdevice::BluetoothUUID BluetoothRemoteGattServiceChromeOS::GetUUID() const {
69c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  BluetoothGattServiceClient::Properties* properties =
70c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      DBusThreadManager::Get()->GetBluetoothGattServiceClient()->
71c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          GetProperties(object_path_);
72c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK(properties);
73c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return device::BluetoothUUID(properties->uuid.value());
74c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
75c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
76c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochbool BluetoothRemoteGattServiceChromeOS::IsLocal() const {
77c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return false;
78c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
79c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
80c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochbool BluetoothRemoteGattServiceChromeOS::IsPrimary() const {
81c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  BluetoothGattServiceClient::Properties* properties =
82c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      DBusThreadManager::Get()->GetBluetoothGattServiceClient()->
83c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          GetProperties(object_path_);
84c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK(properties);
85c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return properties->primary.value();
86c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
87c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liudevice::BluetoothDevice* BluetoothRemoteGattServiceChromeOS::GetDevice() const {
895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return device_;
905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
92a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochstd::vector<device::BluetoothGattCharacteristic*>
93c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochBluetoothRemoteGattServiceChromeOS::GetCharacteristics() const {
94a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  std::vector<device::BluetoothGattCharacteristic*> characteristics;
95a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  for (CharacteristicMap::const_iterator iter = characteristics_.begin();
96a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch       iter != characteristics_.end(); ++iter) {
97a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    characteristics.push_back(iter->second);
98a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
99a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  return characteristics;
100c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
101c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
102a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochstd::vector<device::BluetoothGattService*>
103c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochBluetoothRemoteGattServiceChromeOS::GetIncludedServices() const {
104a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // TODO(armansito): Return the actual included services here.
105a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  return std::vector<device::BluetoothGattService*>();
106c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
107c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
108a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochdevice::BluetoothGattCharacteristic*
109a02191e04bc25c4935f804f2c080ae28663d096dBen MurdochBluetoothRemoteGattServiceChromeOS::GetCharacteristic(
1105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const std::string& identifier) const {
111a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  CharacteristicMap::const_iterator iter =
112a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      characteristics_.find(dbus::ObjectPath(identifier));
113a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (iter == characteristics_.end())
114a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    return NULL;
115a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  return iter->second;
116c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
117c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
118c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochbool BluetoothRemoteGattServiceChromeOS::AddCharacteristic(
119c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    device::BluetoothGattCharacteristic* characteristic) {
120c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  VLOG(1) << "Characteristics cannot be added to a remote GATT service.";
121c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return false;
122c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
123c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
124c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochbool BluetoothRemoteGattServiceChromeOS::AddIncludedService(
125c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    device::BluetoothGattService* service) {
126c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  VLOG(1) << "Included services cannot be added to a remote GATT service.";
127c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return false;
128c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
129c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
130c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid BluetoothRemoteGattServiceChromeOS::Register(
131c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const base::Closure& callback,
132c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const ErrorCallback& error_callback) {
133c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  VLOG(1) << "A remote GATT service cannot be registered.";
134c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  error_callback.Run();
135c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
136c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
137c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid BluetoothRemoteGattServiceChromeOS::Unregister(
138c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const base::Closure& callback,
139c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const ErrorCallback& error_callback) {
140c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  VLOG(1) << "A remote GATT service cannot be unregistered.";
141c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  error_callback.Run();
142c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
143c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)BluetoothAdapterChromeOS*
145116680a4aac90f2aa7413d9095a592090648e557Ben MurdochBluetoothRemoteGattServiceChromeOS::GetAdapter() const {
146116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return adapter_;
147116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
148116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
149a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid BluetoothRemoteGattServiceChromeOS::NotifyServiceChanged() {
1505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Don't send service changed unless we know that all characteristics have
1515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // already been discovered. This is to prevent spammy events before sending
1525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // out the first Gatt
1535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!discovery_complete_)
1545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
1555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(adapter_);
1575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  adapter_->NotifyGattServiceChanged(this);
158a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
159a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
160f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void BluetoothRemoteGattServiceChromeOS::NotifyCharacteristicValueChanged(
161f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    BluetoothRemoteGattCharacteristicChromeOS* characteristic,
162f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const std::vector<uint8>& value) {
163f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DCHECK(characteristic->GetService() == this);
1645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(adapter_);
1655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  adapter_->NotifyGattCharacteristicValueChanged(characteristic, value);
166f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
167f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
168010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void BluetoothRemoteGattServiceChromeOS::NotifyDescriptorAddedOrRemoved(
169010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    BluetoothRemoteGattCharacteristicChromeOS* characteristic,
170010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    BluetoothRemoteGattDescriptorChromeOS* descriptor,
171010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    bool added) {
172010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(characteristic->GetService() == this);
173010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(descriptor->GetCharacteristic() == characteristic);
1745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(adapter_);
1755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
176010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (added) {
1775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    adapter_->NotifyGattDescriptorAdded(descriptor);
178010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
179010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
1805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  adapter_->NotifyGattDescriptorRemoved(descriptor);
182010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
183010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
184010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void BluetoothRemoteGattServiceChromeOS::NotifyDescriptorValueChanged(
185010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    BluetoothRemoteGattCharacteristicChromeOS* characteristic,
186010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    BluetoothRemoteGattDescriptorChromeOS* descriptor,
187010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const std::vector<uint8>& value) {
188010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(characteristic->GetService() == this);
189010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(descriptor->GetCharacteristic() == characteristic);
1905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(adapter_);
1915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  adapter_->NotifyGattDescriptorValueChanged(descriptor, value);
192010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
193010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
194c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid BluetoothRemoteGattServiceChromeOS::GattServicePropertyChanged(
195c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const dbus::ObjectPath& object_path,
196c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const std::string& property_name){
19746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (object_path != object_path_)
19846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return;
19946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
2005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  VLOG(1) << "Service property changed: \"" << property_name << "\", "
2015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          << object_path.value();
2025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  BluetoothGattServiceClient::Properties* properties =
2035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      DBusThreadManager::Get()->GetBluetoothGattServiceClient()->GetProperties(
2045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          object_path);
2055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(properties);
2065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (property_name != properties->characteristics.name()) {
2085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    NotifyServiceChanged();
2095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
2105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
2115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (discovery_complete_)
2135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
2145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  VLOG(1) << "All characteristics were discovered for service: "
2165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          << object_path.value();
2175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  discovery_complete_ = true;
2185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(adapter_);
2195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  adapter_->NotifyGattDiscoveryComplete(this);
220a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
221a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
222a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid BluetoothRemoteGattServiceChromeOS::GattCharacteristicAdded(
223a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    const dbus::ObjectPath& object_path) {
224a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (characteristics_.find(object_path) != characteristics_.end()) {
225a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    VLOG(1) << "Remote GATT characteristic already exists: "
226a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch            << object_path.value();
227a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    return;
228a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
229a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
230a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  BluetoothGattCharacteristicClient::Properties* properties =
231a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()->
232a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch          GetProperties(object_path);
233a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  DCHECK(properties);
234a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (properties->service.value() != object_path_) {
235a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    VLOG(2) << "Remote GATT characteristic does not belong to this service.";
236a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    return;
237a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
238a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
239a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  VLOG(1) << "Adding new remote GATT characteristic for GATT service: "
240a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch          << GetIdentifier() << ", UUID: " << GetUUID().canonical_value();
241a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
242a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  BluetoothRemoteGattCharacteristicChromeOS* characteristic =
243a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      new BluetoothRemoteGattCharacteristicChromeOS(this, object_path);
244a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  characteristics_[object_path] = characteristic;
245a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  DCHECK(characteristic->GetIdentifier() == object_path.value());
246a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  DCHECK(characteristic->GetUUID().IsValid());
247a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
2485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(adapter_);
2495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  adapter_->NotifyGattCharacteristicAdded(characteristic);
250a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
251a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
252a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid BluetoothRemoteGattServiceChromeOS::GattCharacteristicRemoved(
253a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    const dbus::ObjectPath& object_path) {
254a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  CharacteristicMap::iterator iter = characteristics_.find(object_path);
255a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (iter == characteristics_.end()) {
256a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    VLOG(2) << "Unknown GATT characteristic removed: " << object_path.value();
257a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    return;
258a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
259a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
260a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  VLOG(1) << "Removing remote GATT characteristic from service: "
261a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch          << GetIdentifier() << ", UUID: " << GetUUID().canonical_value();
262a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
263a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  BluetoothRemoteGattCharacteristicChromeOS* characteristic = iter->second;
264a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  DCHECK(characteristic->object_path() == object_path);
265a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  characteristics_.erase(iter);
266a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
2675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(adapter_);
2685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  adapter_->NotifyGattCharacteristicRemoved(characteristic);
269a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
270a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  delete characteristic;
271a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
272a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
2736d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)void BluetoothRemoteGattServiceChromeOS::GattCharacteristicPropertyChanged(
2746d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    const dbus::ObjectPath& object_path,
2756d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    const std::string& property_name) {
2766d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (characteristics_.find(object_path) == characteristics_.end()) {
2775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    VLOG(3) << "Properties of unknown characteristic changed";
2786d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    return;
2796d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  }
2806d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
2816d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  // We may receive a property changed event in certain cases, e.g. when the
2826d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  // characteristic "Flags" property has been updated with values from the
2836d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  // "Characteristic Extended Properties" descriptor. In this case, kick off
2846d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  // a service changed observer event to let observers refresh the
2856d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  // characteristics.
2866d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  BluetoothGattCharacteristicClient::Properties* properties =
2876d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()->
2886d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)          GetProperties(object_path);
2896d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  DCHECK(properties);
2906d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (property_name != properties->flags.name())
2916d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    return;
2926d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
2936d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  NotifyServiceChanged();
2946d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)}
2956d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
296c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}  // namespace chromeos
297