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 "device/bluetooth/bluetooth_gatt_notify_session_chromeos.h" 6 7 #include "base/bind.h" 8 #include "base/logging.h" 9 #include "chromeos/dbus/dbus_thread_manager.h" 10 #include "device/bluetooth/bluetooth_adapter.h" 11 #include "device/bluetooth/bluetooth_device.h" 12 #include "device/bluetooth/bluetooth_gatt_service.h" 13 #include "device/bluetooth/bluetooth_remote_gatt_characteristic_chromeos.h" 14 15 namespace chromeos { 16 17 BluetoothGattNotifySessionChromeOS::BluetoothGattNotifySessionChromeOS( 18 scoped_refptr<device::BluetoothAdapter> adapter, 19 const std::string& device_address, 20 const std::string& service_identifier, 21 const std::string& characteristic_identifier, 22 const dbus::ObjectPath& characteristic_path) 23 : active_(true), 24 adapter_(adapter), 25 device_address_(device_address), 26 service_id_(service_identifier), 27 characteristic_id_(characteristic_identifier), 28 object_path_(characteristic_path) { 29 DCHECK(adapter_.get()); 30 DCHECK(!device_address_.empty()); 31 DCHECK(!service_id_.empty()); 32 DCHECK(!characteristic_id_.empty()); 33 DCHECK(object_path_.IsValid()); 34 35 DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()->AddObserver( 36 this); 37 } 38 39 BluetoothGattNotifySessionChromeOS::~BluetoothGattNotifySessionChromeOS() { 40 DBusThreadManager::Get() 41 ->GetBluetoothGattCharacteristicClient() 42 ->RemoveObserver(this); 43 Stop(base::Bind(&base::DoNothing)); 44 } 45 46 std::string BluetoothGattNotifySessionChromeOS::GetCharacteristicIdentifier() 47 const { 48 return characteristic_id_; 49 } 50 51 bool BluetoothGattNotifySessionChromeOS::IsActive() { 52 // Determine if the session is active. If |active_| is false, then it's 53 // been explicitly marked, so return false. 54 if (!active_) 55 return false; 56 57 // The fact that |active_| is true doesn't mean that the session is 58 // actually active, since the characteristic might have stopped sending 59 // notifications yet this method was called before we processed the 60 // observer event (e.g. because somebody else called this method in their 61 // BluetoothGattCharacteristicClient::Observer implementation, which was 62 // called before ours). Check the client to see if notifications are still 63 // being sent. 64 BluetoothGattCharacteristicClient::Properties* properties = 65 DBusThreadManager::Get() 66 ->GetBluetoothGattCharacteristicClient() 67 ->GetProperties(object_path_); 68 if (!properties || !properties->notifying.value()) 69 active_ = false; 70 71 return active_; 72 } 73 74 void BluetoothGattNotifySessionChromeOS::Stop(const base::Closure& callback) { 75 if (!active_) { 76 VLOG(1) << "Notify session already inactive."; 77 callback.Run(); 78 return; 79 } 80 81 // Mark this session as inactive no matter what. 82 active_ = false; 83 84 device::BluetoothDevice* device = adapter_->GetDevice(device_address_); 85 if (!device) 86 return; 87 88 device::BluetoothGattService* service = device->GetGattService(service_id_); 89 if (!service) 90 return; 91 92 BluetoothRemoteGattCharacteristicChromeOS* chrc = 93 static_cast<BluetoothRemoteGattCharacteristicChromeOS*>( 94 service->GetCharacteristic(characteristic_id_)); 95 if (!chrc) 96 return; 97 98 chrc->RemoveNotifySession(callback); 99 } 100 101 void BluetoothGattNotifySessionChromeOS::GattCharacteristicRemoved( 102 const dbus::ObjectPath& object_path) { 103 if (object_path != object_path_) 104 return; 105 106 active_ = false; 107 } 108 109 void BluetoothGattNotifySessionChromeOS::GattCharacteristicPropertyChanged( 110 const dbus::ObjectPath& object_path, 111 const std::string& property_name) { 112 if (object_path != object_path_) 113 return; 114 115 if (!active_) 116 return; 117 118 BluetoothGattCharacteristicClient::Properties* properties = 119 DBusThreadManager::Get() 120 ->GetBluetoothGattCharacteristicClient() 121 ->GetProperties(object_path_); 122 if (!properties) { 123 active_ = false; 124 return; 125 } 126 127 if (property_name == properties->notifying.name() && 128 !properties->notifying.value()) 129 active_ = false; 130 } 131 132 } // namespace chromeos 133