Index: chromeos/dbus/fake_bluetooth_device_client.cc |
diff --git a/chromeos/dbus/fake_bluetooth_device_client.cc b/chromeos/dbus/fake_bluetooth_device_client.cc |
index 64df07f72732b930e288b20c410f6f0e8e0110f2..44b9a0b5a407c01a8cab726157522e528e16cbc0 100644 |
--- a/chromeos/dbus/fake_bluetooth_device_client.cc |
+++ b/chromeos/dbus/fake_bluetooth_device_client.cc |
@@ -19,6 +19,7 @@ |
#include "base/logging.h" |
#include "base/memory/scoped_ptr.h" |
#include "base/message_loop/message_loop.h" |
+#include "base/rand_util.h" |
#include "base/stl_util.h" |
#include "base/threading/worker_pool.h" |
#include "base/time/time.h" |
@@ -26,6 +27,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_gatt_service_client.h" |
#include "chromeos/dbus/fake_bluetooth_input_client.h" |
#include "chromeos/dbus/fake_bluetooth_profile_manager_client.h" |
#include "chromeos/dbus/fake_bluetooth_profile_service_provider.h" |
@@ -38,6 +40,10 @@ namespace { |
// Default interval between simulated events. |
const int kSimulationIntervalMs = 750; |
+// Minimum and maximum bounds for randomly generated RSSI values. |
+const int kMinRSSI = -90; |
+const int kMaxRSSI = -30; |
+ |
void SimulatedProfileSocket(int fd) { |
// Simulate a server-side socket of a profile; read data from the socket, |
@@ -167,6 +173,15 @@ const char FakeBluetoothDeviceClient::kJustWorksName[] = |
"Just-Works Device"; |
const uint32 FakeBluetoothDeviceClient::kJustWorksClass = 0x240428; |
+const char FakeBluetoothDeviceClient::kLowEnergyPath[] = |
+ "/fake/hci0/devC"; |
+const char FakeBluetoothDeviceClient::kLowEnergyAddress[] = |
+ "00:1A:11:00:15:30"; |
+const char FakeBluetoothDeviceClient::kLowEnergyName[] = |
+ "Bluetooth 4.0 Heart Rate Monitor"; |
+const uint32 FakeBluetoothDeviceClient::kLowEnergyClass = |
+ 0x000918; // Major class "Health", Minor class "Heart/Pulse Rate Monitor." |
+ |
FakeBluetoothDeviceClient::Properties::Properties( |
const PropertyChangedCallback& callback) |
: BluetoothDeviceClient::Properties( |
@@ -293,6 +308,15 @@ void FakeBluetoothDeviceClient::Connect( |
properties->connected.ReplaceValue(true); |
callback.Run(); |
+ // Expose GATT services if connected to LE device. |
+ if (object_path == dbus::ObjectPath(kLowEnergyPath)) { |
+ FakeBluetoothGattServiceClient* gatt_service_client = |
+ static_cast<FakeBluetoothGattServiceClient*>( |
+ DBusThreadManager::Get()->GetBluetoothGattServiceClient()); |
+ gatt_service_client->ExposeHeartRateService( |
+ dbus::ObjectPath(kLowEnergyPath)); |
+ } |
+ |
AddInputDeviceIfNeeded(object_path, properties); |
} |
@@ -303,12 +327,21 @@ void FakeBluetoothDeviceClient::Disconnect( |
VLOG(1) << "Disconnect: " << object_path.value(); |
Properties* properties = GetProperties(object_path); |
- if (properties->connected.value() == true) { |
- callback.Run(); |
- properties->connected.ReplaceValue(false); |
- } else { |
+ if (!properties->connected.value()) { |
error_callback.Run("org.bluez.Error.NotConnected", "Not Connected"); |
+ return; |
+ } |
+ |
+ // Hide the Heart Rate Service if disconnected from LE device. |
+ if (object_path == dbus::ObjectPath(kLowEnergyPath)) { |
+ FakeBluetoothGattServiceClient* gatt_service_client = |
+ static_cast<FakeBluetoothGattServiceClient*>( |
+ DBusThreadManager::Get()->GetBluetoothGattServiceClient()); |
+ gatt_service_client->HideHeartRateService(); |
} |
+ |
+ callback.Run(); |
+ properties->connected.ReplaceValue(false); |
} |
void FakeBluetoothDeviceClient::ConnectProfile( |
@@ -564,6 +597,16 @@ void FakeBluetoothDeviceClient::CreateDevice( |
properties->name.ReplaceValue("JustWorks"); |
properties->alias.ReplaceValue(kJustWorksName); |
+ } else if (device_path == dbus::ObjectPath(kLowEnergyPath)) { |
+ properties->address.ReplaceValue(kLowEnergyAddress); |
+ properties->bluetooth_class.ReplaceValue(kLowEnergyClass); |
+ properties->name.ReplaceValue("Heart Rate Monitor"); |
+ properties->alias.ReplaceValue(kLowEnergyName); |
+ |
+ std::vector<std::string> uuids; |
+ uuids.push_back(FakeBluetoothGattServiceClient::kHeartRateServiceUUID); |
+ properties->uuids.ReplaceValue(uuids); |
+ |
} else { |
NOTREACHED(); |
@@ -597,6 +640,13 @@ void FakeBluetoothDeviceClient::RemoveDevice( |
DBusThreadManager::Get()->GetBluetoothInputClient()); |
fake_bluetooth_input_client->RemoveInputDevice(device_path); |
+ if (device_path == dbus::ObjectPath(kLowEnergyPath)) { |
+ FakeBluetoothGattServiceClient* gatt_service_client = |
+ static_cast<FakeBluetoothGattServiceClient*>( |
+ DBusThreadManager::Get()->GetBluetoothGattServiceClient()); |
+ gatt_service_client->HideHeartRateService(); |
+ } |
+ |
FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_, |
DeviceRemoved(device_path)); |
@@ -607,6 +657,8 @@ void FakeBluetoothDeviceClient::RemoveDevice( |
void FakeBluetoothDeviceClient::OnPropertyChanged( |
const dbus::ObjectPath& object_path, |
const std::string& property_name) { |
+ VLOG(2) << "Fake Bluetooth device property changed: " << object_path.value() |
+ << ": " << property_name; |
FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_, |
DevicePropertyChanged(object_path, property_name)); |
} |
@@ -621,22 +673,30 @@ void FakeBluetoothDeviceClient::DiscoverySimulationTimer() { |
if (discovery_simulation_step_ == 2) { |
CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), |
dbus::ObjectPath(kLegacyAutopairPath)); |
+ CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), |
+ dbus::ObjectPath(kLowEnergyPath)); |
} else if (discovery_simulation_step_ == 4) { |
CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), |
dbus::ObjectPath(kDisplayPinCodePath)); |
CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), |
dbus::ObjectPath(kVanishingDevicePath)); |
+ UpdateDeviceRSSI(dbus::ObjectPath(kLowEnergyPath), |
+ base::RandInt(kMinRSSI, kMaxRSSI)); |
} else if (discovery_simulation_step_ == 7) { |
CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), |
dbus::ObjectPath(kConnectUnpairablePath)); |
+ UpdateDeviceRSSI(dbus::ObjectPath(kLowEnergyPath), |
+ base::RandInt(kMinRSSI, kMaxRSSI)); |
} else if (discovery_simulation_step_ == 8) { |
CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), |
dbus::ObjectPath(kDisplayPasskeyPath)); |
CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), |
dbus::ObjectPath(kRequestPinCodePath)); |
+ UpdateDeviceRSSI(dbus::ObjectPath(kLowEnergyPath), |
+ base::RandInt(kMinRSSI, kMaxRSSI)); |
} else if (discovery_simulation_step_ == 10) { |
CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), |
@@ -649,12 +709,18 @@ void FakeBluetoothDeviceClient::DiscoverySimulationTimer() { |
dbus::ObjectPath(kUnpairableDevicePath)); |
CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), |
dbus::ObjectPath(kJustWorksPath)); |
+ UpdateDeviceRSSI(dbus::ObjectPath(kLowEnergyPath), |
+ base::RandInt(kMinRSSI, kMaxRSSI)); |
} else if (discovery_simulation_step_ == 13) { |
RemoveDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), |
dbus::ObjectPath(kVanishingDevicePath)); |
+ UpdateDeviceRSSI(dbus::ObjectPath(kLowEnergyPath), |
+ base::RandInt(kMinRSSI, kMaxRSSI)); |
} else if (discovery_simulation_step_ == 14) { |
+ UpdateDeviceRSSI(dbus::ObjectPath(kLowEnergyPath), |
+ base::RandInt(kMinRSSI, kMaxRSSI)); |
return; |
} |
@@ -744,7 +810,8 @@ void FakeBluetoothDeviceClient::SimulatePairing( |
if (object_path == dbus::ObjectPath(kLegacyAutopairPath) || |
object_path == dbus::ObjectPath(kConnectUnpairablePath) || |
- object_path == dbus::ObjectPath(kUnconnectableDevicePath)) { |
+ object_path == dbus::ObjectPath(kUnconnectableDevicePath) || |
+ object_path == dbus::ObjectPath(kLowEnergyPath)) { |
// No need to call anything on the pairing delegate, just wait 3 times |
// the interval before acting as if the other end accepted it. |
base::MessageLoop::current()->PostDelayedTask( |
@@ -921,6 +988,19 @@ void FakeBluetoothDeviceClient::AddInputDeviceIfNeeded( |
fake_bluetooth_input_client->AddInputDevice(object_path); |
} |
+void FakeBluetoothDeviceClient::UpdateDeviceRSSI( |
+ const dbus::ObjectPath& object_path, |
+ int16 rssi) { |
+ PropertiesMap::iterator iter = properties_map_.find(object_path); |
+ if (iter == properties_map_.end()) { |
+ VLOG(2) << "Fake device does not exist: " << object_path.value(); |
+ return; |
+ } |
+ Properties* properties = iter->second; |
+ DCHECK(properties); |
+ properties->rssi.ReplaceValue(rssi); |
+} |
+ |
void FakeBluetoothDeviceClient::PinCodeCallback( |
const dbus::ObjectPath& object_path, |
const base::Closure& callback, |