blob: 1e6740ce8b50f0125a69c6dc65b85a94daae1b34 [file] [log] [blame]
// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "bluetooth/newblued/newblue_daemon.h"
#include <memory>
#include <utility>
#include <sysexits.h>
#include <base/logging.h>
#include <base/threading/platform_thread.h>
#include <chromeos/dbus/service_constants.h>
#include "bluetooth/common/dbus_daemon.h"
namespace bluetooth {
NewblueDaemon::NewblueDaemon(std::unique_ptr<Newblue> newblue,
bool is_idle_mode)
: is_idle_mode_(is_idle_mode),
newblue_(std::move(newblue)),
weak_ptr_factory_(this) {}
bool NewblueDaemon::Init(scoped_refptr<dbus::Bus> bus,
DBusDaemon* dbus_daemon) {
bus_ = bus;
dbus_daemon_ = dbus_daemon;
if (!bus_->RequestOwnershipAndBlock(
newblue_object_manager::kNewblueObjectManagerServiceName,
dbus::Bus::REQUIRE_PRIMARY)) {
LOG(ERROR) << "Failed to acquire D-Bus name ownership: "
<< newblue_object_manager::kNewblueObjectManagerServiceName;
}
if (is_idle_mode_) {
LOG(INFO) << "LE splitter not enabled, newblued running in idle mode.";
LOG(INFO) << "To enable, run 'newblue enable' in crosh and reboot.";
return true;
}
auto exported_object_manager =
std::make_unique<brillo::dbus_utils::ExportedObjectManager>(
bus_, dbus::ObjectPath(
newblue_object_manager::kNewblueObjectManagerServicePath));
exported_object_manager_wrapper_ =
std::make_unique<ExportedObjectManagerWrapper>(
bus_, std::move(exported_object_manager));
if (!newblue_->Init()) {
LOG(ERROR) << "Failed initializing NewBlue";
return false;
}
adapter_interface_handler_ = std::make_unique<AdapterInterfaceHandler>(
bus_, exported_object_manager_wrapper_.get());
device_interface_handler_ = std::make_unique<DeviceInterfaceHandler>(
bus_, newblue_.get(), exported_object_manager_wrapper_.get());
advertising_manager_interface_handler_ =
std::make_unique<AdvertisingManagerInterfaceHandler>(
newblue_->libnewblue(), bus_, exported_object_manager_wrapper_.get());
agent_manager_interface_handler_ =
std::make_unique<AgentManagerInterfaceHandler>(
bus_, exported_object_manager_wrapper_.get());
debug_manager_ = std::make_unique<NewblueDebugManager>(bus_);
debug_manager_->Init();
agent_manager_interface_handler_->Init();
newblue_->RegisterPairingAgent(agent_manager_interface_handler_.get());
gatt_ =
std::make_unique<Gatt>(newblue_.get(), device_interface_handler_.get());
gatt_interface_handler_ = std::make_unique<GattInterfaceHandler>(
bus_, newblue_.get(), exported_object_manager_wrapper_.get(),
gatt_.get());
gatt_interface_handler_->Init();
if (!newblue_->ListenReadyForUp(base::Bind(&NewblueDaemon::OnHciReadyForUp,
base::Unretained(this)))) {
LOG(ERROR) << "Error listening to HCI ready for up";
return false;
}
LOG(INFO) << "newblued initialized";
return true;
}
void NewblueDaemon::Shutdown() {
newblue_->UnregisterPairingAgent();
gatt_.reset();
newblue_.reset();
agent_manager_interface_handler_.reset();
device_interface_handler_.reset();
exported_object_manager_wrapper_.reset();
debug_manager_.reset();
}
void NewblueDaemon::OnHciReadyForUp() {
VLOG(1) << "NewBlue ready for up";
// Workaround to avoid immediately bringing up the stack as this may result
// in chip hang.
// TODO(sonnysasaka): Remove this sleep when the kernel LE splitter bug
// is fixed(https://crbug.com/852446).
base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(1));
if (!newblue_->BringUp()) {
LOG(ERROR) << "error bringing up NewBlue";
dbus_daemon_->QuitWithExitCode(EX_UNAVAILABLE);
return;
}
adapter_interface_handler_->Init(device_interface_handler_.get(),
newblue_.get());
stack_sync_monitor_.RegisterBluezDownCallback(
bus_.get(),
base::Bind(&NewblueDaemon::OnBluezDown, weak_ptr_factory_.GetWeakPtr()));
LOG(INFO) << "NewBlue is up";
advertising_manager_interface_handler_->Init();
if (!device_interface_handler_->Init()) {
LOG(ERROR) << "Failed to initialize device interface";
dbus_daemon_->QuitWithExitCode(EX_UNAVAILABLE);
return;
}
}
void NewblueDaemon::OnBluezDown() {
ExportedInterface* adapter_interface =
exported_object_manager_wrapper_->GetExportedInterface(
dbus::ObjectPath(kAdapterObjectPath),
bluetooth_adapter::kBluetoothAdapterInterface);
if (!adapter_interface)
return;
LOG(INFO) << "Quitting due to BlueZ down detected";
adapter_interface
->EnsureExportedPropertyRegistered<bool>(
bluetooth_adapter::kStackSyncQuittingProperty)
->SetValue(true);
exit(0); // TODO(crbug/873905): Quit gracefully after this is fixed.
}
} // namespace bluetooth