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