blob: 7fd9b2b1ea219a83fe4853aa8ff4eada185b6b64 [file] [log] [blame]
Arman Ugurayfe65fb72015-07-24 19:14:42 -07001//
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
Arman Ugurayf8881fe2015-08-04 12:56:56 -070019#include <memory>
20
Arman Ugurayfe65fb72015-07-24 19:14:42 -070021#include <base/logging.h>
22
Arman Ugurayd6a4b0c2015-08-13 17:01:07 -070023#include "service/adapter.h"
Arman Uguray9ded7b62015-08-31 16:29:07 -070024#include "service/hal/bluetooth_gatt_interface.h"
Arman Ugurayd6a4b0c2015-08-13 17:01:07 -070025#include "service/hal/bluetooth_interface.h"
Arman Ugurayfe65fb72015-07-24 19:14:42 -070026#include "service/ipc/ipc_manager.h"
27#include "service/settings.h"
Bailey Forreste8e6c6b2017-06-07 14:50:08 -070028#include "service/switches.h"
Arman Ugurayfe65fb72015-07-24 19:14:42 -070029
30namespace bluetooth {
31
32namespace {
33
34// The global Daemon instance.
35Daemon* g_daemon = nullptr;
36
Bailey Forreste8e6c6b2017-06-07 14:50:08 -070037class DaemonImpl : public Daemon, public ipc::IPCManager::Delegate {
Arman Ugurayf8881fe2015-08-04 12:56:56 -070038 public:
Myles Watson911d1ae2016-11-28 16:44:40 -080039 DaemonImpl() : initialized_(false) {}
Arman Ugurayd6a4b0c2015-08-13 17:01:07 -070040
41 ~DaemonImpl() override {
Myles Watson911d1ae2016-11-28 16:44:40 -080042 if (!initialized_) return;
Arman Ugurayd6a4b0c2015-08-13 17:01:07 -070043
44 CleanUpBluetoothStack();
45 }
Arman Ugurayf8881fe2015-08-04 12:56:56 -070046
Myles Watson911d1ae2016-11-28 16:44:40 -080047 void StartMainLoop() override { message_loop_->Run(); }
Arman Ugurayf8881fe2015-08-04 12:56:56 -070048
Myles Watson911d1ae2016-11-28 16:44:40 -080049 Settings* GetSettings() const override { return settings_.get(); }
Arman Ugurayf8881fe2015-08-04 12:56:56 -070050
51 base::MessageLoop* GetMessageLoop() const override {
52 return message_loop_.get();
53 }
54
55 private:
Bailey Forreste8e6c6b2017-06-07 14:50:08 -070056 // 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
Arman Uguray9ded7b62015-08-31 16:29:07 -070066 bool StartUpBluetoothInterfaces() {
Myles Watson911d1ae2016-11-28 16:44:40 -080067 if (!hal::BluetoothInterface::Initialize()) goto failed;
Arman Uguray9ded7b62015-08-31 16:29:07 -070068
Myles Watson911d1ae2016-11-28 16:44:40 -080069 if (!hal::BluetoothGattInterface::Initialize()) goto failed;
Arman Uguray9ded7b62015-08-31 16:29:07 -070070
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
Arman Ugurayd6a4b0c2015-08-13 17:01:07 -070085 void CleanUpBluetoothStack() {
86 // The Adapter object needs to be cleaned up before the HAL interfaces.
87 ipc_manager_.reset();
88 adapter_.reset();
Arman Uguray9ded7b62015-08-31 16:29:07 -070089 ShutDownBluetoothInterfaces();
Arman Ugurayd6a4b0c2015-08-13 17:01:07 -070090 }
Arman Ugurayf8881fe2015-08-04 12:56:56 -070091
Arman Ugurayd6a4b0c2015-08-13 17:01:07 -070092 bool SetUpIPC() {
Arman Ugurayb2286f32015-08-05 21:19:02 -070093 // If an IPC socket path was given, initialize IPC with it. Otherwise
94 // initialize Binder IPC.
95 if (settings_->UseSocketIPC()) {
Bailey Forreste8e6c6b2017-06-07 14:50:08 -070096 if (!ipc_manager_->Start(ipc::IPCManager::TYPE_LINUX, this)) {
Arman Ugurayb2286f32015-08-05 21:19:02 -070097 LOG(ERROR) << "Failed to set up UNIX domain-socket IPCManager";
98 return false;
99 }
Jakub Pawlowski79c2ff92016-10-31 12:56:12 -0700100 return true;
101 }
102
103#if !defined(OS_GENERIC)
Bailey Forreste8e6c6b2017-06-07 14:50:08 -0700104 if (!ipc_manager_->Start(ipc::IPCManager::TYPE_BINDER, this)) {
Arman Ugurayb2286f32015-08-05 21:19:02 -0700105 LOG(ERROR) << "Failed to set up Binder IPCManager";
Arman Ugurayf8881fe2015-08-04 12:56:56 -0700106 return false;
107 }
Jakub Pawlowski79c2ff92016-10-31 12:56:12 -0700108#else
Bailey Forreste8e6c6b2017-06-07 14:50:08 -0700109 if (!ipc_manager_->Start(ipc::IPCManager::TYPE_DBUS, this)) {
Jakub Pawlowski79c2ff92016-10-31 12:56:12 -0700110 LOG(ERROR) << "Failed to set up DBus IPCManager";
111 return false;
112 }
113#endif
Arman Ugurayf8881fe2015-08-04 12:56:56 -0700114
115 return true;
116 }
117
Arman Ugurayd6a4b0c2015-08-13 17:01:07 -0700118 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
Arman Uguray9ded7b62015-08-31 16:29:07 -0700128 if (!StartUpBluetoothInterfaces()) {
129 LOG(ERROR) << "Failed to set up HAL Bluetooth interfaces";
Arman Ugurayd6a4b0c2015-08-13 17:01:07 -0700130 return false;
131 }
132
Arman Uguray0a0d3932015-11-19 15:57:57 -0800133 adapter_ = Adapter::Create();
Arman Ugurayd6a4b0c2015-08-13 17:01:07 -0700134 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_;
Arman Ugurayf8881fe2015-08-04 12:56:56 -0700148 std::unique_ptr<base::MessageLoop> message_loop_;
149 std::unique_ptr<Settings> settings_;
Arman Ugurayd6a4b0c2015-08-13 17:01:07 -0700150 std::unique_ptr<Adapter> adapter_;
Arman Ugurayf8881fe2015-08-04 12:56:56 -0700151 std::unique_ptr<ipc::IPCManager> ipc_manager_;
152
153 DISALLOW_COPY_AND_ASSIGN(DaemonImpl);
154};
155
Arman Ugurayfe65fb72015-07-24 19:14:42 -0700156} // namespace
157
158// static
159bool Daemon::Initialize() {
160 CHECK(!g_daemon);
161
Arman Ugurayf8881fe2015-08-04 12:56:56 -0700162 g_daemon = new DaemonImpl();
Myles Watson911d1ae2016-11-28 16:44:40 -0800163 if (g_daemon->Init()) return true;
Arman Ugurayfe65fb72015-07-24 19:14:42 -0700164
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);
Arman Ugurayfe65fb72015-07-24 19:14:42 -0700176 delete g_daemon;
Arman Ugurayf8881fe2015-08-04 12:56:56 -0700177 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;
Arman Ugurayfe65fb72015-07-24 19:14:42 -0700186}
187
188// static
189Daemon* Daemon::Get() {
190 CHECK(g_daemon);
191 return g_daemon;
192}
193
Arman Ugurayfe65fb72015-07-24 19:14:42 -0700194} // namespace bluetooth