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