1 //
2 //  Copyright 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 #include <base/run_loop.h>
23 
24 #include "service/adapter.h"
25 #include "service/hal/bluetooth_av_interface.h"
26 #include "service/hal/bluetooth_avrcp_interface.h"
27 #include "service/hal/bluetooth_gatt_interface.h"
28 #include "service/hal/bluetooth_interface.h"
29 #include "service/ipc/ipc_manager.h"
30 #include "service/settings.h"
31 #include "service/switches.h"
32 
33 namespace bluetooth {
34 
35 namespace {
36 
37 // The global Daemon instance.
38 Daemon* g_daemon = nullptr;
39 
40 class DaemonImpl : public Daemon, public ipc::IPCManager::Delegate {
41  public:
DaemonImpl()42   DaemonImpl() : initialized_(false) {}
43 
~DaemonImpl()44   ~DaemonImpl() override {
45     if (!initialized_) return;
46 
47     CleanUpBluetoothStack();
48   }
49 
StartMainLoop()50   void StartMainLoop() override { base::RunLoop().Run(); }
51 
GetSettings() const52   Settings* GetSettings() const override { return settings_.get(); }
53 
GetMessageLoop() const54   base::MessageLoop* GetMessageLoop() const override {
55     return message_loop_.get();
56   }
57 
58  private:
59   // ipc::IPCManager::Delegate implementation:
OnIPCHandlerStarted(ipc::IPCManager::Type)60   void OnIPCHandlerStarted(ipc::IPCManager::Type /* type */) override {
61     if (!settings_->EnableOnStart()) return;
62     adapter_->Enable();
63   }
64 
OnIPCHandlerStopped(ipc::IPCManager::Type)65   void OnIPCHandlerStopped(ipc::IPCManager::Type /* type */) override {
66     // Do nothing.
67   }
68 
StartUpBluetoothInterfaces()69   bool StartUpBluetoothInterfaces() {
70     if (!hal::BluetoothInterface::Initialize()) goto failed;
71 
72     if (!hal::BluetoothGattInterface::Initialize()) goto failed;
73 
74     if (!hal::BluetoothAvInterface::Initialize()) goto failed;
75 
76     if (!hal::BluetoothAvrcpInterface::Initialize()) goto failed;
77 
78     return true;
79 
80   failed:
81     ShutDownBluetoothInterfaces();
82     return false;
83   }
84 
ShutDownBluetoothInterfaces()85   void ShutDownBluetoothInterfaces() {
86     if (hal::BluetoothGattInterface::IsInitialized())
87       hal::BluetoothGattInterface::CleanUp();
88     if (hal::BluetoothInterface::IsInitialized())
89       hal::BluetoothInterface::CleanUp();
90     if (hal::BluetoothAvInterface::IsInitialized())
91       hal::BluetoothAvInterface::CleanUp();
92     if (hal::BluetoothAvrcpInterface::IsInitialized())
93       hal::BluetoothAvrcpInterface::CleanUp();
94   }
95 
CleanUpBluetoothStack()96   void CleanUpBluetoothStack() {
97     // The Adapter object needs to be cleaned up before the HAL interfaces.
98     ipc_manager_.reset();
99     adapter_.reset();
100     ShutDownBluetoothInterfaces();
101   }
102 
SetUpIPC()103   bool SetUpIPC() {
104     // If an IPC socket path was given, initialize IPC with it. Otherwise
105     // initialize Binder IPC.
106     if (settings_->UseSocketIPC()) {
107       if (!ipc_manager_->Start(ipc::IPCManager::TYPE_LINUX, this)) {
108         LOG(ERROR) << "Failed to set up UNIX domain-socket IPCManager";
109         return false;
110       }
111       return true;
112     }
113 
114 #if !defined(OS_GENERIC)
115     if (!ipc_manager_->Start(ipc::IPCManager::TYPE_BINDER, this)) {
116       LOG(ERROR) << "Failed to set up Binder IPCManager";
117       return false;
118     }
119 #else
120     if (!ipc_manager_->Start(ipc::IPCManager::TYPE_DBUS, this)) {
121       LOG(ERROR) << "Failed to set up DBus IPCManager";
122       return false;
123     }
124 #endif
125 
126     return true;
127   }
128 
Init()129   bool Init() override {
130     CHECK(!initialized_);
131     message_loop_.reset(new base::MessageLoop());
132 
133     settings_.reset(new Settings());
134     if (!settings_->Init()) {
135       LOG(ERROR) << "Failed to set up Settings";
136       return false;
137     }
138 
139     if (!StartUpBluetoothInterfaces()) {
140       LOG(ERROR) << "Failed to set up HAL Bluetooth interfaces";
141       return false;
142     }
143 
144     adapter_ = Adapter::Create();
145     ipc_manager_.reset(new ipc::IPCManager(adapter_.get()));
146 
147     if (!SetUpIPC()) {
148       CleanUpBluetoothStack();
149       return false;
150     }
151 
152     initialized_ = true;
153     LOG(INFO) << "Daemon initialized";
154 
155     return true;
156   }
157 
158   bool initialized_;
159   std::unique_ptr<base::MessageLoop> message_loop_;
160   std::unique_ptr<Settings> settings_;
161   std::unique_ptr<Adapter> adapter_;
162   std::unique_ptr<ipc::IPCManager> ipc_manager_;
163 
164   DISALLOW_COPY_AND_ASSIGN(DaemonImpl);
165 };
166 
167 }  // namespace
168 
169 // static
Initialize()170 bool Daemon::Initialize() {
171   CHECK(!g_daemon);
172 
173   g_daemon = new DaemonImpl();
174   if (g_daemon->Init()) return true;
175 
176   LOG(ERROR) << "Failed to initialize the Daemon object";
177 
178   delete g_daemon;
179   g_daemon = nullptr;
180 
181   return false;
182 }
183 
184 // static
ShutDown()185 void Daemon::ShutDown() {
186   CHECK(g_daemon);
187   delete g_daemon;
188   g_daemon = nullptr;
189 }
190 
191 // static
InitializeForTesting(Daemon * test_daemon)192 void Daemon::InitializeForTesting(Daemon* test_daemon) {
193   CHECK(test_daemon);
194   CHECK(!g_daemon);
195 
196   g_daemon = test_daemon;
197 }
198 
199 // static
Get()200 Daemon* Daemon::Get() {
201   CHECK(g_daemon);
202   return g_daemon;
203 }
204 
205 }  // namespace bluetooth
206