summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chromeos/chromeos.gyp4
-rw-r--r--chromeos/dbus/dbus_thread_manager.cc11
-rw-r--r--chromeos/dbus/dbus_thread_manager.h3
-rw-r--r--chromeos/dbus/experimental_bluetooth_input_client.cc146
-rw-r--r--chromeos/dbus/experimental_bluetooth_input_client.h87
-rw-r--r--chromeos/dbus/fake_bluetooth_device_client.cc34
-rw-r--r--chromeos/dbus/fake_bluetooth_device_client.h3
-rw-r--r--chromeos/dbus/fake_bluetooth_input_client.cc124
-rw-r--r--chromeos/dbus/fake_bluetooth_input_client.h66
-rw-r--r--chromeos/dbus/mock_dbus_thread_manager.h2
-rw-r--r--chromeos/dbus/mock_dbus_thread_manager_without_gmock.cc7
-rw-r--r--chromeos/dbus/mock_dbus_thread_manager_without_gmock.h8
-rw-r--r--device/bluetooth/bluetooth_device_experimental_chromeos.cc12
-rw-r--r--device/bluetooth/bluetooth_experimental_chromeos_unittest.cc43
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_);