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_service_service_provider.h" 6e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 7e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "base/bind.h" 8e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "base/logging.h" 9e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "base/memory/ref_counted.h" 10e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "base/memory/weak_ptr.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_service_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 Murdoch} // namespace 25e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 26e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch// The BluetoothGattServiceServiceProvider implementation used in production. 27e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochclass BluetoothGattServiceServiceProviderImpl 28e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch : public BluetoothGattServiceServiceProvider { 29e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch public: 30e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch BluetoothGattServiceServiceProviderImpl( 31e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::Bus* bus, 32e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch const dbus::ObjectPath& object_path, 33e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch const std::string& uuid, 34e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch const std::vector<dbus::ObjectPath>& includes) 35e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch : origin_thread_id_(base::PlatformThread::CurrentId()), 36e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch uuid_(uuid), 37e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch includes_(includes), 38e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch bus_(bus), 39e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch object_path_(object_path), 40e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch weak_ptr_factory_(this) { 41e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch VLOG(1) << "Creating Bluetooth GATT service: " << object_path_.value() 42e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch << " UUID: " << uuid; 43e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch DCHECK(!uuid_.empty()); 44e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch DCHECK(object_path_.IsValid()); 45e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch DCHECK(bus_); 46e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 47e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch exported_object_ = bus_->GetExportedObject(object_path_); 48e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 49e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch exported_object_->ExportMethod( 50e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::kDBusPropertiesInterface, 51e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::kDBusPropertiesGet, 52e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch base::Bind(&BluetoothGattServiceServiceProviderImpl::Get, 53e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch weak_ptr_factory_.GetWeakPtr()), 54e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch base::Bind(&BluetoothGattServiceServiceProviderImpl::OnExported, 55e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch weak_ptr_factory_.GetWeakPtr())); 56e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 57e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch exported_object_->ExportMethod( 58e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::kDBusPropertiesInterface, 59e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::kDBusPropertiesSet, 60e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch base::Bind(&BluetoothGattServiceServiceProviderImpl::Set, 61e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch weak_ptr_factory_.GetWeakPtr()), 62e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch base::Bind(&BluetoothGattServiceServiceProviderImpl::OnExported, 63e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch weak_ptr_factory_.GetWeakPtr())); 64e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 65e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch exported_object_->ExportMethod( 66e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::kDBusPropertiesInterface, 67e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::kDBusPropertiesGetAll, 68e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch base::Bind(&BluetoothGattServiceServiceProviderImpl::GetAll, 69e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch weak_ptr_factory_.GetWeakPtr()), 70e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch base::Bind(&BluetoothGattServiceServiceProviderImpl::OnExported, 71e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch weak_ptr_factory_.GetWeakPtr())); 72e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 73e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 74e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch virtual ~BluetoothGattServiceServiceProviderImpl() { 75e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch VLOG(1) << "Cleaning up Bluetooth GATT service: " << object_path_.value(); 76e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch bus_->UnregisterExportedObject(object_path_); 77e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 78e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 79e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch private: 80e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // Returns true if the current thread is on the origin thread. 81e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch bool OnOriginThread() { 82e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch return base::PlatformThread::CurrentId() == origin_thread_id_; 83e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 84e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 85e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // Called by dbus:: when the Bluetooth daemon fetches a single property of 86e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // the service. 87e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch void Get(dbus::MethodCall* method_call, 88e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::ExportedObject::ResponseSender response_sender) { 89e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch VLOG(2) << "BluetoothGattServiceServiceProvider::Get: " 90e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch << object_path_.value(); 91e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch DCHECK(OnOriginThread()); 92e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 93e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::MessageReader reader(method_call); 94e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 95e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch std::string interface_name; 96e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch std::string property_name; 97e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch if (!reader.PopString(&interface_name) || 98e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch !reader.PopString(&property_name) || 99e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch reader.HasMoreData()) { 100e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch scoped_ptr<dbus::ErrorResponse> error_response = 101e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::ErrorResponse::FromMethodCall( 102e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch method_call, kErrorInvalidArgs, "Expected 'ss'."); 103e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch response_sender.Run(error_response.PassAs<dbus::Response>()); 104e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch return; 105e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 106e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 107e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // Only the GATT service interface is allowed. 108e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch if (interface_name != 109e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch bluetooth_gatt_service::kBluetoothGattServiceInterface) { 110e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch scoped_ptr<dbus::ErrorResponse> error_response = 111e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::ErrorResponse::FromMethodCall( 112e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch method_call, kErrorInvalidArgs, 113e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch "No such interface: '" + interface_name + "'."); 114e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch response_sender.Run(error_response.PassAs<dbus::Response>()); 115e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch return; 116e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 117e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 118e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // Return error if |property_name| is unknown. 119e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch if (property_name != bluetooth_gatt_service::kUUIDProperty && 120e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch property_name != bluetooth_gatt_service::kIncludesProperty) { 121e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch scoped_ptr<dbus::ErrorResponse> error_response = 122e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::ErrorResponse::FromMethodCall( 123e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch method_call, kErrorInvalidArgs, 124e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch "No such property: '" + property_name + "'."); 125e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch response_sender.Run(error_response.PassAs<dbus::Response>()); 126e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch return; 127e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 128e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 129e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch scoped_ptr<dbus::Response> response = 130e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::Response::FromMethodCall(method_call); 131e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::MessageWriter writer(response.get()); 132e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::MessageWriter variant_writer(NULL); 133e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 134e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch if (property_name == bluetooth_gatt_service::kUUIDProperty) { 135e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch writer.OpenVariant("s", &variant_writer); 136e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch variant_writer.AppendString(uuid_); 137e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch writer.CloseContainer(&variant_writer); 138e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } else { 139e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch writer.OpenVariant("ao", &variant_writer); 140e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch variant_writer.AppendArrayOfObjectPaths(includes_); 141e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch writer.CloseContainer(&variant_writer); 142e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 143e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 144e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch response_sender.Run(response.Pass()); 145e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 146e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 147e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // Called by dbus:: when the Bluetooth daemon sets a single property of the 148e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // service. 149e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch void Set(dbus::MethodCall* method_call, 150e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::ExportedObject::ResponseSender response_sender) { 151e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch VLOG(2) << "BluetoothGattServiceServiceProvider::Set: " 152e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch << object_path_.value(); 153e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch DCHECK(OnOriginThread()); 154e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 155e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // All of the properties on this interface are read-only, so just return 156e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // error. 157e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch scoped_ptr<dbus::ErrorResponse> error_response = 158e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::ErrorResponse::FromMethodCall( 159e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch method_call, kErrorPropertyReadOnly, 160e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch "All properties are read-only."); 161e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch response_sender.Run(error_response.PassAs<dbus::Response>()); 162e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 163e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 164e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // Called by dbus:: when the Bluetooth daemon fetches all properties of the 165e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // service. 166e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch void GetAll(dbus::MethodCall* method_call, 167e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::ExportedObject::ResponseSender response_sender) { 168e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch VLOG(2) << "BluetoothGattServiceServiceProvider::GetAll: " 169e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch << object_path_.value(); 170e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch DCHECK(OnOriginThread()); 171e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 172e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::MessageReader reader(method_call); 173e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 174e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch std::string interface_name; 175e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch if (!reader.PopString(&interface_name) || reader.HasMoreData()) { 176e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch scoped_ptr<dbus::ErrorResponse> error_response = 177e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::ErrorResponse::FromMethodCall( 178e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch method_call, kErrorInvalidArgs, "Expected 's'."); 179e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch response_sender.Run(error_response.PassAs<dbus::Response>()); 180e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch return; 181e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 182e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 183e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // Only the GATT service interface is allowed. 184e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch if (interface_name != 185e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch bluetooth_gatt_service::kBluetoothGattServiceInterface) { 186e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch scoped_ptr<dbus::ErrorResponse> error_response = 187e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::ErrorResponse::FromMethodCall( 188e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch method_call, kErrorInvalidArgs, 189e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch "No such interface: '" + interface_name + "'."); 190e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch response_sender.Run(error_response.PassAs<dbus::Response>()); 191e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch return; 192e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 193e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 194e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch scoped_ptr<dbus::Response> response = 195e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::Response::FromMethodCall(method_call); 196e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::MessageWriter writer(response.get()); 197e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::MessageWriter array_writer(NULL); 198e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::MessageWriter dict_entry_writer(NULL); 199e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::MessageWriter variant_writer(NULL); 200e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 201e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch writer.OpenArray("{sv}", &array_writer); 202e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 203e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch array_writer.OpenDictEntry(&dict_entry_writer); 204e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dict_entry_writer.AppendString(bluetooth_gatt_service::kUUIDProperty); 205e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dict_entry_writer.AppendVariantOfString(uuid_); 206e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch array_writer.CloseContainer(&dict_entry_writer); 207e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 208e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch array_writer.OpenDictEntry(&dict_entry_writer); 209e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dict_entry_writer.AppendString(bluetooth_gatt_service::kIncludesProperty); 210e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dict_entry_writer.OpenVariant("ao", &variant_writer); 211e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch variant_writer.AppendArrayOfObjectPaths(includes_); 212e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dict_entry_writer.CloseContainer(&variant_writer); 213e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch array_writer.CloseContainer(&dict_entry_writer); 214e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 215e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch writer.CloseContainer(&array_writer); 216e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 217e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch response_sender.Run(response.Pass()); 218e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 219e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 220e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // Called by dbus:: when a method is exported. 221e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch void OnExported(const std::string& interface_name, 222e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch const std::string& method_name, 223e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch bool success) { 224e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch LOG_IF(WARNING, !success) << "Failed to export " 225e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch << interface_name << "." << method_name; 226e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 227e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 228e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // Origin thread (i.e. the UI thread in production). 229e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch base::PlatformThreadId origin_thread_id_; 230e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 231e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // 128-bit service UUID of this object. 232e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch std::string uuid_; 233e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 234e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // List of object paths that represent other exported GATT services that are 235e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // included from this service. 236e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch std::vector<dbus::ObjectPath> includes_; 237e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 238e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // D-Bus bus object is exported on, not owned by this object and must 239e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // outlive it. 240e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::Bus* bus_; 241e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 242e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // D-Bus object path of object we are exporting, kept so we can unregister 243e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // again in our destructor. 244e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::ObjectPath object_path_; 245e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 246e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // D-Bus object we are exporting, owned by this object. 247e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch scoped_refptr<dbus::ExportedObject> exported_object_; 248e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 249e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // Weak pointer factory for generating 'this' pointers that might live longer 250e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // than we do. 251e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // Note: This should remain the last member so it'll be destroyed and 252e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // invalidate its weak pointers before any other members are destroyed. 253e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch base::WeakPtrFactory<BluetoothGattServiceServiceProviderImpl> 254e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch weak_ptr_factory_; 255e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 256e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch DISALLOW_COPY_AND_ASSIGN(BluetoothGattServiceServiceProviderImpl); 257e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}; 258e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 259e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen MurdochBluetoothGattServiceServiceProvider::BluetoothGattServiceServiceProvider() { 260e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch} 261e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 262e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen MurdochBluetoothGattServiceServiceProvider::~BluetoothGattServiceServiceProvider() { 263e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch} 264e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 265e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch// static 266e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen MurdochBluetoothGattServiceServiceProvider* 267e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen MurdochBluetoothGattServiceServiceProvider::Create( 268e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dbus::Bus* bus, 269e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch const dbus::ObjectPath& object_path, 270e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch const std::string& uuid, 271e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch const std::vector<dbus::ObjectPath>& includes) { 2721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!DBusThreadManager::Get()->IsUsingStub(DBusClientBundle::BLUETOOTH)) { 273e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch return new BluetoothGattServiceServiceProviderImpl( 274e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch bus, object_path, uuid, includes); 275e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 276e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch return new FakeBluetoothGattServiceServiceProvider( 277e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch object_path, uuid, includes); 278e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch} 279e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 280e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch} // namespace chromeos 281