1e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch// Copyright 2014 The Chromium Authors. All rights reserved. 2e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch// found in the LICENSE file. 4e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 5e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "chromeos/dbus/bluetooth_gatt_characteristic_service_provider.h" 6e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 7e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "base/bind.h" 8e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "base/logging.h" 9e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "base/memory/weak_ptr.h" 10e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "base/strings/string_util.h" 11e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "base/threading/platform_thread.h" 126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "chromeos/dbus/dbus_thread_manager.h" 13e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "chromeos/dbus/fake_bluetooth_gatt_characteristic_service_provider.h" 14e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "dbus/exported_object.h" 15e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "dbus/message.h" 16e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "third_party/cros_system_api/dbus/service_constants.h" 17e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 18e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochnamespace chromeos { 19e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochnamespace { 20e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochconst char kErrorInvalidArgs[] = 21e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch "org.freedesktop.DBus.Error.InvalidArgs"; 22e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochconst char kErrorPropertyReadOnly[] = 23e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch "org.freedesktop.DBus.Error.PropertyReadOnly"; 24e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochconst char kErrorFailed[] = 25e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch "org.freedesktop.DBus.Error.Failed"; 26e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch} // namespace 27e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 28e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch// The BluetoothGattCharacteristicServiceProvider implementation used in 29e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch// production. 30e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochclass BluetoothGattCharacteristicServiceProviderImpl 31e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch : public BluetoothGattCharacteristicServiceProvider { 32e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch public: 33e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch BluetoothGattCharacteristicServiceProviderImpl( 34e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::Bus* bus, 35e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch const dbus::ObjectPath& object_path, 36e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch Delegate* delegate, 37e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch const std::string& uuid, 38e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch const std::vector<std::string>& flags, 39e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch const std::vector<std::string>& permissions, 40e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch const dbus::ObjectPath& service_path) 41e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch : origin_thread_id_(base::PlatformThread::CurrentId()), 42e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch uuid_(uuid), 43e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch bus_(bus), 44e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch delegate_(delegate), 45e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch object_path_(object_path), 46e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch service_path_(service_path), 47e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch weak_ptr_factory_(this) { 48e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch VLOG(1) << "Created Bluetooth GATT characteristic: " << object_path.value() 49e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch << " UUID: " << uuid; 50e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch DCHECK(bus_); 51e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch DCHECK(delegate_); 52e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch DCHECK(!uuid_.empty()); 53e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch DCHECK(object_path_.IsValid()); 54e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch DCHECK(service_path_.IsValid()); 55e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch DCHECK(StartsWithASCII( 56e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch object_path_.value(), service_path_.value() + "/", true)); 57e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 58e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch exported_object_ = bus_->GetExportedObject(object_path_); 59e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 60e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch exported_object_->ExportMethod( 61e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::kDBusPropertiesInterface, 62e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::kDBusPropertiesGet, 63e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::Get, 64e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch weak_ptr_factory_.GetWeakPtr()), 65e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::OnExported, 66e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch weak_ptr_factory_.GetWeakPtr())); 67e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 68e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch exported_object_->ExportMethod( 69e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::kDBusPropertiesInterface, 70e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::kDBusPropertiesSet, 71e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::Set, 72e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch weak_ptr_factory_.GetWeakPtr()), 73e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::OnExported, 74e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch weak_ptr_factory_.GetWeakPtr())); 75e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 76e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch exported_object_->ExportMethod( 77e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::kDBusPropertiesInterface, 78e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::kDBusPropertiesGetAll, 79e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::GetAll, 80e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch weak_ptr_factory_.GetWeakPtr()), 81e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::OnExported, 82e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch weak_ptr_factory_.GetWeakPtr())); 83e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 84e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 85e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch virtual ~BluetoothGattCharacteristicServiceProviderImpl() { 86e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch VLOG(1) << "Cleaning up Bluetooth GATT characteristic: " 87e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch << object_path_.value(); 88e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch bus_->UnregisterExportedObject(object_path_); 89e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 90e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 91e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // BluetoothGattCharacteristicServiceProvider override. 92e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch virtual void SendValueChanged(const std::vector<uint8>& value) OVERRIDE { 93e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch VLOG(2) << "Emitting a PropertiesChanged signal for characteristic value."; 94e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::Signal signal( 95e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::kDBusPropertiesInterface, 96e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::kDBusPropertiesChangedSignal); 97e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::MessageWriter writer(&signal); 98e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::MessageWriter array_writer(NULL); 99e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::MessageWriter dict_entry_writer(NULL); 100e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::MessageWriter variant_writer(NULL); 101e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 102e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // interface_name 103e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch writer.AppendString( 104e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface); 105e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 106e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // changed_properties 107e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch writer.OpenArray("{sv}", &array_writer); 108e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch array_writer.OpenDictEntry(&dict_entry_writer); 109e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dict_entry_writer.AppendString( 110e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch bluetooth_gatt_characteristic::kValueProperty); 111e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dict_entry_writer.OpenVariant("ay", &variant_writer); 112e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch variant_writer.AppendArrayOfBytes(value.data(), value.size()); 113e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dict_entry_writer.CloseContainer(&variant_writer); 114e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch array_writer.CloseContainer(&dict_entry_writer); 115e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch writer.CloseContainer(&array_writer); 116e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 117e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // invalidated_properties. 118e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch writer.OpenArray("s", &array_writer); 119e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch writer.CloseContainer(&array_writer); 120e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 121e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch exported_object_->SendSignal(&signal); 122e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 123e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 124e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch private: 125e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // Returns true if the current thread is on the origin thread. 126e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch bool OnOriginThread() { 127e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch return base::PlatformThread::CurrentId() == origin_thread_id_; 128e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 129e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 130e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // Called by dbus:: when the Bluetooth daemon fetches a single property of 131e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // the characteristic. 132e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch void Get(dbus::MethodCall* method_call, 133e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::ExportedObject::ResponseSender response_sender) { 134e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch VLOG(2) << "BluetoothGattCharacteristicServiceProvider::Get: " 135e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch << object_path_.value(); 136e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch DCHECK(OnOriginThread()); 137e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 138e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::MessageReader reader(method_call); 139e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 140e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch std::string interface_name; 141e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch std::string property_name; 142e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch if (!reader.PopString(&interface_name) || 143e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch !reader.PopString(&property_name) || 144e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch reader.HasMoreData()) { 145e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch scoped_ptr<dbus::ErrorResponse> error_response = 146e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::ErrorResponse::FromMethodCall( 147e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch method_call, kErrorInvalidArgs, "Expected 'ss'."); 148e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch response_sender.Run(error_response.PassAs<dbus::Response>()); 149e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch return; 150e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 151e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 152e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // Only the GATT characteristic interface is supported. 153e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch if (interface_name != 154e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface) { 155e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch scoped_ptr<dbus::ErrorResponse> error_response = 156e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::ErrorResponse::FromMethodCall( 157e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch method_call, kErrorInvalidArgs, 158e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch "No such interface: '" + interface_name + "'."); 159e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch response_sender.Run(error_response.PassAs<dbus::Response>()); 160e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch return; 161e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 162e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 163e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // If getting the "Value" property, obtain the value from the delegate. 164e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch if (property_name == bluetooth_gatt_characteristic::kValueProperty) { 165e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch DCHECK(delegate_); 166e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch delegate_->GetCharacteristicValue( 167e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::OnGet, 168e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch weak_ptr_factory_.GetWeakPtr(), 169e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch method_call, response_sender), 170e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::OnFailure, 171e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch weak_ptr_factory_.GetWeakPtr(), 172e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch method_call, response_sender)); 173e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch return; 174e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 175e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 176e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch scoped_ptr<dbus::Response> response = 177e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::Response::FromMethodCall(method_call); 178e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::MessageWriter writer(response.get()); 179e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::MessageWriter variant_writer(NULL); 180e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 181e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // TODO(armansito): Process the "Flags" and "Permissions" properties below. 182e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch if (property_name == bluetooth_gatt_characteristic::kUUIDProperty) { 183e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch writer.OpenVariant("s", &variant_writer); 184e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch variant_writer.AppendString(uuid_); 185e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch writer.CloseContainer(&variant_writer); 186e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } else if (property_name == 187e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch bluetooth_gatt_characteristic::kServiceProperty) { 188e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch writer.OpenVariant("o", &variant_writer); 189e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch variant_writer.AppendObjectPath(service_path_); 190e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch writer.CloseContainer(&variant_writer); 191e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } else { 192e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch response = dbus::ErrorResponse::FromMethodCall( 193e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch method_call, kErrorInvalidArgs, 194e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch "No such property: '" + property_name + "'.") 195e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch .PassAs<dbus::Response>(); 196e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 197e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 198e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch response_sender.Run(response.Pass()); 199e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 200e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 201e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // Called by dbus:: when the Bluetooth daemon sets a single property of the 202e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // characteristic. 203e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch void Set(dbus::MethodCall* method_call, 204e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::ExportedObject::ResponseSender response_sender) { 205e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch VLOG(2) << "BluetoothGattCharacteristicServiceProvider::Set: " 206e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch << object_path_.value(); 207e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch DCHECK(OnOriginThread()); 208e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 209e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::MessageReader reader(method_call); 210e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 211e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch std::string interface_name; 212e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch std::string property_name; 213e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::MessageReader variant_reader(NULL); 214e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch if (!reader.PopString(&interface_name) || 215e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch !reader.PopString(&property_name) || 216e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch !reader.PopVariant(&variant_reader) || 217e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch reader.HasMoreData()) { 218e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch scoped_ptr<dbus::ErrorResponse> error_response = 219e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::ErrorResponse::FromMethodCall( 220e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch method_call, kErrorInvalidArgs, "Expected 'ssv'."); 221e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch response_sender.Run(error_response.PassAs<dbus::Response>()); 222e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch return; 223e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 224e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 225e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // Only the GATT characteristic interface is allowed. 226e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch if (interface_name != 227e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface) { 228e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch scoped_ptr<dbus::ErrorResponse> error_response = 229e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::ErrorResponse::FromMethodCall( 230e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch method_call, kErrorInvalidArgs, 231e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch "No such interface: '" + interface_name + "'."); 232e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch response_sender.Run(error_response.PassAs<dbus::Response>()); 233e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch return; 234e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 235e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 236e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // Only the "Value" property is writeable. 237e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch if (property_name != bluetooth_gatt_characteristic::kValueProperty) { 238e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch std::string error_name; 239e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch std::string error_message; 240e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch if (property_name == bluetooth_gatt_characteristic::kUUIDProperty || 241e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch property_name == bluetooth_gatt_characteristic::kServiceProperty) { 242e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch error_name = kErrorPropertyReadOnly; 243e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch error_message = "Read-only property: '" + property_name + "'."; 244e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } else { 245e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch error_name = kErrorInvalidArgs; 246e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch error_message = "No such property: '" + property_name + "'."; 247e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 248e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch scoped_ptr<dbus::ErrorResponse> error_response = 249e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::ErrorResponse::FromMethodCall( 250e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch method_call, error_name, error_message); 251e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch response_sender.Run(error_response.PassAs<dbus::Response>()); 252e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch return; 253e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 254e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 255e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // Obtain the value. 256e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch const uint8* bytes = NULL; 257e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch size_t length = 0; 258e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch if (!variant_reader.PopArrayOfBytes(&bytes, &length)) { 259e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch scoped_ptr<dbus::ErrorResponse> error_response = 260e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::ErrorResponse::FromMethodCall( 261e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch method_call, kErrorInvalidArgs, 262e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch "Property '" + property_name + "' has type 'ay'."); 263e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch response_sender.Run(error_response.PassAs<dbus::Response>()); 264e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch return; 265e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 266e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 267e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // Pass the set request onto the delegate. 268e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch std::vector<uint8> value(bytes, bytes + length); 269e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch DCHECK(delegate_); 270e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch delegate_->SetCharacteristicValue( 271e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch value, 272e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::OnSet, 273e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch weak_ptr_factory_.GetWeakPtr(), 274e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch method_call, response_sender), 275e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::OnFailure, 276e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch weak_ptr_factory_.GetWeakPtr(), 277e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch method_call, response_sender)); 278e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 279e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 280e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // Called by dbus:: when the Bluetooth daemon fetches all properties of the 281e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // characteristic. 282e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch void GetAll(dbus::MethodCall* method_call, 283e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::ExportedObject::ResponseSender response_sender) { 284e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch VLOG(2) << "BluetoothGattCharacteristicServiceProvider::GetAll: " 285e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch << object_path_.value(); 286e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch DCHECK(OnOriginThread()); 287e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 288e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::MessageReader reader(method_call); 289e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 290e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch std::string interface_name; 291e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch if (!reader.PopString(&interface_name) || reader.HasMoreData()) { 292e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch scoped_ptr<dbus::ErrorResponse> error_response = 293e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::ErrorResponse::FromMethodCall( 294e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch method_call, kErrorInvalidArgs, "Expected 's'."); 295e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch response_sender.Run(error_response.PassAs<dbus::Response>()); 296e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch return; 297e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 298e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 299e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // Only the GATT characteristic interface is supported. 300e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch if (interface_name != 301e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface) { 302e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch scoped_ptr<dbus::ErrorResponse> error_response = 303e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::ErrorResponse::FromMethodCall( 304e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch method_call, kErrorInvalidArgs, 305e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch "No such interface: '" + interface_name + "'."); 306e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch response_sender.Run(error_response.PassAs<dbus::Response>()); 307e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch return; 308e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 309e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 310e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // Try to obtain the value from the delegate. We will construct the 311e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // response in the success callback. 312e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch DCHECK(delegate_); 313e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch delegate_->GetCharacteristicValue( 314e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::OnGetAll, 315e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch weak_ptr_factory_.GetWeakPtr(), 316e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch method_call, response_sender), 317e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::OnFailure, 318e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch weak_ptr_factory_.GetWeakPtr(), 319e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch method_call, response_sender)); 320e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 321e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 322e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // Called by dbus:: when a method is exported. 323e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch void OnExported(const std::string& interface_name, 324e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch const std::string& method_name, 325e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch bool success) { 326e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch LOG_IF(WARNING, !success) << "Failed to export " 327e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch << interface_name << "." << method_name; 328e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 329e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 330e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // Called by the Delegate in response to a method to call to get all 331e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // properties, in which the delegate has successfully returned the 332e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // characteristic value. 333e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch void OnGetAll(dbus::MethodCall* method_call, 334e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::ExportedObject::ResponseSender response_sender, 335e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch const std::vector<uint8>& value) { 336e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch VLOG(2) << "Characteristic value obtained from delegate. Responding to " 337e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch << "GetAll."; 338e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 339e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch scoped_ptr<dbus::Response> response = 340e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::Response::FromMethodCall(method_call); 341e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::MessageWriter writer(response.get()); 342e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::MessageWriter array_writer(NULL); 343e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::MessageWriter dict_entry_writer(NULL); 344e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::MessageWriter variant_writer(NULL); 345e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 346e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch writer.OpenArray("{sv}", &array_writer); 347e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 348e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch array_writer.OpenDictEntry(&dict_entry_writer); 349e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dict_entry_writer.AppendString( 350e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch bluetooth_gatt_characteristic::kUUIDProperty); 351e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dict_entry_writer.AppendVariantOfString(uuid_); 352e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch array_writer.CloseContainer(&dict_entry_writer); 353e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 354e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch array_writer.OpenDictEntry(&dict_entry_writer); 355e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dict_entry_writer.AppendString( 356e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch bluetooth_gatt_characteristic::kServiceProperty); 357e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dict_entry_writer.AppendVariantOfObjectPath(service_path_); 358e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch array_writer.CloseContainer(&dict_entry_writer); 359e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 360e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch array_writer.OpenDictEntry(&dict_entry_writer); 361e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dict_entry_writer.AppendString( 362e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch bluetooth_gatt_characteristic::kValueProperty); 363e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dict_entry_writer.OpenVariant("ay", &variant_writer); 364e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch variant_writer.AppendArrayOfBytes(value.data(), value.size()); 365e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dict_entry_writer.CloseContainer(&variant_writer); 366e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch array_writer.CloseContainer(&dict_entry_writer); 367e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 368e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // TODO(armansito): Process Flags & Permissions properties. 369e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 370e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch writer.CloseContainer(&array_writer); 371e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 372e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch response_sender.Run(response.Pass()); 373e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 374e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 375e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // Called by the Delegate in response to a successful method call to get the 376e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // characteristic value. 377e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch void OnGet(dbus::MethodCall* method_call, 378e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::ExportedObject::ResponseSender response_sender, 379e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch const std::vector<uint8>& value) { 380e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch VLOG(2) << "Returning characteristic value obtained from delegate."; 381e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch scoped_ptr<dbus::Response> response = 382e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::Response::FromMethodCall(method_call); 383e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::MessageWriter writer(response.get()); 384e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::MessageWriter variant_writer(NULL); 385e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 386e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch writer.OpenVariant("ay", &variant_writer); 387e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch variant_writer.AppendArrayOfBytes(value.data(), value.size()); 388e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch writer.CloseContainer(&variant_writer); 389e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 390e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch response_sender.Run(response.Pass()); 391e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 392e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 393e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // Called by the Delegate in response to a successful method call to set the 394e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // characteristic value. 395e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch void OnSet(dbus::MethodCall* method_call, 396e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::ExportedObject::ResponseSender response_sender) { 397e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch VLOG(2) << "Successfully set characteristic value. Return success."; 398e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch response_sender.Run(dbus::Response::FromMethodCall(method_call)); 399e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 400e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 401e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // Called by the Delegate in response to a failed method call to get or set 402e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // the characteristic value. 403e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch void OnFailure(dbus::MethodCall* method_call, 404e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::ExportedObject::ResponseSender response_sender) { 405e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch VLOG(2) << "Failed to get/set characteristic value. Report error."; 406e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch scoped_ptr<dbus::ErrorResponse> error_response = 407e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::ErrorResponse::FromMethodCall( 408e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch method_call, kErrorFailed, 409e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch "Failed to get/set characteristic value."); 410e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch response_sender.Run(error_response.PassAs<dbus::Response>()); 411e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 412e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 413e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // Origin thread (i.e. the UI thread in production). 414e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch base::PlatformThreadId origin_thread_id_; 415e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 416e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // 128-bit characteristic UUID of this object. 417e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch std::string uuid_; 418e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 419e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // D-Bus bus object is exported on, not owned by this object and must 420e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // outlive it. 421e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::Bus* bus_; 422e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 423e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // Incoming methods to get and set the "Value" property are passed on to the 424e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // delegate and callbacks passed to generate a reply. |delegate_| is generally 425e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // the object that owns this one and must outlive it. 426e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch Delegate* delegate_; 427e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 428e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // D-Bus object path of object we are exporting, kept so we can unregister 429e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // again in our destructor. 430e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::ObjectPath object_path_; 431e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 432e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // Object path of the GATT service that the exported characteristic belongs 433e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // to. 434e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::ObjectPath service_path_; 435e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 436e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // D-Bus object we are exporting, owned by this object. 437e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch scoped_refptr<dbus::ExportedObject> exported_object_; 438e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 439e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // Weak pointer factory for generating 'this' pointers that might live longer 440e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // than we do. 441e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // Note: This should remain the last member so it'll be destroyed and 442e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // invalidate its weak pointers before any other members are destroyed. 443e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch base::WeakPtrFactory<BluetoothGattCharacteristicServiceProviderImpl> 444e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch weak_ptr_factory_; 445e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 446e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch DISALLOW_COPY_AND_ASSIGN(BluetoothGattCharacteristicServiceProviderImpl); 447e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}; 448e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 449e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen MurdochBluetoothGattCharacteristicServiceProvider:: 450e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch BluetoothGattCharacteristicServiceProvider() { 451e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch} 452e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 453e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen MurdochBluetoothGattCharacteristicServiceProvider:: 454e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch ~BluetoothGattCharacteristicServiceProvider() { 455e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch} 456e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 457e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch// static 458e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen MurdochBluetoothGattCharacteristicServiceProvider* 459e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen MurdochBluetoothGattCharacteristicServiceProvider::Create( 460e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::Bus* bus, 461e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch const dbus::ObjectPath& object_path, 462e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch Delegate* delegate, 463e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch const std::string& uuid, 464e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch const std::vector<std::string>& flags, 465e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch const std::vector<std::string>& permissions, 466e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch const dbus::ObjectPath& service_path) { 4671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!DBusThreadManager::Get()->IsUsingStub(DBusClientBundle::BLUETOOTH)) { 468e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch return new BluetoothGattCharacteristicServiceProviderImpl( 469e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch bus, object_path, delegate, uuid, flags, permissions, service_path); 470e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 471e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch return new FakeBluetoothGattCharacteristicServiceProvider( 472e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch object_path, delegate, uuid, flags, permissions, service_path); 473e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch} 474e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 475e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch} // namespace chromeos 476