diff options
-rw-r--r-- | chromeos/chromeos.gyp | 4 | ||||
-rw-r--r-- | chromeos/dbus/dbus_thread_manager.cc | 11 | ||||
-rw-r--r-- | chromeos/dbus/dbus_thread_manager.h | 3 | ||||
-rw-r--r-- | chromeos/dbus/experimental_bluetooth_input_client.cc | 146 | ||||
-rw-r--r-- | chromeos/dbus/experimental_bluetooth_input_client.h | 87 | ||||
-rw-r--r-- | chromeos/dbus/fake_bluetooth_device_client.cc | 34 | ||||
-rw-r--r-- | chromeos/dbus/fake_bluetooth_device_client.h | 3 | ||||
-rw-r--r-- | chromeos/dbus/fake_bluetooth_input_client.cc | 124 | ||||
-rw-r--r-- | chromeos/dbus/fake_bluetooth_input_client.h | 66 | ||||
-rw-r--r-- | chromeos/dbus/mock_dbus_thread_manager.h | 2 | ||||
-rw-r--r-- | chromeos/dbus/mock_dbus_thread_manager_without_gmock.cc | 7 | ||||
-rw-r--r-- | chromeos/dbus/mock_dbus_thread_manager_without_gmock.h | 8 | ||||
-rw-r--r-- | device/bluetooth/bluetooth_device_experimental_chromeos.cc | 12 | ||||
-rw-r--r-- | device/bluetooth/bluetooth_experimental_chromeos_unittest.cc | 43 |
14 files changed, 547 insertions, 3 deletions
diff --git a/chromeos/chromeos.gyp b/chromeos/chromeos.gyp index 2122be9..8dc61ad 100644 --- a/chromeos/chromeos.gyp +++ b/chromeos/chromeos.gyp @@ -82,6 +82,8 @@ 'dbus/experimental_bluetooth_agent_service_provider.h', 'dbus/experimental_bluetooth_device_client.cc', 'dbus/experimental_bluetooth_device_client.h', + 'dbus/experimental_bluetooth_input_client.cc', + 'dbus/experimental_bluetooth_input_client.h', 'dbus/experimental_bluetooth_profile_manager_client.cc', 'dbus/experimental_bluetooth_profile_manager_client.h', 'dbus/experimental_bluetooth_profile_service_provider.cc', @@ -94,6 +96,8 @@ 'dbus/fake_bluetooth_agent_service_provider.h', 'dbus/fake_bluetooth_device_client.cc', 'dbus/fake_bluetooth_device_client.h', + 'dbus/fake_bluetooth_input_client.cc', + 'dbus/fake_bluetooth_input_client.h', 'dbus/fake_bluetooth_profile_manager_client.cc', 'dbus/fake_bluetooth_profile_manager_client.h', 'dbus/fake_bluetooth_profile_service_provider.cc', diff --git a/chromeos/dbus/dbus_thread_manager.cc b/chromeos/dbus/dbus_thread_manager.cc index 95dd243..8b521e5 100644 --- a/chromeos/dbus/dbus_thread_manager.cc +++ b/chromeos/dbus/dbus_thread_manager.cc @@ -26,6 +26,7 @@ #include "chromeos/dbus/experimental_bluetooth_adapter_client.h" #include "chromeos/dbus/experimental_bluetooth_agent_manager_client.h" #include "chromeos/dbus/experimental_bluetooth_device_client.h" +#include "chromeos/dbus/experimental_bluetooth_input_client.h" #include "chromeos/dbus/experimental_bluetooth_profile_manager_client.h" #include "chromeos/dbus/gsm_sms_client.h" #include "chromeos/dbus/shill_device_client.h" @@ -118,6 +119,9 @@ class DBusThreadManagerImpl : public DBusThreadManager { experimental_bluetooth_device_client_.reset( ExperimentalBluetoothDeviceClient::Create( client_type_, system_bus_.get())); + experimental_bluetooth_input_client_.reset( + ExperimentalBluetoothInputClient::Create( + client_type_, system_bus_.get())); experimental_bluetooth_profile_manager_client_.reset( ExperimentalBluetoothProfileManagerClient::Create( client_type_, system_bus_.get())); @@ -296,6 +300,11 @@ class DBusThreadManagerImpl : public DBusThreadManager { return experimental_bluetooth_device_client_.get(); } + virtual ExperimentalBluetoothInputClient* + GetExperimentalBluetoothInputClient() OVERRIDE { + return experimental_bluetooth_input_client_.get(); + } + virtual ExperimentalBluetoothProfileManagerClient* GetExperimentalBluetoothProfileManagerClient() OVERRIDE { return experimental_bluetooth_profile_manager_client_.get(); @@ -436,6 +445,8 @@ class DBusThreadManagerImpl : public DBusThreadManager { experimental_bluetooth_agent_manager_client_; scoped_ptr<ExperimentalBluetoothDeviceClient> experimental_bluetooth_device_client_; + scoped_ptr<ExperimentalBluetoothInputClient> + experimental_bluetooth_input_client_; scoped_ptr<ExperimentalBluetoothProfileManagerClient> experimental_bluetooth_profile_manager_client_; scoped_ptr<ShillDeviceClient> shill_device_client_; diff --git a/chromeos/dbus/dbus_thread_manager.h b/chromeos/dbus/dbus_thread_manager.h index 0002ebb..30fe91b 100644 --- a/chromeos/dbus/dbus_thread_manager.h +++ b/chromeos/dbus/dbus_thread_manager.h @@ -39,6 +39,7 @@ class DebugDaemonClient; class ExperimentalBluetoothAdapterClient; class ExperimentalBluetoothAgentManagerClient; class ExperimentalBluetoothDeviceClient; +class ExperimentalBluetoothInputClient; class ExperimentalBluetoothProfileManagerClient; class GsmSMSClient; class IBusClient; @@ -141,6 +142,8 @@ class CHROMEOS_EXPORT DBusThreadManager { GetExperimentalBluetoothAgentManagerClient() = 0; virtual ExperimentalBluetoothDeviceClient* GetExperimentalBluetoothDeviceClient() = 0; + virtual ExperimentalBluetoothInputClient* + GetExperimentalBluetoothInputClient() = 0; virtual ExperimentalBluetoothProfileManagerClient* GetExperimentalBluetoothProfileManagerClient() = 0; virtual GsmSMSClient* GetGsmSMSClient() = 0; diff --git a/chromeos/dbus/experimental_bluetooth_input_client.cc b/chromeos/dbus/experimental_bluetooth_input_client.cc new file mode 100644 index 0000000..ee6bf40 --- /dev/null +++ b/chromeos/dbus/experimental_bluetooth_input_client.cc @@ -0,0 +1,146 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chromeos/dbus/experimental_bluetooth_input_client.h" + +#include <map> + +#include "base/logging.h" +#include "base/stl_util.h" +#include "chromeos/dbus/bluetooth_property.h" +#include "chromeos/dbus/fake_bluetooth_input_client.h" +#include "dbus/bus.h" +#include "dbus/message.h" +#include "dbus/object_manager.h" +#include "dbus/object_path.h" +#include "dbus/object_proxy.h" +#include "third_party/cros_system_api/dbus/service_constants.h" + +namespace chromeos { + +ExperimentalBluetoothInputClient::Properties::Properties( + dbus::ObjectProxy* object_proxy, + const std::string& interface_name, + const PropertyChangedCallback& callback) + : dbus::PropertySet(object_proxy, interface_name, callback) { + RegisterProperty(bluetooth_input::kReconnectModeProperty, &reconnect_mode); +} + +ExperimentalBluetoothInputClient::Properties::~Properties() { +} + + +// The ExperimentalBluetoothInputClient implementation used in production. +class ExperimentalBluetoothInputClientImpl + : public ExperimentalBluetoothInputClient, + public dbus::ObjectManager::Interface { + public: + explicit ExperimentalBluetoothInputClientImpl(dbus::Bus* bus) + : bus_(bus), + weak_ptr_factory_(this) { + object_manager_ = bus_->GetObjectManager( + bluetooth_manager::kBluetoothManagerServiceName, + dbus::ObjectPath(bluetooth_manager::kBluetoothManagerServicePath)); + object_manager_->RegisterInterface( + bluetooth_input::kExperimentalBluetoothInputInterface, this); + } + + virtual ~ExperimentalBluetoothInputClientImpl() { + object_manager_->UnregisterInterface( + bluetooth_input::kExperimentalBluetoothInputInterface); + } + + // ExperimentalBluetoothInputClient override. + virtual void AddObserver( + ExperimentalBluetoothInputClient::Observer* observer) OVERRIDE { + DCHECK(observer); + observers_.AddObserver(observer); + } + + // ExperimentalBluetoothInputClient override. + virtual void RemoveObserver( + ExperimentalBluetoothInputClient::Observer* observer) OVERRIDE { + DCHECK(observer); + observers_.RemoveObserver(observer); + } + + // dbus::ObjectManager::Interface override. + virtual dbus::PropertySet* CreateProperties( + dbus::ObjectProxy* object_proxy, + const dbus::ObjectPath& object_path, + const std::string& interface_name) { + Properties* properties = new Properties( + object_proxy, interface_name, + base::Bind(&ExperimentalBluetoothInputClientImpl::OnPropertyChanged, + weak_ptr_factory_.GetWeakPtr(), + object_path)); + return static_cast<dbus::PropertySet*>(properties); + } + + // ExperimentalBluetoothInputClient override. + virtual Properties* GetProperties(const dbus::ObjectPath& object_path) + OVERRIDE { + return static_cast<Properties*>( + object_manager_->GetProperties( + object_path, + bluetooth_input::kExperimentalBluetoothInputInterface)); + } + + private: + // Called by dbus::ObjectManager when an object with the input interface + // is created. Informs observers. + void ObjectAdded(const dbus::ObjectPath& object_path, + const std::string& interface_name) OVERRIDE { + FOR_EACH_OBSERVER(ExperimentalBluetoothInputClient::Observer, observers_, + InputAdded(object_path)); + } + + // Called by dbus::ObjectManager when an object with the input interface + // is removed. Informs observers. + void ObjectRemoved(const dbus::ObjectPath& object_path, + const std::string& interface_name) OVERRIDE { + FOR_EACH_OBSERVER(ExperimentalBluetoothInputClient::Observer, observers_, + InputRemoved(object_path)); + } + + // Called by BluetoothPropertySet when a property value is changed, + // either by result of a signal or response to a GetAll() or Get() + // call. Informs observers. + void OnPropertyChanged(const dbus::ObjectPath& object_path, + const std::string& property_name) { + FOR_EACH_OBSERVER(ExperimentalBluetoothInputClient::Observer, observers_, + InputPropertyChanged(object_path, property_name)); + } + + dbus::Bus* bus_; + dbus::ObjectManager* object_manager_; + + // List of observers interested in event notifications from us. + ObserverList<ExperimentalBluetoothInputClient::Observer> observers_; + + // Weak pointer factory for generating 'this' pointers that might live longer + // than we do. + // Note: This should remain the last member so it'll be destroyed and + // invalidate its weak pointers before any other members are destroyed. + base::WeakPtrFactory<ExperimentalBluetoothInputClientImpl> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(ExperimentalBluetoothInputClientImpl); +}; + +ExperimentalBluetoothInputClient::ExperimentalBluetoothInputClient() { +} + +ExperimentalBluetoothInputClient::~ExperimentalBluetoothInputClient() { +} + +ExperimentalBluetoothInputClient* ExperimentalBluetoothInputClient::Create( + DBusClientImplementationType type, + dbus::Bus* bus) { + if (type == REAL_DBUS_CLIENT_IMPLEMENTATION) + return new ExperimentalBluetoothInputClientImpl(bus); + DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type); + return new FakeBluetoothInputClient(); +} + +} // namespace chromeos diff --git a/chromeos/dbus/experimental_bluetooth_input_client.h b/chromeos/dbus/experimental_bluetooth_input_client.h new file mode 100644 index 0000000..09a6a6b --- /dev/null +++ b/chromeos/dbus/experimental_bluetooth_input_client.h @@ -0,0 +1,87 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROMEOS_DBUS_EXPERIMENTAL_BLUETOOTH_INPUT_CLIENT_H_ +#define CHROMEOS_DBUS_EXPERIMENTAL_BLUETOOTH_INPUT_CLIENT_H_ + +#include <string> +#include <vector> + +#include "base/callback.h" +#include "base/observer_list.h" +#include "chromeos/chromeos_export.h" +#include "chromeos/dbus/dbus_client_implementation_type.h" +#include "dbus/object_path.h" +#include "dbus/property.h" + +namespace dbus { +class Bus; +} // namespace dbus + +namespace chromeos { + +// ExperimentalBluetoothInputClient is used to communicate with Bluetooth +// Input objects. +class CHROMEOS_EXPORT ExperimentalBluetoothInputClient { + public: + // Structure of properties associated with bluetooth input devices. + struct Properties : public dbus::PropertySet { + // The Bluetooth input device reconnect mode. Read-only. + dbus::Property<std::string> reconnect_mode; + + Properties(dbus::ObjectProxy* object_proxy, + const std::string& interface_name, + const PropertyChangedCallback& callback); + virtual ~Properties(); + }; + + // Interface for observing changes from a remote bluetooth input device. + class Observer { + public: + virtual ~Observer() {} + + // Called when the remote device with object path |object_path| implementing + // the Input interface is added to the set of known devices or an already + // known device implements the Input interface. + virtual void InputAdded(const dbus::ObjectPath& object_path) {} + + // Called when the remote device with object path |object_path| is removed + // from the set of known devices or does not implement the Input interface + // anymore. + virtual void InputRemoved(const dbus::ObjectPath& object_path) {} + + // Called when the device with object path |object_path| has a + // change in value of the property named |property_name| of its Input + // interface. + virtual void InputPropertyChanged(const dbus::ObjectPath& object_path, + const std::string& property_name) {} + }; + + virtual ~ExperimentalBluetoothInputClient(); + + // Adds and removes observers for events on all remote bluetooth input + // devices. Check the |object_path| parameter of observer methods to + // determine which device is issuing the event. + virtual void AddObserver(Observer* observer) = 0; + virtual void RemoveObserver(Observer* observer) = 0; + + // Obtain the properties for the device with object path |object_path|, + // any values should be copied if needed. + virtual Properties* GetProperties(const dbus::ObjectPath& object_path) = 0; + + // Creates the instance. + static ExperimentalBluetoothInputClient* Create( + DBusClientImplementationType type, + dbus::Bus* bus); + + protected: + ExperimentalBluetoothInputClient(); + + private: + DISALLOW_COPY_AND_ASSIGN(ExperimentalBluetoothInputClient); +}; + +} // namespace chromeos + +#endif // CHROMEOS_DBUS_EXPERIMENTAL_BLUETOOTH_INPUT_CLIENT_H_ diff --git a/chromeos/dbus/fake_bluetooth_device_client.cc b/chromeos/dbus/fake_bluetooth_device_client.cc index 00c8df4..46d4ae3 100644 --- a/chromeos/dbus/fake_bluetooth_device_client.cc +++ b/chromeos/dbus/fake_bluetooth_device_client.cc @@ -19,6 +19,7 @@ #include "chromeos/dbus/fake_bluetooth_adapter_client.h" #include "chromeos/dbus/fake_bluetooth_agent_manager_client.h" #include "chromeos/dbus/fake_bluetooth_agent_service_provider.h" +#include "chromeos/dbus/fake_bluetooth_input_client.h" #include "dbus/object_path.h" #include "third_party/cros_system_api/dbus/service_constants.h" @@ -224,6 +225,8 @@ void FakeBluetoothDeviceClient::Connect( // The device can be connected. properties->connected.ReplaceValue(true); + AddInputDeviceIfNeeded(object_path, properties); + callback.Run(); properties->NotifyPropertyChanged(properties->connected.name()); } @@ -413,6 +416,15 @@ void FakeBluetoothDeviceClient::RemoveDevice( VLOG(1) << "removing device: " << properties->alias.value(); device_list_.erase(listiter); + // Remove the Input interface if it exists. This should be called before the + // ExperimentalBluetoothDeviceClient::Observer::DeviceRemoved because it + // deletes the BluetoothDeviceExperimentalChromeOS object, including the + // device_path referenced here. + FakeBluetoothInputClient* fake_bluetooth_input_client = + static_cast<FakeBluetoothInputClient*>( + DBusThreadManager::Get()->GetExperimentalBluetoothInputClient()); + fake_bluetooth_input_client->RemoveInputDevice(device_path); + FOR_EACH_OBSERVER(ExperimentalBluetoothDeviceClient::Observer, observers_, DeviceRemoved(device_path)); @@ -628,6 +640,8 @@ void FakeBluetoothDeviceClient::CompleteSimulatedPairing( properties->paired.ReplaceValue(true); + AddInputDeviceIfNeeded(object_path, properties); + callback.Run(); properties->NotifyPropertyChanged(properties->paired.name()); } @@ -660,6 +674,26 @@ void FakeBluetoothDeviceClient::RejectSimulatedPairing( "Rejected"); } +void FakeBluetoothDeviceClient::AddInputDeviceIfNeeded( + const dbus::ObjectPath& object_path, + Properties* properties) { + // If the paired device is a HID device based on it's bluetooth class, + // simulate the Input interface. + FakeBluetoothInputClient* fake_bluetooth_input_client = + static_cast<FakeBluetoothInputClient*>( + DBusThreadManager::Get()->GetExperimentalBluetoothInputClient()); + + if ((properties->bluetooth_class.value() & 0x001f03) == 0x000500) { + std::vector<std::string> uuids = properties->uuids.value(); + if (std::find(uuids.begin(), uuids.end(), + "00001124-0000-1000-8000-00805f9b34fb") == uuids.end()) { + uuids.push_back("00001124-0000-1000-8000-00805f9b34fb"); + properties->uuids.ReplaceValue(uuids); + fake_bluetooth_input_client->AddInputDevice(object_path); + } + } +} + void FakeBluetoothDeviceClient::PinCodeCallback( const dbus::ObjectPath& object_path, const base::Closure& callback, diff --git a/chromeos/dbus/fake_bluetooth_device_client.h b/chromeos/dbus/fake_bluetooth_device_client.h index 34b7959..d3b0fdd 100644 --- a/chromeos/dbus/fake_bluetooth_device_client.h +++ b/chromeos/dbus/fake_bluetooth_device_client.h @@ -146,6 +146,9 @@ class CHROMEOS_EXPORT FakeBluetoothDeviceClient void RejectSimulatedPairing( const dbus::ObjectPath& object_path, const ErrorCallback& error_callback); + void AddInputDeviceIfNeeded( + const dbus::ObjectPath& object_path, + Properties* properties); void PinCodeCallback( const dbus::ObjectPath& object_path, diff --git a/chromeos/dbus/fake_bluetooth_input_client.cc b/chromeos/dbus/fake_bluetooth_input_client.cc new file mode 100644 index 0000000..a52831b --- /dev/null +++ b/chromeos/dbus/fake_bluetooth_input_client.cc @@ -0,0 +1,124 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chromeos/dbus/fake_bluetooth_input_client.h" + +#include <map> + +#include "base/logging.h" +#include "base/stl_util.h" +#include "chromeos/dbus/bluetooth_property.h" +#include "chromeos/dbus/fake_bluetooth_device_client.h" +#include "dbus/bus.h" +#include "dbus/message.h" +#include "dbus/object_manager.h" +#include "dbus/object_path.h" +#include "dbus/object_proxy.h" +#include "third_party/cros_system_api/dbus/service_constants.h" + +namespace chromeos { + +FakeBluetoothInputClient::Properties::Properties( + const PropertyChangedCallback& callback) + : ExperimentalBluetoothInputClient::Properties( + NULL, + bluetooth_input::kExperimentalBluetoothInputInterface, + callback) { +} + +FakeBluetoothInputClient::Properties::~Properties() { +} + +void FakeBluetoothInputClient::Properties::Get( + dbus::PropertyBase* property, + dbus::PropertySet::GetCallback callback) { + VLOG(1) << "Get " << property->name(); + callback.Run(false); +} + +void FakeBluetoothInputClient::Properties::GetAll() { + VLOG(1) << "GetAll"; +} + +void FakeBluetoothInputClient::Properties::Set( + dbus::PropertyBase *property, + dbus::PropertySet::SetCallback callback) { + VLOG(1) << "Set " << property->name(); + callback.Run(false); +} + + +FakeBluetoothInputClient::FakeBluetoothInputClient() { +} + +FakeBluetoothInputClient::~FakeBluetoothInputClient() { + // Clean up Properties structures + STLDeleteValues(&properties_map_); +} + +void FakeBluetoothInputClient::AddObserver(Observer* observer) { + observers_.AddObserver(observer); +} + +void FakeBluetoothInputClient::RemoveObserver(Observer* observer) { + observers_.RemoveObserver(observer); +} + +FakeBluetoothInputClient::Properties* +FakeBluetoothInputClient::GetProperties(const dbus::ObjectPath& object_path) { + PropertiesMap::iterator iter = properties_map_.find(object_path); + if (iter != properties_map_.end()) + return iter->second; + return NULL; +} + +void FakeBluetoothInputClient::AddInputDevice( + const dbus::ObjectPath& object_path) { + if (properties_map_.find(object_path) != properties_map_.end()) + return; + + Properties* properties = new Properties(base::Bind( + &FakeBluetoothInputClient::OnPropertyChanged, + base::Unretained(this), + object_path)); + + // Mark Apple mouse and keyboard as ReconnectMode "any" and the Motorola and + // Microsoft devices as ReconnectMode "device". + if (object_path.value() == FakeBluetoothDeviceClient::kMotorolaKeyboardPath || + object_path.value() == FakeBluetoothDeviceClient::kMicrosoftMousePath) { + properties->reconnect_mode.ReplaceValue( + bluetooth_input::kDeviceReconnectModeProperty); + } else { + properties->reconnect_mode.ReplaceValue( + bluetooth_input::kAnyReconnectModeProperty); + } + + properties_map_[object_path] = properties; + + FOR_EACH_OBSERVER(ExperimentalBluetoothInputClient::Observer, observers_, + InputAdded(object_path)); +} + +void FakeBluetoothInputClient::RemoveInputDevice( + const dbus::ObjectPath& object_path) { + PropertiesMap::iterator it = properties_map_.find(object_path); + + if (it == properties_map_.end()) + return; + + FOR_EACH_OBSERVER(ExperimentalBluetoothInputClient::Observer, observers_, + InputRemoved(object_path)); + + delete it->second; + properties_map_.erase(it); +} + +void FakeBluetoothInputClient::OnPropertyChanged( + const dbus::ObjectPath& object_path, + const std::string& property_name) { + FOR_EACH_OBSERVER(ExperimentalBluetoothInputClient::Observer, observers_, + InputPropertyChanged(object_path, property_name)); +} + +} // namespace chromeos diff --git a/chromeos/dbus/fake_bluetooth_input_client.h b/chromeos/dbus/fake_bluetooth_input_client.h new file mode 100644 index 0000000..103e57d --- /dev/null +++ b/chromeos/dbus/fake_bluetooth_input_client.h @@ -0,0 +1,66 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROMEOS_DBUS_FAKE_BLUETOOTH_INPUT_CLIENT_H_ +#define CHROMEOS_DBUS_FAKE_BLUETOOTH_INPUT_CLIENT_H_ + +#include "base/callback.h" +#include "base/observer_list.h" +#include "chromeos/chromeos_export.h" +#include "chromeos/dbus/dbus_client_implementation_type.h" +#include "chromeos/dbus/experimental_bluetooth_input_client.h" +#include "dbus/object_path.h" +#include "dbus/property.h" + +namespace chromeos { + +// FakeBluetoothInputClient simulates the behavior of the Bluetooth Daemon +// input device objects and is used both in test cases in place of a mock and on +// the Linux desktop. +class CHROMEOS_EXPORT FakeBluetoothInputClient + : public ExperimentalBluetoothInputClient { + public: + struct Properties : public ExperimentalBluetoothInputClient::Properties { + explicit Properties(const PropertyChangedCallback & callback); + virtual ~Properties(); + + // dbus::PropertySet override + virtual void Get(dbus::PropertyBase* property, + dbus::PropertySet::GetCallback callback) OVERRIDE; + virtual void GetAll() OVERRIDE; + virtual void Set(dbus::PropertyBase* property, + dbus::PropertySet::SetCallback callback) OVERRIDE; + }; + + FakeBluetoothInputClient(); + virtual ~FakeBluetoothInputClient(); + + // ExperimentalBluetoothInputClient override + virtual void AddObserver(Observer* observer) OVERRIDE; + virtual void RemoveObserver(Observer* observer) OVERRIDE; + virtual Properties* GetProperties(const dbus::ObjectPath& object_path) + OVERRIDE; + + // Simulate device addition/removal + void AddInputDevice(const dbus::ObjectPath& object_path); + void RemoveInputDevice(const dbus::ObjectPath& object_path); + + private: + // Property callback passed when we create Properties* structures. + void OnPropertyChanged(const dbus::ObjectPath& object_path, + const std::string& property_name); + + // Static properties we return. + typedef std::map<const dbus::ObjectPath, Properties *> PropertiesMap; + PropertiesMap properties_map_; + + // List of observers interested in event notifications from us. + ObserverList<Observer> observers_; + + DISALLOW_COPY_AND_ASSIGN(FakeBluetoothInputClient); +}; + +} // namespace chromeos + +#endif // CHROMEOS_DBUS_FAKE_BLUETOOTH_INPUT_CLIENT_H_ diff --git a/chromeos/dbus/mock_dbus_thread_manager.h b/chromeos/dbus/mock_dbus_thread_manager.h index 3f92236..5290988 100644 --- a/chromeos/dbus/mock_dbus_thread_manager.h +++ b/chromeos/dbus/mock_dbus_thread_manager.h @@ -82,6 +82,8 @@ class MockDBusThreadManager : public DBusThreadManager { ExperimentalBluetoothAgentManagerClient*(void)); MOCK_METHOD0(GetExperimentalBluetoothDeviceClient, ExperimentalBluetoothDeviceClient*(void)); + MOCK_METHOD0(GetExperimentalBluetoothInputClient, + ExperimentalBluetoothInputClient*(void)); MOCK_METHOD0(GetExperimentalBluetoothProfileManagerClient, ExperimentalBluetoothProfileManagerClient*(void)); MOCK_METHOD0(GetShillDeviceClient, ShillDeviceClient*(void)); diff --git a/chromeos/dbus/mock_dbus_thread_manager_without_gmock.cc b/chromeos/dbus/mock_dbus_thread_manager_without_gmock.cc index eee44dc..3ffc623 100644 --- a/chromeos/dbus/mock_dbus_thread_manager_without_gmock.cc +++ b/chromeos/dbus/mock_dbus_thread_manager_without_gmock.cc @@ -8,6 +8,7 @@ #include "chromeos/dbus/fake_bluetooth_adapter_client.h" #include "chromeos/dbus/fake_bluetooth_agent_manager_client.h" #include "chromeos/dbus/fake_bluetooth_device_client.h" +#include "chromeos/dbus/fake_bluetooth_input_client.h" #include "chromeos/dbus/fake_bluetooth_profile_manager_client.h" #include "chromeos/dbus/ibus/mock_ibus_client.h" #include "chromeos/dbus/ibus/mock_ibus_config_client.h" @@ -22,6 +23,7 @@ MockDBusThreadManagerWithoutGMock::MockDBusThreadManagerWithoutGMock() : fake_bluetooth_adapter_client_(new FakeBluetoothAdapterClient()), fake_bluetooth_agent_manager_client_(new FakeBluetoothAgentManagerClient()), fake_bluetooth_device_client_(new FakeBluetoothDeviceClient()), + fake_bluetooth_input_client_(new FakeBluetoothInputClient()), fake_bluetooth_profile_manager_client_( new FakeBluetoothProfileManagerClient()), mock_ibus_client_(new MockIBusClient), @@ -127,6 +129,11 @@ ExperimentalBluetoothDeviceClient* return fake_bluetooth_device_client_.get(); } +ExperimentalBluetoothInputClient* + MockDBusThreadManagerWithoutGMock::GetExperimentalBluetoothInputClient() { + return fake_bluetooth_input_client_.get(); +} + ExperimentalBluetoothProfileManagerClient* MockDBusThreadManagerWithoutGMock:: GetExperimentalBluetoothProfileManagerClient() { diff --git a/chromeos/dbus/mock_dbus_thread_manager_without_gmock.h b/chromeos/dbus/mock_dbus_thread_manager_without_gmock.h index 0acbd81..fecdf54 100644 --- a/chromeos/dbus/mock_dbus_thread_manager_without_gmock.h +++ b/chromeos/dbus/mock_dbus_thread_manager_without_gmock.h @@ -22,6 +22,7 @@ class DBusThreadManagerObserver; class FakeBluetoothAdapterClient; class FakeBluetoothAgentManagerClient; class FakeBluetoothDeviceClient; +class FakeBluetoothInputClient; class FakeBluetoothProfileManagerClient; class MockIBusClient; class MockIBusConfigClient; @@ -60,6 +61,8 @@ class MockDBusThreadManagerWithoutGMock : public DBusThreadManager { GetExperimentalBluetoothAgentManagerClient() OVERRIDE; virtual ExperimentalBluetoothDeviceClient* GetExperimentalBluetoothDeviceClient() OVERRIDE; + virtual ExperimentalBluetoothInputClient* + GetExperimentalBluetoothInputClient() OVERRIDE; virtual ExperimentalBluetoothProfileManagerClient* GetExperimentalBluetoothProfileManagerClient() OVERRIDE; virtual ShillDeviceClient* GetShillDeviceClient() OVERRIDE; @@ -101,6 +104,10 @@ class MockDBusThreadManagerWithoutGMock : public DBusThreadManager { return fake_bluetooth_device_client_.get(); } + FakeBluetoothInputClient* fake_bluetooth_input_client() { + return fake_bluetooth_input_client_.get(); + } + FakeBluetoothProfileManagerClient* fake_bluetooth_profile_manager_client() { return fake_bluetooth_profile_manager_client_.get(); } @@ -138,6 +145,7 @@ class MockDBusThreadManagerWithoutGMock : public DBusThreadManager { scoped_ptr<FakeBluetoothAgentManagerClient> fake_bluetooth_agent_manager_client_; scoped_ptr<FakeBluetoothDeviceClient> fake_bluetooth_device_client_; + scoped_ptr<FakeBluetoothInputClient> fake_bluetooth_input_client_; scoped_ptr<FakeBluetoothProfileManagerClient> fake_bluetooth_profile_manager_client_; scoped_ptr<MockIBusClient> mock_ibus_client_; diff --git a/device/bluetooth/bluetooth_device_experimental_chromeos.cc b/device/bluetooth/bluetooth_device_experimental_chromeos.cc index 0797983..4b99dbe 100644 --- a/device/bluetooth/bluetooth_device_experimental_chromeos.cc +++ b/device/bluetooth/bluetooth_device_experimental_chromeos.cc @@ -10,6 +10,7 @@ #include "chromeos/dbus/experimental_bluetooth_agent_manager_client.h" #include "chromeos/dbus/experimental_bluetooth_agent_service_provider.h" #include "chromeos/dbus/experimental_bluetooth_device_client.h" +#include "chromeos/dbus/experimental_bluetooth_input_client.h" #include "dbus/bus.h" #include "device/bluetooth/bluetooth_adapter_experimental_chromeos.h" #include "device/bluetooth/bluetooth_socket.h" @@ -90,8 +91,15 @@ bool BluetoothDeviceExperimentalChromeOS::IsConnected() const { } bool BluetoothDeviceExperimentalChromeOS::IsConnectable() const { - // TODO(deymo): implement - return false; + ExperimentalBluetoothInputClient::Properties* input_properties = + DBusThreadManager::Get()->GetExperimentalBluetoothInputClient()-> + GetProperties(object_path_); + // GetProperties returns NULL when the device does not implement the given + // interface. Non HID devices are normally connectable. + if (!input_properties) + return true; + + return input_properties->reconnect_mode.value() != "device"; } bool BluetoothDeviceExperimentalChromeOS::IsConnecting() const { diff --git a/device/bluetooth/bluetooth_experimental_chromeos_unittest.cc b/device/bluetooth/bluetooth_experimental_chromeos_unittest.cc index 4fc8e67..2f14369 100644 --- a/device/bluetooth/bluetooth_experimental_chromeos_unittest.cc +++ b/device/bluetooth/bluetooth_experimental_chromeos_unittest.cc @@ -755,9 +755,11 @@ TEST_F(BluetoothExperimentalChromeOSTest, DeviceProperties) { EXPECT_EQ(BluetoothDevice::DEVICE_COMPUTER, devices[0]->GetDeviceType()); EXPECT_TRUE(devices[0]->IsPaired()); EXPECT_FALSE(devices[0]->IsConnected()); - EXPECT_FALSE(devices[0]->IsConnectable()); EXPECT_FALSE(devices[0]->IsConnecting()); + // Non HID devices are always connectable. + EXPECT_TRUE(devices[0]->IsConnectable()); + BluetoothDevice::ServiceList uuids = devices[0]->GetServices(); ASSERT_EQ(2U, uuids.size()); EXPECT_EQ(uuids[0], "00001800-0000-1000-8000-00805f9b34fb"); @@ -1009,6 +1011,12 @@ TEST_F(BluetoothExperimentalChromeOSTest, ConnectUnpairableDevice) { fake_bluetooth_device_client_->GetProperties( dbus::ObjectPath(FakeBluetoothDeviceClient::kMicrosoftMousePath)); EXPECT_TRUE(properties->trusted.value()); + + // Verify is a HID device and is not connectable. + BluetoothDevice::ServiceList uuids = device->GetServices(); + ASSERT_EQ(1U, uuids.size()); + EXPECT_EQ(uuids[0], "00001124-0000-1000-8000-00805f9b34fb"); + EXPECT_FALSE(device->IsConnectable()); } TEST_F(BluetoothExperimentalChromeOSTest, ConnectConnectedDevice) { @@ -1197,6 +1205,12 @@ TEST_F(BluetoothExperimentalChromeOSTest, PairAppleMouse) { EXPECT_TRUE(device->IsPaired()); + // Verify is a HID device and is connectable. + BluetoothDevice::ServiceList uuids = device->GetServices(); + ASSERT_EQ(1U, uuids.size()); + EXPECT_EQ(uuids[0], "00001124-0000-1000-8000-00805f9b34fb"); + EXPECT_TRUE(device->IsConnectable()); + // Pairing dialog should be dismissed EXPECT_EQ(1, pairing_delegate.call_count_); EXPECT_EQ(1, pairing_delegate.dismiss_count_); @@ -1252,6 +1266,12 @@ TEST_F(BluetoothExperimentalChromeOSTest, PairAppleKeyboard) { EXPECT_TRUE(device->IsPaired()); + // Verify is a HID device and is connectable. + BluetoothDevice::ServiceList uuids = device->GetServices(); + ASSERT_EQ(1U, uuids.size()); + EXPECT_EQ(uuids[0], "00001124-0000-1000-8000-00805f9b34fb"); + EXPECT_TRUE(device->IsConnectable()); + // Pairing dialog should be dismissed EXPECT_EQ(1, pairing_delegate.dismiss_count_); @@ -1325,6 +1345,14 @@ TEST_F(BluetoothExperimentalChromeOSTest, PairMotorolaKeyboard) { EXPECT_TRUE(device->IsPaired()); + // Verify is a HID device. + BluetoothDevice::ServiceList uuids = device->GetServices(); + ASSERT_EQ(1U, uuids.size()); + EXPECT_EQ(uuids[0], "00001124-0000-1000-8000-00805f9b34fb"); + + // Fake MotorolaKeyboard is not connectable. + EXPECT_FALSE(device->IsConnectable()); + // Pairing dialog should be dismissed EXPECT_EQ(1, pairing_delegate.dismiss_count_); @@ -1379,6 +1407,13 @@ TEST_F(BluetoothExperimentalChromeOSTest, PairSonyHeadphones) { EXPECT_TRUE(device->IsPaired()); + // Verify is not a HID device. + BluetoothDevice::ServiceList uuids = device->GetServices(); + ASSERT_EQ(0U, uuids.size()); + + // Non HID devices are always connectable. + EXPECT_TRUE(device->IsConnectable()); + // Pairing dialog should be dismissed EXPECT_EQ(2, pairing_delegate.call_count_); EXPECT_EQ(1, pairing_delegate.dismiss_count_); @@ -1435,6 +1470,9 @@ TEST_F(BluetoothExperimentalChromeOSTest, PairPhone) { EXPECT_TRUE(device->IsPaired()); + // Non HID devices are always connectable. + EXPECT_TRUE(device->IsConnectable()); + // Pairing dialog should be dismissed EXPECT_EQ(2, pairing_delegate.call_count_); EXPECT_EQ(1, pairing_delegate.dismiss_count_); @@ -1492,6 +1530,9 @@ TEST_F(BluetoothExperimentalChromeOSTest, PairWeirdDevice) { EXPECT_TRUE(device->IsPaired()); + // Non HID devices are always connectable. + EXPECT_TRUE(device->IsConnectable()); + // Pairing dialog should be dismissed EXPECT_EQ(2, pairing_delegate.call_count_); EXPECT_EQ(1, pairing_delegate.dismiss_count_); |