// // Copyright 2015 Google, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at: // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "service/daemon.h" #include #include #include #include "abstract_message_loop.h" #include "service/adapter.h" #include "service/hal/bluetooth_av_interface.h" #include "service/hal/bluetooth_avrcp_interface.h" #include "service/hal/bluetooth_gatt_interface.h" #include "service/hal/bluetooth_interface.h" #include "service/ipc/ipc_manager.h" #include "service/settings.h" #include "service/switches.h" namespace bluetooth { namespace { // The global Daemon instance. Daemon* g_daemon = nullptr; class DaemonImpl : public Daemon, public ipc::IPCManager::Delegate { public: DaemonImpl() : initialized_(false) {} ~DaemonImpl() override { if (!initialized_) return; CleanUpBluetoothStack(); } void StartMainLoop() override { base::RunLoop().Run(); } Settings* GetSettings() const override { return settings_.get(); } btbase::AbstractMessageLoop* GetMessageLoop() const override { return message_loop_.get(); } private: // ipc::IPCManager::Delegate implementation: void OnIPCHandlerStarted(ipc::IPCManager::Type /* type */) override { if (!settings_->EnableOnStart()) return; adapter_->Enable(); } void OnIPCHandlerStopped(ipc::IPCManager::Type /* type */) override { // Do nothing. } bool StartUpBluetoothInterfaces() { if (!hal::BluetoothInterface::Initialize()) goto failed; if (!hal::BluetoothGattInterface::Initialize()) goto failed; if (!hal::BluetoothAvInterface::Initialize()) goto failed; if (!hal::BluetoothAvrcpInterface::Initialize()) goto failed; return true; failed: ShutDownBluetoothInterfaces(); return false; } void ShutDownBluetoothInterfaces() { if (hal::BluetoothGattInterface::IsInitialized()) hal::BluetoothGattInterface::CleanUp(); if (hal::BluetoothInterface::IsInitialized()) hal::BluetoothInterface::CleanUp(); if (hal::BluetoothAvInterface::IsInitialized()) hal::BluetoothAvInterface::CleanUp(); if (hal::BluetoothAvrcpInterface::IsInitialized()) hal::BluetoothAvrcpInterface::CleanUp(); } void CleanUpBluetoothStack() { // The Adapter object needs to be cleaned up before the HAL interfaces. ipc_manager_.reset(); adapter_.reset(); ShutDownBluetoothInterfaces(); } bool SetUpIPC() { // If an IPC socket path was given, initialize IPC with it. Otherwise // initialize Binder IPC. if (settings_->UseSocketIPC()) { if (!ipc_manager_->Start(ipc::IPCManager::TYPE_LINUX, this)) { LOG(ERROR) << "Failed to set up UNIX domain-socket IPCManager"; return false; } return true; } #if !defined(OS_GENERIC) if (!ipc_manager_->Start(ipc::IPCManager::TYPE_BINDER, this)) { LOG(ERROR) << "Failed to set up Binder IPCManager"; return false; } #else if (!ipc_manager_->Start(ipc::IPCManager::TYPE_DBUS, this)) { LOG(ERROR) << "Failed to set up DBus IPCManager"; return false; } #endif return true; } bool Init() override { CHECK(!initialized_); message_loop_.reset(new btbase::AbstractMessageLoop()); settings_.reset(new Settings()); if (!settings_->Init()) { LOG(ERROR) << "Failed to set up Settings"; return false; } if (!StartUpBluetoothInterfaces()) { LOG(ERROR) << "Failed to set up HAL Bluetooth interfaces"; return false; } adapter_ = Adapter::Create(); ipc_manager_.reset(new ipc::IPCManager(adapter_.get())); if (!SetUpIPC()) { CleanUpBluetoothStack(); return false; } initialized_ = true; LOG(INFO) << "Daemon initialized"; return true; } bool initialized_; std::unique_ptr message_loop_; std::unique_ptr settings_; std::unique_ptr adapter_; std::unique_ptr ipc_manager_; DISALLOW_COPY_AND_ASSIGN(DaemonImpl); }; } // namespace // static bool Daemon::Initialize() { CHECK(!g_daemon); g_daemon = new DaemonImpl(); if (g_daemon->Init()) return true; LOG(ERROR) << "Failed to initialize the Daemon object"; delete g_daemon; g_daemon = nullptr; return false; } // static void Daemon::ShutDown() { CHECK(g_daemon); delete g_daemon; g_daemon = nullptr; } // static void Daemon::InitializeForTesting(Daemon* test_daemon) { CHECK(test_daemon); CHECK(!g_daemon); g_daemon = test_daemon; } // static Daemon* Daemon::Get() { CHECK(g_daemon); return g_daemon; } } // namespace bluetooth