1//
2//  Copyright (C) 2015 Google, Inc.
3//
4//  Licensed under the Apache License, Version 2.0 (the "License");
5//  you may not use this file except in compliance with the License.
6//  You may obtain a copy of the License at:
7//
8//  http://www.apache.org/licenses/LICENSE-2.0
9//
10//  Unless required by applicable law or agreed to in writing, software
11//  distributed under the License is distributed on an "AS IS" BASIS,
12//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13//  See the License for the specific language governing permissions and
14//  limitations under the License.
15//
16
17#include "service/daemon.h"
18
19#include <memory>
20
21#include <base/logging.h>
22
23#include "service/adapter.h"
24#include "service/hal/bluetooth_gatt_interface.h"
25#include "service/hal/bluetooth_interface.h"
26#include "service/ipc/ipc_manager.h"
27#include "service/settings.h"
28#include "service/switches.h"
29
30namespace bluetooth {
31
32namespace {
33
34// The global Daemon instance.
35Daemon* g_daemon = nullptr;
36
37class DaemonImpl : public Daemon, public ipc::IPCManager::Delegate {
38 public:
39  DaemonImpl() : initialized_(false) {}
40
41  ~DaemonImpl() override {
42    if (!initialized_) return;
43
44    CleanUpBluetoothStack();
45  }
46
47  void StartMainLoop() override { message_loop_->Run(); }
48
49  Settings* GetSettings() const override { return settings_.get(); }
50
51  base::MessageLoop* GetMessageLoop() const override {
52    return message_loop_.get();
53  }
54
55 private:
56  // ipc::IPCManager::Delegate implementation:
57  void OnIPCHandlerStarted(ipc::IPCManager::Type /* type */) override {
58    if (!settings_->EnableOnStart()) return;
59    adapter_->Enable(false /* start_restricted */);
60  }
61
62  void OnIPCHandlerStopped(ipc::IPCManager::Type /* type */) override {
63    // Do nothing.
64  }
65
66  bool StartUpBluetoothInterfaces() {
67    if (!hal::BluetoothInterface::Initialize()) goto failed;
68
69    if (!hal::BluetoothGattInterface::Initialize()) goto failed;
70
71    return true;
72
73  failed:
74    ShutDownBluetoothInterfaces();
75    return false;
76  }
77
78  void ShutDownBluetoothInterfaces() {
79    if (hal::BluetoothGattInterface::IsInitialized())
80      hal::BluetoothGattInterface::CleanUp();
81    if (hal::BluetoothInterface::IsInitialized())
82      hal::BluetoothInterface::CleanUp();
83  }
84
85  void CleanUpBluetoothStack() {
86    // The Adapter object needs to be cleaned up before the HAL interfaces.
87    ipc_manager_.reset();
88    adapter_.reset();
89    ShutDownBluetoothInterfaces();
90  }
91
92  bool SetUpIPC() {
93    // If an IPC socket path was given, initialize IPC with it. Otherwise
94    // initialize Binder IPC.
95    if (settings_->UseSocketIPC()) {
96      if (!ipc_manager_->Start(ipc::IPCManager::TYPE_LINUX, this)) {
97        LOG(ERROR) << "Failed to set up UNIX domain-socket IPCManager";
98        return false;
99      }
100      return true;
101    }
102
103#if !defined(OS_GENERIC)
104    if (!ipc_manager_->Start(ipc::IPCManager::TYPE_BINDER, this)) {
105      LOG(ERROR) << "Failed to set up Binder IPCManager";
106      return false;
107    }
108#else
109    if (!ipc_manager_->Start(ipc::IPCManager::TYPE_DBUS, this)) {
110      LOG(ERROR) << "Failed to set up DBus IPCManager";
111      return false;
112    }
113#endif
114
115    return true;
116  }
117
118  bool Init() override {
119    CHECK(!initialized_);
120    message_loop_.reset(new base::MessageLoop());
121
122    settings_.reset(new Settings());
123    if (!settings_->Init()) {
124      LOG(ERROR) << "Failed to set up Settings";
125      return false;
126    }
127
128    if (!StartUpBluetoothInterfaces()) {
129      LOG(ERROR) << "Failed to set up HAL Bluetooth interfaces";
130      return false;
131    }
132
133    adapter_ = Adapter::Create();
134    ipc_manager_.reset(new ipc::IPCManager(adapter_.get()));
135
136    if (!SetUpIPC()) {
137      CleanUpBluetoothStack();
138      return false;
139    }
140
141    initialized_ = true;
142    LOG(INFO) << "Daemon initialized";
143
144    return true;
145  }
146
147  bool initialized_;
148  std::unique_ptr<base::MessageLoop> message_loop_;
149  std::unique_ptr<Settings> settings_;
150  std::unique_ptr<Adapter> adapter_;
151  std::unique_ptr<ipc::IPCManager> ipc_manager_;
152
153  DISALLOW_COPY_AND_ASSIGN(DaemonImpl);
154};
155
156}  // namespace
157
158// static
159bool Daemon::Initialize() {
160  CHECK(!g_daemon);
161
162  g_daemon = new DaemonImpl();
163  if (g_daemon->Init()) return true;
164
165  LOG(ERROR) << "Failed to initialize the Daemon object";
166
167  delete g_daemon;
168  g_daemon = nullptr;
169
170  return false;
171}
172
173// static
174void Daemon::ShutDown() {
175  CHECK(g_daemon);
176  delete g_daemon;
177  g_daemon = nullptr;
178}
179
180// static
181void Daemon::InitializeForTesting(Daemon* test_daemon) {
182  CHECK(test_daemon);
183  CHECK(!g_daemon);
184
185  g_daemon = test_daemon;
186}
187
188// static
189Daemon* Daemon::Get() {
190  CHECK(g_daemon);
191  return g_daemon;
192}
193
194}  // namespace bluetooth
195