Home | History | Annotate | Download | only in dbus
      1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chromeos/dbus/fake_bluetooth_device_client.h"
      6 
      7 #include <fcntl.h>
      8 #include <unistd.h>
      9 #include <sys/types.h>
     10 #include <sys/socket.h>
     11 
     12 #include <algorithm>
     13 #include <map>
     14 #include <string>
     15 #include <utility>
     16 #include <vector>
     17 
     18 #include "base/bind.h"
     19 #include "base/logging.h"
     20 #include "base/memory/scoped_ptr.h"
     21 #include "base/message_loop/message_loop.h"
     22 #include "base/rand_util.h"
     23 #include "base/stl_util.h"
     24 #include "base/threading/worker_pool.h"
     25 #include "base/time/time.h"
     26 #include "chromeos/dbus/dbus_thread_manager.h"
     27 #include "chromeos/dbus/fake_bluetooth_adapter_client.h"
     28 #include "chromeos/dbus/fake_bluetooth_agent_manager_client.h"
     29 #include "chromeos/dbus/fake_bluetooth_agent_service_provider.h"
     30 #include "chromeos/dbus/fake_bluetooth_gatt_service_client.h"
     31 #include "chromeos/dbus/fake_bluetooth_input_client.h"
     32 #include "chromeos/dbus/fake_bluetooth_profile_manager_client.h"
     33 #include "chromeos/dbus/fake_bluetooth_profile_service_provider.h"
     34 #include "dbus/file_descriptor.h"
     35 #include "dbus/object_path.h"
     36 #include "third_party/cros_system_api/dbus/service_constants.h"
     37 
     38 namespace {
     39 
     40 // Default interval between simulated events.
     41 const int kSimulationIntervalMs = 750;
     42 
     43 // Minimum and maximum bounds for randomly generated RSSI values.
     44 const int kMinRSSI = -90;
     45 const int kMaxRSSI = -30;
     46 
     47 
     48 void SimulatedProfileSocket(int fd) {
     49   // Simulate a server-side socket of a profile; read data from the socket,
     50   // write it back, and then close.
     51   char buf[1024];
     52   ssize_t len;
     53   ssize_t count;
     54 
     55   len = read(fd, buf, sizeof buf);
     56   if (len < 0) {
     57     close(fd);
     58     return;
     59   }
     60 
     61   count = len;
     62   len = write(fd, buf, count);
     63   if (len < 0) {
     64     close(fd);
     65     return;
     66   }
     67 
     68   close(fd);
     69 }
     70 
     71 void SimpleErrorCallback(const std::string& error_name,
     72                          const std::string& error_message) {
     73   VLOG(1) << "Bluetooth Error: " << error_name << ": " << error_message;
     74 }
     75 
     76 }  // namespace
     77 
     78 namespace chromeos {
     79 
     80 const char FakeBluetoothDeviceClient::kPairedDevicePath[] =
     81     "/fake/hci0/dev0";
     82 const char FakeBluetoothDeviceClient::kPairedDeviceAddress[] =
     83     "00:11:22:33:44:55";
     84 const char FakeBluetoothDeviceClient::kPairedDeviceName[] =
     85     "Fake Device";
     86 const uint32 FakeBluetoothDeviceClient::kPairedDeviceClass = 0x000104;
     87 
     88 const char FakeBluetoothDeviceClient::kLegacyAutopairPath[] =
     89     "/fake/hci0/dev1";
     90 const char FakeBluetoothDeviceClient::kLegacyAutopairAddress[] =
     91     "28:CF:DA:00:00:00";
     92 const char FakeBluetoothDeviceClient::kLegacyAutopairName[] =
     93     "Bluetooth 2.0 Mouse";
     94 const uint32 FakeBluetoothDeviceClient::kLegacyAutopairClass = 0x002580;
     95 
     96 const char FakeBluetoothDeviceClient::kDisplayPinCodePath[] =
     97     "/fake/hci0/dev2";
     98 const char FakeBluetoothDeviceClient::kDisplayPinCodeAddress[] =
     99     "28:37:37:00:00:00";
    100 const char FakeBluetoothDeviceClient::kDisplayPinCodeName[] =
    101     "Bluetooth 2.0 Keyboard";
    102 const uint32 FakeBluetoothDeviceClient::kDisplayPinCodeClass = 0x002540;
    103 
    104 const char FakeBluetoothDeviceClient::kVanishingDevicePath[] =
    105     "/fake/hci0/dev3";
    106 const char FakeBluetoothDeviceClient::kVanishingDeviceAddress[] =
    107     "01:02:03:04:05:06";
    108 const char FakeBluetoothDeviceClient::kVanishingDeviceName[] =
    109     "Vanishing Device";
    110 const uint32 FakeBluetoothDeviceClient::kVanishingDeviceClass = 0x000104;
    111 
    112 const char FakeBluetoothDeviceClient::kConnectUnpairablePath[] =
    113     "/fake/hci0/dev4";
    114 const char FakeBluetoothDeviceClient::kConnectUnpairableAddress[] =
    115     "7C:ED:8D:00:00:00";
    116 const char FakeBluetoothDeviceClient::kConnectUnpairableName[] =
    117     "Unpairable Device";
    118 const uint32 FakeBluetoothDeviceClient::kConnectUnpairableClass = 0x002580;
    119 
    120 const char FakeBluetoothDeviceClient::kDisplayPasskeyPath[] =
    121     "/fake/hci0/dev5";
    122 const char FakeBluetoothDeviceClient::kDisplayPasskeyAddress[] =
    123     "00:0F:F6:00:00:00";
    124 const char FakeBluetoothDeviceClient::kDisplayPasskeyName[] =
    125     "Bluetooth 2.1+ Keyboard";
    126 const uint32 FakeBluetoothDeviceClient::kDisplayPasskeyClass = 0x002540;
    127 
    128 const char FakeBluetoothDeviceClient::kRequestPinCodePath[] =
    129     "/fake/hci0/dev6";
    130 const char FakeBluetoothDeviceClient::kRequestPinCodeAddress[] =
    131     "00:24:BE:00:00:00";
    132 const char FakeBluetoothDeviceClient::kRequestPinCodeName[] =
    133     "PIN Device";
    134 const uint32 FakeBluetoothDeviceClient::kRequestPinCodeClass = 0x240408;
    135 
    136 const char FakeBluetoothDeviceClient::kConfirmPasskeyPath[] =
    137     "/fake/hci0/dev7";
    138 const char FakeBluetoothDeviceClient::kConfirmPasskeyAddress[] =
    139     "20:7D:74:00:00:00";
    140 const char FakeBluetoothDeviceClient::kConfirmPasskeyName[] =
    141     "Phone";
    142 const uint32 FakeBluetoothDeviceClient::kConfirmPasskeyClass = 0x7a020c;
    143 
    144 const char FakeBluetoothDeviceClient::kRequestPasskeyPath[] =
    145     "/fake/hci0/dev8";
    146 const char FakeBluetoothDeviceClient::kRequestPasskeyAddress[] =
    147     "20:7D:74:00:00:01";
    148 const char FakeBluetoothDeviceClient::kRequestPasskeyName[] =
    149     "Passkey Device";
    150 const uint32 FakeBluetoothDeviceClient::kRequestPasskeyClass = 0x7a020c;
    151 
    152 const char FakeBluetoothDeviceClient::kUnconnectableDevicePath[] =
    153     "/fake/hci0/dev9";
    154 const char FakeBluetoothDeviceClient::kUnconnectableDeviceAddress[] =
    155     "20:7D:74:00:00:02";
    156 const char FakeBluetoothDeviceClient::kUnconnectableDeviceName[] =
    157     "Unconnectable Device";
    158 const uint32 FakeBluetoothDeviceClient::kUnconnectableDeviceClass = 0x7a020c;
    159 
    160 const char FakeBluetoothDeviceClient::kUnpairableDevicePath[] =
    161     "/fake/hci0/devA";
    162 const char FakeBluetoothDeviceClient::kUnpairableDeviceAddress[] =
    163     "20:7D:74:00:00:03";
    164 const char FakeBluetoothDeviceClient::kUnpairableDeviceName[] =
    165     "Unpairable Device";
    166 const uint32 FakeBluetoothDeviceClient::kUnpairableDeviceClass = 0x002540;
    167 
    168 const char FakeBluetoothDeviceClient::kJustWorksPath[] =
    169     "/fake/hci0/devB";
    170 const char FakeBluetoothDeviceClient::kJustWorksAddress[] =
    171     "00:0C:8A:00:00:00";
    172 const char FakeBluetoothDeviceClient::kJustWorksName[] =
    173     "Just-Works Device";
    174 const uint32 FakeBluetoothDeviceClient::kJustWorksClass = 0x240428;
    175 
    176 const char FakeBluetoothDeviceClient::kLowEnergyPath[] =
    177     "/fake/hci0/devC";
    178 const char FakeBluetoothDeviceClient::kLowEnergyAddress[] =
    179     "00:1A:11:00:15:30";
    180 const char FakeBluetoothDeviceClient::kLowEnergyName[] =
    181     "Bluetooth 4.0 Heart Rate Monitor";
    182 const uint32 FakeBluetoothDeviceClient::kLowEnergyClass =
    183     0x000918;  // Major class "Health", Minor class "Heart/Pulse Rate Monitor."
    184 
    185 FakeBluetoothDeviceClient::Properties::Properties(
    186     const PropertyChangedCallback& callback)
    187     : BluetoothDeviceClient::Properties(
    188           NULL,
    189           bluetooth_device::kBluetoothDeviceInterface,
    190           callback) {
    191 }
    192 
    193 FakeBluetoothDeviceClient::Properties::~Properties() {
    194 }
    195 
    196 void FakeBluetoothDeviceClient::Properties::Get(
    197     dbus::PropertyBase* property,
    198     dbus::PropertySet::GetCallback callback) {
    199   VLOG(1) << "Get " << property->name();
    200   callback.Run(false);
    201 }
    202 
    203 void FakeBluetoothDeviceClient::Properties::GetAll() {
    204   VLOG(1) << "GetAll";
    205 }
    206 
    207 void FakeBluetoothDeviceClient::Properties::Set(
    208     dbus::PropertyBase *property,
    209     dbus::PropertySet::SetCallback callback) {
    210   VLOG(1) << "Set " << property->name();
    211   if (property->name() == trusted.name()) {
    212     callback.Run(true);
    213     property->ReplaceValueWithSetValue();
    214   } else {
    215     callback.Run(false);
    216   }
    217 }
    218 
    219 FakeBluetoothDeviceClient::FakeBluetoothDeviceClient()
    220     : simulation_interval_ms_(kSimulationIntervalMs),
    221       discovery_simulation_step_(0),
    222       incoming_pairing_simulation_step_(0),
    223       pairing_cancelled_(false),
    224       connection_monitor_started_(false) {
    225   Properties* properties = new Properties(base::Bind(
    226       &FakeBluetoothDeviceClient::OnPropertyChanged,
    227       base::Unretained(this),
    228       dbus::ObjectPath(kPairedDevicePath)));
    229   properties->address.ReplaceValue(kPairedDeviceAddress);
    230   properties->bluetooth_class.ReplaceValue(kPairedDeviceClass);
    231   properties->name.ReplaceValue("Fake Device (Name)");
    232   properties->alias.ReplaceValue(kPairedDeviceName);
    233   properties->paired.ReplaceValue(true);
    234   properties->trusted.ReplaceValue(true);
    235   properties->adapter.ReplaceValue(
    236       dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath));
    237 
    238   std::vector<std::string> uuids;
    239   uuids.push_back("00001800-0000-1000-8000-00805f9b34fb");
    240   uuids.push_back("00001801-0000-1000-8000-00805f9b34fb");
    241   properties->uuids.ReplaceValue(uuids);
    242 
    243   properties->modalias.ReplaceValue("usb:v05ACp030Dd0306");
    244 
    245   properties_map_[dbus::ObjectPath(kPairedDevicePath)] = properties;
    246   device_list_.push_back(dbus::ObjectPath(kPairedDevicePath));
    247 }
    248 
    249 FakeBluetoothDeviceClient::~FakeBluetoothDeviceClient() {
    250   // Clean up Properties structures
    251   STLDeleteValues(&properties_map_);
    252 }
    253 
    254 void FakeBluetoothDeviceClient::Init(dbus::Bus* bus) {
    255 }
    256 
    257 void FakeBluetoothDeviceClient::AddObserver(Observer* observer) {
    258   observers_.AddObserver(observer);
    259 }
    260 
    261 void FakeBluetoothDeviceClient::RemoveObserver(Observer* observer) {
    262   observers_.RemoveObserver(observer);
    263 }
    264 
    265 std::vector<dbus::ObjectPath> FakeBluetoothDeviceClient::GetDevicesForAdapter(
    266     const dbus::ObjectPath& adapter_path) {
    267   if (adapter_path ==
    268       dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath))
    269     return device_list_;
    270   else
    271     return std::vector<dbus::ObjectPath>();
    272 }
    273 
    274 FakeBluetoothDeviceClient::Properties*
    275 FakeBluetoothDeviceClient::GetProperties(const dbus::ObjectPath& object_path) {
    276   PropertiesMap::iterator iter = properties_map_.find(object_path);
    277   if (iter != properties_map_.end())
    278     return iter->second;
    279   return NULL;
    280 }
    281 
    282 void FakeBluetoothDeviceClient::Connect(
    283     const dbus::ObjectPath& object_path,
    284     const base::Closure& callback,
    285     const ErrorCallback& error_callback) {
    286   VLOG(1) << "Connect: " << object_path.value();
    287   Properties* properties = GetProperties(object_path);
    288 
    289   if (properties->connected.value() == true) {
    290     // Already connected.
    291     callback.Run();
    292     return;
    293   }
    294 
    295   if (properties->paired.value() != true &&
    296       object_path != dbus::ObjectPath(kConnectUnpairablePath) &&
    297       object_path != dbus::ObjectPath(kLowEnergyPath)) {
    298     // Must be paired.
    299     error_callback.Run(bluetooth_device::kErrorFailed, "Not paired");
    300     return;
    301   } else if (properties->paired.value() == true &&
    302              object_path == dbus::ObjectPath(kUnconnectableDevicePath)) {
    303     // Must not be paired
    304     error_callback.Run(bluetooth_device::kErrorFailed,
    305                        "Connection fails while paired");
    306     return;
    307   }
    308 
    309   // The device can be connected.
    310   properties->connected.ReplaceValue(true);
    311   callback.Run();
    312 
    313   // Expose GATT services if connected to LE device.
    314   if (object_path == dbus::ObjectPath(kLowEnergyPath)) {
    315     FakeBluetoothGattServiceClient* gatt_service_client =
    316         static_cast<FakeBluetoothGattServiceClient*>(
    317             DBusThreadManager::Get()->GetBluetoothGattServiceClient());
    318     gatt_service_client->ExposeHeartRateService(
    319         dbus::ObjectPath(kLowEnergyPath));
    320   }
    321 
    322   AddInputDeviceIfNeeded(object_path, properties);
    323 }
    324 
    325 void FakeBluetoothDeviceClient::Disconnect(
    326     const dbus::ObjectPath& object_path,
    327     const base::Closure& callback,
    328     const ErrorCallback& error_callback) {
    329   VLOG(1) << "Disconnect: " << object_path.value();
    330   Properties* properties = GetProperties(object_path);
    331 
    332   if (!properties->connected.value()) {
    333     error_callback.Run("org.bluez.Error.NotConnected", "Not Connected");
    334     return;
    335   }
    336 
    337   // Hide the Heart Rate Service if disconnected from LE device.
    338   if (object_path == dbus::ObjectPath(kLowEnergyPath)) {
    339     FakeBluetoothGattServiceClient* gatt_service_client =
    340         static_cast<FakeBluetoothGattServiceClient*>(
    341             DBusThreadManager::Get()->GetBluetoothGattServiceClient());
    342     gatt_service_client->HideHeartRateService();
    343   }
    344 
    345   callback.Run();
    346   properties->connected.ReplaceValue(false);
    347 }
    348 
    349 void FakeBluetoothDeviceClient::ConnectProfile(
    350     const dbus::ObjectPath& object_path,
    351     const std::string& uuid,
    352     const base::Closure& callback,
    353     const ErrorCallback& error_callback) {
    354   VLOG(1) << "ConnectProfile: " << object_path.value() << " " << uuid;
    355 
    356   FakeBluetoothProfileManagerClient* fake_bluetooth_profile_manager_client =
    357       static_cast<FakeBluetoothProfileManagerClient*>(
    358           DBusThreadManager::Get()->GetBluetoothProfileManagerClient());
    359   FakeBluetoothProfileServiceProvider* profile_service_provider =
    360       fake_bluetooth_profile_manager_client->GetProfileServiceProvider(uuid);
    361   if (profile_service_provider == NULL) {
    362     error_callback.Run(kNoResponseError, "Missing profile");
    363     return;
    364   }
    365 
    366   // Make a socket pair of a compatible type with the type used by Bluetooth;
    367   // spin up a thread to simulate the server side and wrap the client side in
    368   // a D-Bus file descriptor object.
    369   int socket_type = SOCK_STREAM;
    370   if (uuid == FakeBluetoothProfileManagerClient::kL2capUuid)
    371     socket_type = SOCK_SEQPACKET;
    372 
    373   int fds[2];
    374   if (socketpair(AF_UNIX, socket_type, 0, fds) < 0) {
    375     error_callback.Run(kNoResponseError, "socketpair call failed");
    376     return;
    377   }
    378 
    379   int args;
    380   args = fcntl(fds[1], F_GETFL, NULL);
    381   if (args < 0) {
    382     error_callback.Run(kNoResponseError, "failed to get socket flags");
    383     return;
    384   }
    385 
    386   args |= O_NONBLOCK;
    387   if (fcntl(fds[1], F_SETFL, args) < 0) {
    388     error_callback.Run(kNoResponseError, "failed to set socket non-blocking");
    389     return;
    390   }
    391 
    392   base::WorkerPool::GetTaskRunner(false)->PostTask(
    393       FROM_HERE,
    394       base::Bind(&SimulatedProfileSocket,
    395                  fds[0]));
    396 
    397   scoped_ptr<dbus::FileDescriptor> fd(new dbus::FileDescriptor(fds[1]));
    398 
    399   // Post the new connection to the service provider.
    400   BluetoothProfileServiceProvider::Delegate::Options options;
    401 
    402   profile_service_provider->NewConnection(
    403       object_path,
    404       fd.Pass(),
    405       options,
    406       base::Bind(&FakeBluetoothDeviceClient::ConnectionCallback,
    407                  base::Unretained(this),
    408                  object_path,
    409                  callback,
    410                  error_callback));
    411 }
    412 
    413 void FakeBluetoothDeviceClient::DisconnectProfile(
    414     const dbus::ObjectPath& object_path,
    415     const std::string& uuid,
    416     const base::Closure& callback,
    417     const ErrorCallback& error_callback) {
    418   VLOG(1) << "DisconnectProfile: " << object_path.value() << " " << uuid;
    419 
    420   FakeBluetoothProfileManagerClient* fake_bluetooth_profile_manager_client =
    421       static_cast<FakeBluetoothProfileManagerClient*>(
    422           DBusThreadManager::Get()->GetBluetoothProfileManagerClient());
    423   FakeBluetoothProfileServiceProvider* profile_service_provider =
    424       fake_bluetooth_profile_manager_client->GetProfileServiceProvider(uuid);
    425   if (profile_service_provider == NULL) {
    426     error_callback.Run(kNoResponseError, "Missing profile");
    427     return;
    428   }
    429 
    430   profile_service_provider->RequestDisconnection(
    431       object_path,
    432       base::Bind(&FakeBluetoothDeviceClient::DisconnectionCallback,
    433                  base::Unretained(this),
    434                  object_path,
    435                  callback,
    436                  error_callback));
    437 }
    438 
    439 void FakeBluetoothDeviceClient::Pair(
    440     const dbus::ObjectPath& object_path,
    441     const base::Closure& callback,
    442     const ErrorCallback& error_callback) {
    443   VLOG(1) << "Pair: " << object_path.value();
    444   Properties* properties = GetProperties(object_path);
    445 
    446   if (properties->paired.value() == true) {
    447     // Already paired.
    448     callback.Run();
    449     return;
    450   }
    451 
    452   SimulatePairing(object_path, false, callback, error_callback);
    453 }
    454 
    455 void FakeBluetoothDeviceClient::CancelPairing(
    456     const dbus::ObjectPath& object_path,
    457     const base::Closure& callback,
    458     const ErrorCallback& error_callback) {
    459   VLOG(1) << "CancelPairing: " << object_path.value();
    460   pairing_cancelled_ = true;
    461   callback.Run();
    462 }
    463 
    464 void FakeBluetoothDeviceClient::StartConnectionMonitor(
    465     const dbus::ObjectPath& object_path,
    466     const base::Closure& callback,
    467     const ErrorCallback& error_callback) {
    468   VLOG(1) << "StartConnectionMonitor: " << object_path.value();
    469   connection_monitor_started_ = true;
    470   callback.Run();
    471 }
    472 
    473 void FakeBluetoothDeviceClient::StopConnectionMonitor(
    474     const dbus::ObjectPath& object_path,
    475     const base::Closure& callback,
    476     const ErrorCallback& error_callback) {
    477   connection_monitor_started_ = false;
    478   callback.Run();
    479 }
    480 
    481 void FakeBluetoothDeviceClient::BeginDiscoverySimulation(
    482     const dbus::ObjectPath& adapter_path) {
    483   VLOG(1) << "starting discovery simulation";
    484 
    485   discovery_simulation_step_ = 1;
    486 
    487   base::MessageLoop::current()->PostDelayedTask(
    488       FROM_HERE,
    489       base::Bind(&FakeBluetoothDeviceClient::DiscoverySimulationTimer,
    490                  base::Unretained(this)),
    491       base::TimeDelta::FromMilliseconds(simulation_interval_ms_));
    492 }
    493 
    494 void FakeBluetoothDeviceClient::EndDiscoverySimulation(
    495     const dbus::ObjectPath& adapter_path) {
    496   VLOG(1) << "stopping discovery simulation";
    497   discovery_simulation_step_ = 0;
    498 }
    499 
    500 void FakeBluetoothDeviceClient::BeginIncomingPairingSimulation(
    501     const dbus::ObjectPath& adapter_path) {
    502   VLOG(1) << "starting incoming pairing simulation";
    503 
    504   incoming_pairing_simulation_step_ = 1;
    505 
    506   base::MessageLoop::current()->PostDelayedTask(
    507       FROM_HERE,
    508       base::Bind(&FakeBluetoothDeviceClient::IncomingPairingSimulationTimer,
    509                  base::Unretained(this)),
    510       base::TimeDelta::FromMilliseconds(30 * simulation_interval_ms_));
    511 }
    512 
    513 void FakeBluetoothDeviceClient::EndIncomingPairingSimulation(
    514     const dbus::ObjectPath& adapter_path) {
    515   VLOG(1) << "stopping incoming pairing simulation";
    516   incoming_pairing_simulation_step_ = 0;
    517 }
    518 
    519 void FakeBluetoothDeviceClient::SetSimulationIntervalMs(int interval_ms) {
    520   simulation_interval_ms_ = interval_ms;
    521 }
    522 
    523 void FakeBluetoothDeviceClient::CreateDevice(
    524     const dbus::ObjectPath& adapter_path,
    525     const dbus::ObjectPath& device_path) {
    526   if (std::find(device_list_.begin(),
    527                 device_list_.end(), device_path) != device_list_.end())
    528     return;
    529 
    530   Properties* properties = new Properties(base::Bind(
    531       &FakeBluetoothDeviceClient::OnPropertyChanged,
    532       base::Unretained(this),
    533       device_path));
    534   properties->adapter.ReplaceValue(adapter_path);
    535 
    536   if (device_path == dbus::ObjectPath(kLegacyAutopairPath)) {
    537     properties->address.ReplaceValue(kLegacyAutopairAddress);
    538     properties->bluetooth_class.ReplaceValue(kLegacyAutopairClass);
    539     properties->name.ReplaceValue("LegacyAutopair");
    540     properties->alias.ReplaceValue(kLegacyAutopairName);
    541 
    542     std::vector<std::string> uuids;
    543     uuids.push_back("00001124-0000-1000-8000-00805f9b34fb");
    544     properties->uuids.ReplaceValue(uuids);
    545 
    546   } else if (device_path == dbus::ObjectPath(kDisplayPinCodePath)) {
    547     properties->address.ReplaceValue(kDisplayPinCodeAddress);
    548     properties->bluetooth_class.ReplaceValue(kDisplayPinCodeClass);
    549     properties->name.ReplaceValue("DisplayPinCode");
    550     properties->alias.ReplaceValue(kDisplayPinCodeName);
    551 
    552     std::vector<std::string> uuids;
    553     uuids.push_back("00001124-0000-1000-8000-00805f9b34fb");
    554     properties->uuids.ReplaceValue(uuids);
    555 
    556   } else if (device_path == dbus::ObjectPath(kVanishingDevicePath)) {
    557     properties->address.ReplaceValue(kVanishingDeviceAddress);
    558     properties->bluetooth_class.ReplaceValue(kVanishingDeviceClass);
    559     properties->name.ReplaceValue("VanishingDevice");
    560     properties->alias.ReplaceValue(kVanishingDeviceName);
    561 
    562   } else if (device_path == dbus::ObjectPath(kConnectUnpairablePath)) {
    563     properties->address.ReplaceValue(kConnectUnpairableAddress);
    564     properties->bluetooth_class.ReplaceValue(kConnectUnpairableClass);
    565     properties->name.ReplaceValue("ConnectUnpairable");
    566     properties->alias.ReplaceValue(kConnectUnpairableName);
    567 
    568     std::vector<std::string> uuids;
    569     uuids.push_back("00001124-0000-1000-8000-00805f9b34fb");
    570     properties->uuids.ReplaceValue(uuids);
    571 
    572   } else if (device_path == dbus::ObjectPath(kDisplayPasskeyPath)) {
    573     properties->address.ReplaceValue(kDisplayPasskeyAddress);
    574     properties->bluetooth_class.ReplaceValue(kDisplayPasskeyClass);
    575     properties->name.ReplaceValue("DisplayPasskey");
    576     properties->alias.ReplaceValue(kDisplayPasskeyName);
    577 
    578     std::vector<std::string> uuids;
    579     uuids.push_back("00001124-0000-1000-8000-00805f9b34fb");
    580     properties->uuids.ReplaceValue(uuids);
    581 
    582   } else if (device_path == dbus::ObjectPath(kRequestPinCodePath)) {
    583     properties->address.ReplaceValue(kRequestPinCodeAddress);
    584     properties->bluetooth_class.ReplaceValue(kRequestPinCodeClass);
    585     properties->name.ReplaceValue("RequestPinCode");
    586     properties->alias.ReplaceValue(kRequestPinCodeName);
    587 
    588   } else if (device_path == dbus::ObjectPath(kConfirmPasskeyPath)) {
    589     properties->address.ReplaceValue(kConfirmPasskeyAddress);
    590     properties->bluetooth_class.ReplaceValue(kConfirmPasskeyClass);
    591     properties->name.ReplaceValue("ConfirmPasskey");
    592     properties->alias.ReplaceValue(kConfirmPasskeyName);
    593 
    594   } else if (device_path == dbus::ObjectPath(kRequestPasskeyPath)) {
    595     properties->address.ReplaceValue(kRequestPasskeyAddress);
    596     properties->bluetooth_class.ReplaceValue(kRequestPasskeyClass);
    597     properties->name.ReplaceValue("RequestPasskey");
    598     properties->alias.ReplaceValue(kRequestPasskeyName);
    599 
    600   } else if (device_path == dbus::ObjectPath(kUnconnectableDevicePath)) {
    601     properties->address.ReplaceValue(kUnconnectableDeviceAddress);
    602     properties->bluetooth_class.ReplaceValue(kUnconnectableDeviceClass);
    603     properties->name.ReplaceValue("UnconnectableDevice");
    604     properties->alias.ReplaceValue(kUnconnectableDeviceName);
    605 
    606   } else if (device_path == dbus::ObjectPath(kUnpairableDevicePath)) {
    607     properties->address.ReplaceValue(kUnpairableDeviceAddress);
    608     properties->bluetooth_class.ReplaceValue(kUnpairableDeviceClass);
    609     properties->name.ReplaceValue("Fake Unpairable Device");
    610     properties->alias.ReplaceValue(kUnpairableDeviceName);
    611 
    612   } else if (device_path == dbus::ObjectPath(kJustWorksPath)) {
    613     properties->address.ReplaceValue(kJustWorksAddress);
    614     properties->bluetooth_class.ReplaceValue(kJustWorksClass);
    615     properties->name.ReplaceValue("JustWorks");
    616     properties->alias.ReplaceValue(kJustWorksName);
    617 
    618   } else if (device_path == dbus::ObjectPath(kLowEnergyPath)) {
    619     properties->address.ReplaceValue(kLowEnergyAddress);
    620     properties->bluetooth_class.ReplaceValue(kLowEnergyClass);
    621     properties->name.ReplaceValue("Heart Rate Monitor");
    622     properties->alias.ReplaceValue(kLowEnergyName);
    623 
    624     std::vector<std::string> uuids;
    625     uuids.push_back(FakeBluetoothGattServiceClient::kHeartRateServiceUUID);
    626     properties->uuids.ReplaceValue(uuids);
    627 
    628   } else {
    629     NOTREACHED();
    630 
    631   }
    632 
    633   properties_map_[device_path] = properties;
    634   device_list_.push_back(device_path);
    635   FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_,
    636                     DeviceAdded(device_path));
    637 }
    638 
    639 void FakeBluetoothDeviceClient::RemoveDevice(
    640     const dbus::ObjectPath& adapter_path,
    641     const dbus::ObjectPath& device_path) {
    642   std::vector<dbus::ObjectPath>::iterator listiter =
    643       std::find(device_list_.begin(), device_list_.end(), device_path);
    644   if (listiter == device_list_.end())
    645     return;
    646 
    647   PropertiesMap::iterator iter = properties_map_.find(device_path);
    648   Properties* properties = iter->second;
    649 
    650   VLOG(1) << "removing device: " << properties->alias.value();
    651   device_list_.erase(listiter);
    652 
    653   // Remove the Input interface if it exists. This should be called before the
    654   // BluetoothDeviceClient::Observer::DeviceRemoved because it deletes the
    655   // BluetoothDeviceChromeOS object, including the device_path referenced here.
    656   FakeBluetoothInputClient* fake_bluetooth_input_client =
    657       static_cast<FakeBluetoothInputClient*>(
    658           DBusThreadManager::Get()->GetBluetoothInputClient());
    659   fake_bluetooth_input_client->RemoveInputDevice(device_path);
    660 
    661   if (device_path == dbus::ObjectPath(kLowEnergyPath)) {
    662     FakeBluetoothGattServiceClient* gatt_service_client =
    663         static_cast<FakeBluetoothGattServiceClient*>(
    664             DBusThreadManager::Get()->GetBluetoothGattServiceClient());
    665     gatt_service_client->HideHeartRateService();
    666   }
    667 
    668   FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_,
    669                     DeviceRemoved(device_path));
    670 
    671   delete properties;
    672   properties_map_.erase(iter);
    673 }
    674 
    675 void FakeBluetoothDeviceClient::OnPropertyChanged(
    676     const dbus::ObjectPath& object_path,
    677     const std::string& property_name) {
    678   VLOG(2) << "Fake Bluetooth device property changed: " << object_path.value()
    679           << ": " << property_name;
    680   FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_,
    681                     DevicePropertyChanged(object_path, property_name));
    682 }
    683 
    684 void FakeBluetoothDeviceClient::DiscoverySimulationTimer() {
    685   if (!discovery_simulation_step_)
    686     return;
    687 
    688   // Timer fires every .75s, the numbers below are arbitrary to give a feel
    689   // for a discovery process.
    690   VLOG(1) << "discovery simulation, step " << discovery_simulation_step_;
    691   if (discovery_simulation_step_ == 2) {
    692     CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
    693                  dbus::ObjectPath(kLegacyAutopairPath));
    694     CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
    695                  dbus::ObjectPath(kLowEnergyPath));
    696 
    697   } else if (discovery_simulation_step_ == 4) {
    698     UpdateDeviceRSSI(dbus::ObjectPath(kLowEnergyPath),
    699                      base::RandInt(kMinRSSI, kMaxRSSI));
    700     CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
    701                  dbus::ObjectPath(kDisplayPinCodePath));
    702     CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
    703                  dbus::ObjectPath(kVanishingDevicePath));
    704 
    705   } else if (discovery_simulation_step_ == 7) {
    706     CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
    707                  dbus::ObjectPath(kConnectUnpairablePath));
    708     UpdateDeviceRSSI(dbus::ObjectPath(kLowEnergyPath),
    709                      base::RandInt(kMinRSSI, kMaxRSSI));
    710 
    711   } else if (discovery_simulation_step_ == 8) {
    712     CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
    713                  dbus::ObjectPath(kDisplayPasskeyPath));
    714     CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
    715                  dbus::ObjectPath(kRequestPinCodePath));
    716     UpdateDeviceRSSI(dbus::ObjectPath(kLowEnergyPath),
    717                      base::RandInt(kMinRSSI, kMaxRSSI));
    718 
    719   } else if (discovery_simulation_step_ == 10) {
    720     CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
    721                  dbus::ObjectPath(kConfirmPasskeyPath));
    722     CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
    723                  dbus::ObjectPath(kRequestPasskeyPath));
    724     CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
    725                  dbus::ObjectPath(kUnconnectableDevicePath));
    726     CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
    727                  dbus::ObjectPath(kUnpairableDevicePath));
    728     CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
    729                  dbus::ObjectPath(kJustWorksPath));
    730     UpdateDeviceRSSI(dbus::ObjectPath(kLowEnergyPath),
    731                      base::RandInt(kMinRSSI, kMaxRSSI));
    732 
    733   } else if (discovery_simulation_step_ == 13) {
    734     UpdateDeviceRSSI(dbus::ObjectPath(kLowEnergyPath),
    735                      base::RandInt(kMinRSSI, kMaxRSSI));
    736     RemoveDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
    737                  dbus::ObjectPath(kVanishingDevicePath));
    738 
    739   } else if (discovery_simulation_step_ == 14) {
    740     UpdateDeviceRSSI(dbus::ObjectPath(kLowEnergyPath),
    741                      base::RandInt(kMinRSSI, kMaxRSSI));
    742     return;
    743 
    744   }
    745 
    746   ++discovery_simulation_step_;
    747   base::MessageLoop::current()->PostDelayedTask(
    748       FROM_HERE,
    749       base::Bind(&FakeBluetoothDeviceClient::DiscoverySimulationTimer,
    750                  base::Unretained(this)),
    751       base::TimeDelta::FromMilliseconds(simulation_interval_ms_));
    752 }
    753 
    754 void FakeBluetoothDeviceClient::IncomingPairingSimulationTimer() {
    755   if (!incoming_pairing_simulation_step_)
    756     return;
    757 
    758   VLOG(1) << "incoming pairing simulation, step "
    759           << incoming_pairing_simulation_step_;
    760   switch (incoming_pairing_simulation_step_) {
    761     case 1:
    762       CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
    763                    dbus::ObjectPath(kConfirmPasskeyPath));
    764       SimulatePairing(dbus::ObjectPath(kConfirmPasskeyPath), true,
    765                       base::Bind(&base::DoNothing),
    766                       base::Bind(&SimpleErrorCallback));
    767       break;
    768     case 2:
    769       CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
    770                    dbus::ObjectPath(kJustWorksPath));
    771       SimulatePairing(dbus::ObjectPath(kJustWorksPath), true,
    772                       base::Bind(&base::DoNothing),
    773                       base::Bind(&SimpleErrorCallback));
    774       break;
    775     case 3:
    776       CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
    777                    dbus::ObjectPath(kDisplayPinCodePath));
    778       SimulatePairing(dbus::ObjectPath(kDisplayPinCodePath), true,
    779                       base::Bind(&base::DoNothing),
    780                       base::Bind(&SimpleErrorCallback));
    781       break;
    782     case 4:
    783       CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
    784                    dbus::ObjectPath(kDisplayPasskeyPath));
    785       SimulatePairing(dbus::ObjectPath(kDisplayPasskeyPath), true,
    786                       base::Bind(&base::DoNothing),
    787                       base::Bind(&SimpleErrorCallback));
    788       break;
    789     case 5:
    790       CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
    791                    dbus::ObjectPath(kRequestPinCodePath));
    792       SimulatePairing(dbus::ObjectPath(kRequestPinCodePath), true,
    793                       base::Bind(&base::DoNothing),
    794                       base::Bind(&SimpleErrorCallback));
    795       break;
    796     case 6:
    797       CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
    798                    dbus::ObjectPath(kRequestPasskeyPath));
    799       SimulatePairing(dbus::ObjectPath(kRequestPasskeyPath), true,
    800                       base::Bind(&base::DoNothing),
    801                       base::Bind(&SimpleErrorCallback));
    802       break;
    803     default:
    804       return;
    805   }
    806 
    807   ++incoming_pairing_simulation_step_;
    808   base::MessageLoop::current()->PostDelayedTask(
    809       FROM_HERE,
    810       base::Bind(&FakeBluetoothDeviceClient::IncomingPairingSimulationTimer,
    811                  base::Unretained(this)),
    812       base::TimeDelta::FromMilliseconds(45 * simulation_interval_ms_));
    813 }
    814 
    815 void FakeBluetoothDeviceClient::SimulatePairing(
    816     const dbus::ObjectPath& object_path,
    817     bool incoming_request,
    818     const base::Closure& callback,
    819     const ErrorCallback& error_callback) {
    820   pairing_cancelled_ = false;
    821 
    822   FakeBluetoothAgentManagerClient* fake_bluetooth_agent_manager_client =
    823       static_cast<FakeBluetoothAgentManagerClient*>(
    824           DBusThreadManager::Get()->GetBluetoothAgentManagerClient());
    825   FakeBluetoothAgentServiceProvider* agent_service_provider =
    826       fake_bluetooth_agent_manager_client->GetAgentServiceProvider();
    827   CHECK(agent_service_provider != NULL);
    828 
    829   if (object_path == dbus::ObjectPath(kLegacyAutopairPath) ||
    830       object_path == dbus::ObjectPath(kConnectUnpairablePath) ||
    831       object_path == dbus::ObjectPath(kUnconnectableDevicePath) ||
    832       object_path == dbus::ObjectPath(kLowEnergyPath)) {
    833     // No need to call anything on the pairing delegate, just wait 3 times
    834     // the interval before acting as if the other end accepted it.
    835     base::MessageLoop::current()->PostDelayedTask(
    836         FROM_HERE,
    837         base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing,
    838                    base::Unretained(this),
    839                    object_path, callback, error_callback),
    840         base::TimeDelta::FromMilliseconds(3 * simulation_interval_ms_));
    841 
    842   } else if (object_path == dbus::ObjectPath(kDisplayPinCodePath)) {
    843     // Display a Pincode, and wait 7 times the interval before acting as
    844     // if the other end accepted it.
    845     agent_service_provider->DisplayPinCode(object_path, "123456");
    846 
    847     base::MessageLoop::current()->PostDelayedTask(
    848         FROM_HERE,
    849         base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing,
    850                    base::Unretained(this),
    851                    object_path, callback, error_callback),
    852         base::TimeDelta::FromMilliseconds(7 * simulation_interval_ms_));
    853 
    854   } else if (object_path == dbus::ObjectPath(kVanishingDevicePath)) {
    855     // The vanishing device simulates being too far away, and thus times out.
    856     base::MessageLoop::current()->PostDelayedTask(
    857         FROM_HERE,
    858         base::Bind(&FakeBluetoothDeviceClient::TimeoutSimulatedPairing,
    859                    base::Unretained(this),
    860                    object_path, error_callback),
    861         base::TimeDelta::FromMilliseconds(4 * simulation_interval_ms_));
    862 
    863   } else if (object_path == dbus::ObjectPath(kDisplayPasskeyPath)) {
    864     // Display a passkey, and each interval act as if another key was entered
    865     // for it.
    866     agent_service_provider->DisplayPasskey(object_path, 123456, 0);
    867 
    868     base::MessageLoop::current()->PostDelayedTask(
    869         FROM_HERE,
    870         base::Bind(&FakeBluetoothDeviceClient::SimulateKeypress,
    871                    base::Unretained(this),
    872                    1, object_path, callback, error_callback),
    873         base::TimeDelta::FromMilliseconds(simulation_interval_ms_));
    874 
    875   } else if (object_path == dbus::ObjectPath(kRequestPinCodePath)) {
    876     // Request a Pincode.
    877     agent_service_provider->RequestPinCode(
    878         object_path,
    879         base::Bind(&FakeBluetoothDeviceClient::PinCodeCallback,
    880                    base::Unretained(this),
    881                    object_path,
    882                    callback,
    883                    error_callback));
    884 
    885   } else if (object_path == dbus::ObjectPath(kConfirmPasskeyPath)) {
    886     // Request confirmation of a Passkey.
    887     agent_service_provider->RequestConfirmation(
    888         object_path, 123456,
    889         base::Bind(&FakeBluetoothDeviceClient::ConfirmationCallback,
    890                    base::Unretained(this),
    891                    object_path,
    892                    callback,
    893                    error_callback));
    894 
    895   } else if (object_path == dbus::ObjectPath(kRequestPasskeyPath)) {
    896     // Request a Passkey from the user.
    897     agent_service_provider->RequestPasskey(
    898         object_path,
    899         base::Bind(&FakeBluetoothDeviceClient::PasskeyCallback,
    900                    base::Unretained(this),
    901                    object_path,
    902                    callback,
    903                    error_callback));
    904 
    905   } else if (object_path == dbus::ObjectPath(kUnpairableDevicePath)) {
    906     // Fails the pairing with an org.bluez.Error.Failed error.
    907     base::MessageLoop::current()->PostDelayedTask(
    908         FROM_HERE,
    909         base::Bind(&FakeBluetoothDeviceClient::FailSimulatedPairing,
    910                    base::Unretained(this),
    911                    object_path, error_callback),
    912         base::TimeDelta::FromMilliseconds(simulation_interval_ms_));
    913 
    914   } else if (object_path == dbus::ObjectPath(kJustWorksPath)) {
    915     if (incoming_request) {
    916       agent_service_provider->RequestAuthorization(
    917           object_path,
    918           base::Bind(&FakeBluetoothDeviceClient::ConfirmationCallback,
    919                      base::Unretained(this),
    920                      object_path,
    921                      callback,
    922                      error_callback));
    923 
    924     } else {
    925       // No need to call anything on the pairing delegate, just wait 3 times
    926       // the interval before acting as if the other end accepted it.
    927       base::MessageLoop::current()->PostDelayedTask(
    928           FROM_HERE,
    929           base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing,
    930                      base::Unretained(this),
    931                      object_path, callback, error_callback),
    932           base::TimeDelta::FromMilliseconds(3 * simulation_interval_ms_));
    933 
    934     }
    935 
    936   } else {
    937     error_callback.Run(kNoResponseError, "No pairing fake");
    938   }
    939 }
    940 
    941 void FakeBluetoothDeviceClient::CompleteSimulatedPairing(
    942     const dbus::ObjectPath& object_path,
    943     const base::Closure& callback,
    944     const ErrorCallback& error_callback) {
    945   VLOG(1) << "CompleteSimulatedPairing: " << object_path.value();
    946   if (pairing_cancelled_) {
    947     pairing_cancelled_ = false;
    948 
    949     error_callback.Run(bluetooth_device::kErrorAuthenticationCanceled,
    950                        "Cancelled");
    951   } else {
    952     Properties* properties = GetProperties(object_path);
    953 
    954     properties->paired.ReplaceValue(true);
    955     callback.Run();
    956 
    957     AddInputDeviceIfNeeded(object_path, properties);
    958   }
    959 }
    960 
    961 void FakeBluetoothDeviceClient::TimeoutSimulatedPairing(
    962     const dbus::ObjectPath& object_path,
    963     const ErrorCallback& error_callback) {
    964   VLOG(1) << "TimeoutSimulatedPairing: " << object_path.value();
    965 
    966   error_callback.Run(bluetooth_device::kErrorAuthenticationTimeout,
    967                      "Timed out");
    968 }
    969 
    970 void FakeBluetoothDeviceClient::CancelSimulatedPairing(
    971     const dbus::ObjectPath& object_path,
    972     const ErrorCallback& error_callback) {
    973   VLOG(1) << "CancelSimulatedPairing: " << object_path.value();
    974 
    975   error_callback.Run(bluetooth_device::kErrorAuthenticationCanceled,
    976                      "Canceled");
    977 }
    978 
    979 void FakeBluetoothDeviceClient::RejectSimulatedPairing(
    980     const dbus::ObjectPath& object_path,
    981     const ErrorCallback& error_callback) {
    982   VLOG(1) << "RejectSimulatedPairing: " << object_path.value();
    983 
    984   error_callback.Run(bluetooth_device::kErrorAuthenticationRejected,
    985                      "Rejected");
    986 }
    987 
    988 void FakeBluetoothDeviceClient::FailSimulatedPairing(
    989     const dbus::ObjectPath& object_path,
    990     const ErrorCallback& error_callback) {
    991   VLOG(1) << "FailSimulatedPairing: " << object_path.value();
    992 
    993   error_callback.Run(bluetooth_device::kErrorFailed, "Failed");
    994 }
    995 
    996 void FakeBluetoothDeviceClient::AddInputDeviceIfNeeded(
    997     const dbus::ObjectPath& object_path,
    998     Properties* properties) {
    999   // If the paired device is a HID device based on it's bluetooth class,
   1000   // simulate the Input interface.
   1001   FakeBluetoothInputClient* fake_bluetooth_input_client =
   1002       static_cast<FakeBluetoothInputClient*>(
   1003           DBusThreadManager::Get()->GetBluetoothInputClient());
   1004 
   1005   if ((properties->bluetooth_class.value() & 0x001f03) == 0x000500)
   1006     fake_bluetooth_input_client->AddInputDevice(object_path);
   1007 }
   1008 
   1009 void FakeBluetoothDeviceClient::UpdateDeviceRSSI(
   1010     const dbus::ObjectPath& object_path,
   1011     int16 rssi) {
   1012   PropertiesMap::iterator iter = properties_map_.find(object_path);
   1013   if (iter == properties_map_.end()) {
   1014     VLOG(2) << "Fake device does not exist: " << object_path.value();
   1015     return;
   1016   }
   1017   Properties* properties = iter->second;
   1018   DCHECK(properties);
   1019   properties->rssi.ReplaceValue(rssi);
   1020 }
   1021 
   1022 void FakeBluetoothDeviceClient::PinCodeCallback(
   1023     const dbus::ObjectPath& object_path,
   1024     const base::Closure& callback,
   1025     const ErrorCallback& error_callback,
   1026     BluetoothAgentServiceProvider::Delegate::Status status,
   1027     const std::string& pincode) {
   1028   VLOG(1) << "PinCodeCallback: " << object_path.value();
   1029 
   1030   if (status == BluetoothAgentServiceProvider::Delegate::SUCCESS) {
   1031     base::MessageLoop::current()->PostDelayedTask(
   1032         FROM_HERE,
   1033         base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing,
   1034                    base::Unretained(this),
   1035                    object_path, callback, error_callback),
   1036         base::TimeDelta::FromMilliseconds(3 * simulation_interval_ms_));
   1037 
   1038   } else if (status == BluetoothAgentServiceProvider::Delegate::CANCELLED) {
   1039     base::MessageLoop::current()->PostDelayedTask(
   1040         FROM_HERE,
   1041         base::Bind(&FakeBluetoothDeviceClient::CancelSimulatedPairing,
   1042                    base::Unretained(this),
   1043                    object_path, error_callback),
   1044         base::TimeDelta::FromMilliseconds(simulation_interval_ms_));
   1045 
   1046   } else if (status == BluetoothAgentServiceProvider::Delegate::REJECTED) {
   1047     base::MessageLoop::current()->PostDelayedTask(
   1048         FROM_HERE,
   1049         base::Bind(&FakeBluetoothDeviceClient::RejectSimulatedPairing,
   1050                    base::Unretained(this),
   1051                    object_path, error_callback),
   1052         base::TimeDelta::FromMilliseconds(simulation_interval_ms_));
   1053 
   1054   }
   1055 }
   1056 
   1057 void FakeBluetoothDeviceClient::PasskeyCallback(
   1058     const dbus::ObjectPath& object_path,
   1059     const base::Closure& callback,
   1060     const ErrorCallback& error_callback,
   1061     BluetoothAgentServiceProvider::Delegate::Status status,
   1062     uint32 passkey) {
   1063   VLOG(1) << "PasskeyCallback: " << object_path.value();
   1064 
   1065   if (status == BluetoothAgentServiceProvider::Delegate::SUCCESS) {
   1066     base::MessageLoop::current()->PostDelayedTask(
   1067         FROM_HERE,
   1068         base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing,
   1069                    base::Unretained(this),
   1070                    object_path, callback, error_callback),
   1071         base::TimeDelta::FromMilliseconds(3 * simulation_interval_ms_));
   1072 
   1073   } else if (status == BluetoothAgentServiceProvider::Delegate::CANCELLED) {
   1074     base::MessageLoop::current()->PostDelayedTask(
   1075         FROM_HERE,
   1076         base::Bind(&FakeBluetoothDeviceClient::CancelSimulatedPairing,
   1077                    base::Unretained(this),
   1078                    object_path, error_callback),
   1079         base::TimeDelta::FromMilliseconds(simulation_interval_ms_));
   1080 
   1081   } else if (status == BluetoothAgentServiceProvider::Delegate::REJECTED) {
   1082     base::MessageLoop::current()->PostDelayedTask(
   1083         FROM_HERE,
   1084         base::Bind(&FakeBluetoothDeviceClient::RejectSimulatedPairing,
   1085                    base::Unretained(this),
   1086                    object_path, error_callback),
   1087         base::TimeDelta::FromMilliseconds(simulation_interval_ms_));
   1088 
   1089   }
   1090 }
   1091 
   1092 void FakeBluetoothDeviceClient::ConfirmationCallback(
   1093     const dbus::ObjectPath& object_path,
   1094     const base::Closure& callback,
   1095     const ErrorCallback& error_callback,
   1096     BluetoothAgentServiceProvider::Delegate::Status status) {
   1097   VLOG(1) << "ConfirmationCallback: " << object_path.value();
   1098 
   1099   if (status == BluetoothAgentServiceProvider::Delegate::SUCCESS) {
   1100     base::MessageLoop::current()->PostDelayedTask(
   1101         FROM_HERE,
   1102         base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing,
   1103                    base::Unretained(this),
   1104                    object_path, callback, error_callback),
   1105         base::TimeDelta::FromMilliseconds(3 * simulation_interval_ms_));
   1106 
   1107   } else if (status == BluetoothAgentServiceProvider::Delegate::CANCELLED) {
   1108     base::MessageLoop::current()->PostDelayedTask(
   1109         FROM_HERE,
   1110         base::Bind(&FakeBluetoothDeviceClient::CancelSimulatedPairing,
   1111                    base::Unretained(this),
   1112                    object_path, error_callback),
   1113         base::TimeDelta::FromMilliseconds(simulation_interval_ms_));
   1114 
   1115   } else if (status == BluetoothAgentServiceProvider::Delegate::REJECTED) {
   1116     base::MessageLoop::current()->PostDelayedTask(
   1117         FROM_HERE,
   1118         base::Bind(&FakeBluetoothDeviceClient::RejectSimulatedPairing,
   1119                    base::Unretained(this),
   1120                    object_path, error_callback),
   1121         base::TimeDelta::FromMilliseconds(simulation_interval_ms_));
   1122 
   1123   }
   1124 }
   1125 
   1126 void FakeBluetoothDeviceClient::SimulateKeypress(
   1127     uint16 entered,
   1128     const dbus::ObjectPath& object_path,
   1129     const base::Closure& callback,
   1130     const ErrorCallback& error_callback) {
   1131   VLOG(1) << "SimulateKeypress " << entered << ": " << object_path.value();
   1132 
   1133   FakeBluetoothAgentManagerClient* fake_bluetooth_agent_manager_client =
   1134       static_cast<FakeBluetoothAgentManagerClient*>(
   1135           DBusThreadManager::Get()->GetBluetoothAgentManagerClient());
   1136   FakeBluetoothAgentServiceProvider* agent_service_provider =
   1137       fake_bluetooth_agent_manager_client->GetAgentServiceProvider();
   1138 
   1139   // The agent service provider object could have been destroyed after the
   1140   // pairing is canceled.
   1141   if (!agent_service_provider)
   1142     return;
   1143 
   1144   agent_service_provider->DisplayPasskey(object_path, 123456, entered);
   1145 
   1146   if (entered < 7) {
   1147     base::MessageLoop::current()->PostDelayedTask(
   1148         FROM_HERE,
   1149         base::Bind(&FakeBluetoothDeviceClient::SimulateKeypress,
   1150                    base::Unretained(this),
   1151                    entered + 1, object_path, callback, error_callback),
   1152         base::TimeDelta::FromMilliseconds(simulation_interval_ms_));
   1153 
   1154   } else {
   1155     base::MessageLoop::current()->PostDelayedTask(
   1156         FROM_HERE,
   1157         base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing,
   1158                    base::Unretained(this),
   1159                    object_path, callback, error_callback),
   1160         base::TimeDelta::FromMilliseconds(simulation_interval_ms_));
   1161 
   1162   }
   1163 }
   1164 
   1165 void FakeBluetoothDeviceClient::ConnectionCallback(
   1166     const dbus::ObjectPath& object_path,
   1167     const base::Closure& callback,
   1168     const ErrorCallback& error_callback,
   1169     BluetoothProfileServiceProvider::Delegate::Status status) {
   1170   VLOG(1) << "ConnectionCallback: " << object_path.value();
   1171 
   1172   if (status == BluetoothProfileServiceProvider::Delegate::SUCCESS) {
   1173     callback.Run();
   1174   } else if (status == BluetoothProfileServiceProvider::Delegate::CANCELLED) {
   1175     // TODO(keybuk): tear down this side of the connection
   1176     error_callback.Run(bluetooth_device::kErrorFailed, "Canceled");
   1177   } else if (status == BluetoothProfileServiceProvider::Delegate::REJECTED) {
   1178     // TODO(keybuk): tear down this side of the connection
   1179     error_callback.Run(bluetooth_device::kErrorFailed, "Rejected");
   1180   }
   1181 }
   1182 
   1183 void FakeBluetoothDeviceClient::DisconnectionCallback(
   1184     const dbus::ObjectPath& object_path,
   1185     const base::Closure& callback,
   1186     const ErrorCallback& error_callback,
   1187     BluetoothProfileServiceProvider::Delegate::Status status) {
   1188   VLOG(1) << "DisconnectionCallback: " << object_path.value();
   1189 
   1190   if (status == BluetoothProfileServiceProvider::Delegate::SUCCESS) {
   1191     // TODO(keybuk): tear down this side of the connection
   1192     callback.Run();
   1193   } else if (status == BluetoothProfileServiceProvider::Delegate::CANCELLED) {
   1194     error_callback.Run(bluetooth_device::kErrorFailed, "Canceled");
   1195   } else if (status == BluetoothProfileServiceProvider::Delegate::REJECTED) {
   1196     error_callback.Run(bluetooth_device::kErrorFailed, "Rejected");
   1197   }
   1198 }
   1199 
   1200 }  // namespace chromeos
   1201