1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file.
4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/dbus/fake_bluetooth_adapter_client.h"
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/bind.h"
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/logging.h"
99ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h"
10eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/dbus/dbus_thread_manager.h"
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/dbus/fake_bluetooth_device_client.h"
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "dbus/object_path.h"
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "third_party/cros_system_api/dbus/service_constants.h"
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace chromeos {
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
18a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace {
19a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
20a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Default interval for delayed tasks.
21a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const int kSimulationIntervalMs = 750;
22a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
23a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}  // namespace
24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char FakeBluetoothAdapterClient::kAdapterPath[] =
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    "/fake/hci0";
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char FakeBluetoothAdapterClient::kAdapterName[] =
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    "Fake Adapter";
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char FakeBluetoothAdapterClient::kAdapterAddress[] =
30cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    "01:1A:2B:1A:2B:03";
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char FakeBluetoothAdapterClient::kSecondAdapterPath[] =
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    "/fake/hci1";
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char FakeBluetoothAdapterClient::kSecondAdapterName[] =
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    "Second Fake Adapter";
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char FakeBluetoothAdapterClient::kSecondAdapterAddress[] =
37cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    "00:DE:51:10:01:00";
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)FakeBluetoothAdapterClient::Properties::Properties(
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const PropertyChangedCallback& callback)
417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    : BluetoothAdapterClient::Properties(
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        NULL,
43868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        bluetooth_adapter::kBluetoothAdapterInterface,
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        callback) {
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)FakeBluetoothAdapterClient::Properties::~Properties() {
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void FakeBluetoothAdapterClient::Properties::Get(
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    dbus::PropertyBase* property,
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    dbus::PropertySet::GetCallback callback) {
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  VLOG(1) << "Get " << property->name();
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.Run(false);
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void FakeBluetoothAdapterClient::Properties::GetAll() {
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  VLOG(1) << "GetAll";
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void FakeBluetoothAdapterClient::Properties::Set(
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    dbus::PropertyBase *property,
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    dbus::PropertySet::SetCallback callback) {
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  VLOG(1) << "Set " << property->name();
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (property->name() == powered.name() ||
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      property->name() == alias.name() ||
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      property->name() == discoverable.name() ||
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      property->name() == discoverable_timeout.name()) {
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    callback.Run(true);
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    property->ReplaceValueWithSetValue();
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else {
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    callback.Run(false);
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)FakeBluetoothAdapterClient::FakeBluetoothAdapterClient()
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : visible_(true),
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      second_visible_(false),
79a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      discovering_count_(0),
80a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      simulation_interval_ms_(kSimulationIntervalMs) {
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  properties_.reset(new Properties(base::Bind(
82424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      &FakeBluetoothAdapterClient::OnPropertyChanged, base::Unretained(this))));
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  properties_->address.ReplaceValue(kAdapterAddress);
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  properties_->name.ReplaceValue("Fake Adapter (Name)");
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  properties_->alias.ReplaceValue(kAdapterName);
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  properties_->pairable.ReplaceValue(true);
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  second_properties_.reset(new Properties(base::Bind(
90424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      &FakeBluetoothAdapterClient::OnPropertyChanged, base::Unretained(this))));
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  second_properties_->address.ReplaceValue(kSecondAdapterAddress);
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  second_properties_->name.ReplaceValue("Second Fake Adapter (Name)");
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  second_properties_->alias.ReplaceValue(kSecondAdapterName);
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  second_properties_->pairable.ReplaceValue(true);
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)FakeBluetoothAdapterClient::~FakeBluetoothAdapterClient() {
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
101424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void FakeBluetoothAdapterClient::Init(dbus::Bus* bus) {
102424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
103424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void FakeBluetoothAdapterClient::AddObserver(Observer* observer) {
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  observers_.AddObserver(observer);
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void FakeBluetoothAdapterClient::RemoveObserver(Observer* observer) {
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  observers_.RemoveObserver(observer);
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)std::vector<dbus::ObjectPath> FakeBluetoothAdapterClient::GetAdapters() {
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::vector<dbus::ObjectPath> object_paths;
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (visible_)
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    object_paths.push_back(dbus::ObjectPath(kAdapterPath));
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (second_visible_)
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    object_paths.push_back(dbus::ObjectPath(kSecondAdapterPath));
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return object_paths;
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)FakeBluetoothAdapterClient::Properties*
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)FakeBluetoothAdapterClient::GetProperties(const dbus::ObjectPath& object_path) {
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (object_path == dbus::ObjectPath(kAdapterPath))
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return properties_.get();
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  else if (object_path == dbus::ObjectPath(kSecondAdapterPath))
126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return second_properties_.get();
127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  else
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return NULL;
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void FakeBluetoothAdapterClient::StartDiscovery(
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const dbus::ObjectPath& object_path,
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::Closure& callback,
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const ErrorCallback& error_callback) {
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (object_path != dbus::ObjectPath(kAdapterPath)) {
136a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    PostDelayedTask(base::Bind(error_callback, kNoResponseError, ""));
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ++discovering_count_;
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  VLOG(1) << "StartDiscovery: " << object_path.value() << ", "
142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          << "count is now " << discovering_count_;
143a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  PostDelayedTask(callback);
144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (discovering_count_ == 1) {
146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    properties_->discovering.ReplaceValue(true);
147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    FakeBluetoothDeviceClient* device_client =
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        static_cast<FakeBluetoothDeviceClient*>(
1507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)            DBusThreadManager::Get()->GetBluetoothDeviceClient());
151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    device_client->BeginDiscoverySimulation(dbus::ObjectPath(kAdapterPath));
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void FakeBluetoothAdapterClient::StopDiscovery(
156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const dbus::ObjectPath& object_path,
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::Closure& callback,
158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const ErrorCallback& error_callback) {
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (object_path != dbus::ObjectPath(kAdapterPath)) {
160a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    PostDelayedTask(base::Bind(error_callback, kNoResponseError, ""));
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!discovering_count_) {
165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    LOG(WARNING) << "StopDiscovery called when not discovering";
166a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    PostDelayedTask(base::Bind(error_callback, kNoResponseError, ""));
167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  --discovering_count_;
171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  VLOG(1) << "StopDiscovery: " << object_path.value() << ", "
172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          << "count is now " << discovering_count_;
173a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  PostDelayedTask(callback);
174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (discovering_count_ == 0) {
176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    FakeBluetoothDeviceClient* device_client =
177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        static_cast<FakeBluetoothDeviceClient*>(
1787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)            DBusThreadManager::Get()->GetBluetoothDeviceClient());
179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    device_client->EndDiscoverySimulation(dbus::ObjectPath(kAdapterPath));
180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
181a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (simulation_interval_ms_ > 100) {
182a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      device_client->BeginIncomingPairingSimulation(
183a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          dbus::ObjectPath(kAdapterPath));
184a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
185a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    properties_->discovering.ReplaceValue(false);
187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void FakeBluetoothAdapterClient::RemoveDevice(
191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const dbus::ObjectPath& object_path,
192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const dbus::ObjectPath& device_path,
193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::Closure& callback,
194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const ErrorCallback& error_callback) {
195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (object_path != dbus::ObjectPath(kAdapterPath)) {
196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    error_callback.Run(kNoResponseError, "");
197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  VLOG(1) << "RemoveDevice: " << object_path.value()
201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          << " " << device_path.value();
202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.Run();
203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  FakeBluetoothDeviceClient* device_client =
205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      static_cast<FakeBluetoothDeviceClient*>(
2067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          DBusThreadManager::Get()->GetBluetoothDeviceClient());
207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  device_client->RemoveDevice(dbus::ObjectPath(kAdapterPath), device_path);
208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
210a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void FakeBluetoothAdapterClient::SetSimulationIntervalMs(int interval_ms) {
211a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  simulation_interval_ms_ = interval_ms;
212a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
213a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void FakeBluetoothAdapterClient::SetVisible(
215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool visible) {
216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (visible && !visible_) {
217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Adapter becoming visible
218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    visible_ = visible;
219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    FOR_EACH_OBSERVER(BluetoothAdapterClient::Observer, observers_,
221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                      AdapterAdded(dbus::ObjectPath(kAdapterPath)));
222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else if (visible_ && !visible) {
224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Adapter becoming invisible
225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    visible_ = visible;
226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    FOR_EACH_OBSERVER(BluetoothAdapterClient::Observer, observers_,
228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                      AdapterRemoved(dbus::ObjectPath(kAdapterPath)));
229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void FakeBluetoothAdapterClient::SetSecondVisible(
233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool visible) {
234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (visible && !second_visible_) {
235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Second adapter becoming visible
236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    second_visible_ = visible;
237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    FOR_EACH_OBSERVER(BluetoothAdapterClient::Observer, observers_,
239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                      AdapterAdded(dbus::ObjectPath(kSecondAdapterPath)));
240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else if (second_visible_ && !visible) {
242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Second adapter becoming invisible
243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    second_visible_ = visible;
244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    FOR_EACH_OBSERVER(BluetoothAdapterClient::Observer, observers_,
246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                      AdapterRemoved(dbus::ObjectPath(kSecondAdapterPath)));
247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void FakeBluetoothAdapterClient::OnPropertyChanged(
251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& property_name) {
252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (property_name == properties_->powered.name() &&
253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      !properties_->powered.value()) {
254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    VLOG(1) << "Adapter powered off";
255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (discovering_count_) {
257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      discovering_count_ = 0;
258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      properties_->discovering.ReplaceValue(false);
259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
260c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
261c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  FOR_EACH_OBSERVER(BluetoothAdapterClient::Observer, observers_,
263c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    AdapterPropertyChanged(dbus::ObjectPath(kAdapterPath),
264c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                           property_name));
265c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
267a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void FakeBluetoothAdapterClient::PostDelayedTask(
268a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const base::Closure& callback) {
269a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::MessageLoop::current()->PostDelayedTask(
270a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      FROM_HERE, callback,
271a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      base::TimeDelta::FromMilliseconds(simulation_interval_ms_));
272a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
273a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace chromeos
275