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
29namespace bluetooth {
30
31namespace {
32
33// The global Daemon instance.
34Daemon* g_daemon = nullptr;
35
36class DaemonImpl : public Daemon {
37 public:
38  DaemonImpl() : initialized_(false) {}
39
40  ~DaemonImpl() override {
41    if (!initialized_) return;
42
43    CleanUpBluetoothStack();
44  }
45
46  void StartMainLoop() override { message_loop_->Run(); }
47
48  Settings* GetSettings() const override { return settings_.get(); }
49
50  base::MessageLoop* GetMessageLoop() const override {
51    return message_loop_.get();
52  }
53
54 private:
55  bool StartUpBluetoothInterfaces() {
56    if (!hal::BluetoothInterface::Initialize()) goto failed;
57
58    if (!hal::BluetoothGattInterface::Initialize()) goto failed;
59
60    return true;
61
62  failed:
63    ShutDownBluetoothInterfaces();
64    return false;
65  }
66
67  void ShutDownBluetoothInterfaces() {
68    if (hal::BluetoothGattInterface::IsInitialized())
69      hal::BluetoothGattInterface::CleanUp();
70    if (hal::BluetoothInterface::IsInitialized())
71      hal::BluetoothInterface::CleanUp();
72  }
73
74  void CleanUpBluetoothStack() {
75    // The Adapter object needs to be cleaned up before the HAL interfaces.
76    ipc_manager_.reset();
77    adapter_.reset();
78    ShutDownBluetoothInterfaces();
79  }
80
81  bool SetUpIPC() {
82    // If an IPC socket path was given, initialize IPC with it. Otherwise
83    // initialize Binder IPC.
84    if (settings_->UseSocketIPC()) {
85      if (!ipc_manager_->Start(ipc::IPCManager::TYPE_LINUX, nullptr)) {
86        LOG(ERROR) << "Failed to set up UNIX domain-socket IPCManager";
87        return false;
88      }
89    } else if (!ipc_manager_->Start(ipc::IPCManager::TYPE_BINDER, nullptr)) {
90      LOG(ERROR) << "Failed to set up Binder IPCManager";
91      return false;
92    }
93
94    return true;
95  }
96
97  bool Init() override {
98    CHECK(!initialized_);
99    message_loop_.reset(new base::MessageLoop());
100
101    settings_.reset(new Settings());
102    if (!settings_->Init()) {
103      LOG(ERROR) << "Failed to set up Settings";
104      return false;
105    }
106
107    if (!StartUpBluetoothInterfaces()) {
108      LOG(ERROR) << "Failed to set up HAL Bluetooth interfaces";
109      return false;
110    }
111
112    adapter_ = Adapter::Create();
113    ipc_manager_.reset(new ipc::IPCManager(adapter_.get()));
114
115    if (!SetUpIPC()) {
116      CleanUpBluetoothStack();
117      return false;
118    }
119
120    initialized_ = true;
121    LOG(INFO) << "Daemon initialized";
122
123    return true;
124  }
125
126  bool initialized_;
127  std::unique_ptr<base::MessageLoop> message_loop_;
128  std::unique_ptr<Settings> settings_;
129  std::unique_ptr<Adapter> adapter_;
130  std::unique_ptr<ipc::IPCManager> ipc_manager_;
131
132  DISALLOW_COPY_AND_ASSIGN(DaemonImpl);
133};
134
135}  // namespace
136
137// static
138bool Daemon::Initialize() {
139  CHECK(!g_daemon);
140
141  g_daemon = new DaemonImpl();
142  if (g_daemon->Init()) return true;
143
144  LOG(ERROR) << "Failed to initialize the Daemon object";
145
146  delete g_daemon;
147  g_daemon = nullptr;
148
149  return false;
150}
151
152// static
153void Daemon::ShutDown() {
154  CHECK(g_daemon);
155  delete g_daemon;
156  g_daemon = nullptr;
157}
158
159// static
160void Daemon::InitializeForTesting(Daemon* test_daemon) {
161  CHECK(test_daemon);
162  CHECK(!g_daemon);
163
164  g_daemon = test_daemon;
165}
166
167// static
168Daemon* Daemon::Get() {
169  CHECK(g_daemon);
170  return g_daemon;
171}
172
173}  // namespace bluetooth
174