blob: 99f9265cf72f6ee339ae722ed37b34157da6617d [file] [log] [blame]
// Copyright 2020 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 "iioservice/daemon/daemon.h"
#include <sysexits.h>
#include <memory>
#include <utility>
#include <base/bind.h>
#include <base/files/file_util.h>
#include <base/files/scoped_file.h>
#include <chromeos/dbus/service_constants.h>
#include <dbus/bus.h>
#include <dbus/message.h>
#include <dbus/object_proxy.h>
#include <mojo/core/embedder/embedder.h>
#include <mojo/public/cpp/system/invitation.h>
#include "iioservice/daemon/sensor_hal_server_impl.h"
#include "iioservice/include/common.h"
namespace {
constexpr int kDelayBootstrapInMilliseconds = 1000;
}
namespace iioservice {
Daemon::Daemon() : weak_ptr_factory_(this) {}
Daemon::~Daemon() {}
int Daemon::OnInit() {
int exit_code = DBusDaemon::OnInit();
if (exit_code != EX_OK)
return exit_code;
mojo::core::Init();
ipc_support_ = std::make_unique<mojo::core::ScopedIPCSupport>(
base::ThreadTaskRunnerHandle::Get(),
mojo::core::ScopedIPCSupport::ShutdownPolicy::CLEAN);
ServerBootstrapMojoConnection();
return 0;
}
void Daemon::ServerBootstrapMojoConnection() {
// Get or create the ExportedObject for the IIO service.
dbus::ObjectProxy* proxy = bus_->GetObjectProxy(
::mojo_connection_service::kMojoConnectionServiceServiceName,
dbus::ObjectPath(
::mojo_connection_service::kMojoConnectionServiceServicePath));
dbus::MethodCall method_call(
::mojo_connection_service::kMojoConnectionServiceInterface,
::mojo_connection_service::kBootstrapMojoConnectionForIioServiceMethod);
dbus::MessageWriter writer(&method_call);
proxy->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
base::BindOnce(&Daemon::OnBootstrapResponse,
weak_ptr_factory_.GetWeakPtr()));
}
void Daemon::ReconnectWithDelay() {
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE,
base::BindOnce(&Daemon::ServerBootstrapMojoConnection,
weak_ptr_factory_.GetWeakPtr()),
base::TimeDelta::FromMilliseconds(kDelayBootstrapInMilliseconds));
}
void Daemon::OnBootstrapResponse(dbus::Response* response) {
DCHECK(!sensor_hal_server_.get());
if (!response) {
LOG(ERROR) << ::mojo_connection_service::kMojoConnectionServiceServiceName
<< " D-Bus call to "
<< ::mojo_connection_service::
kBootstrapMojoConnectionForIioServiceMethod
<< " failed";
ReconnectWithDelay();
return;
}
base::ScopedFD file_handle;
dbus::MessageReader reader(response);
if (!reader.PopFileDescriptor(&file_handle)) {
LOG(ERROR) << "Couldn't extract file descriptor from D-Bus call";
ReconnectWithDelay();
return;
}
if (!file_handle.is_valid()) {
LOG(ERROR) << "ScopedFD extracted from D-Bus call was invalid (i.e. empty)";
ReconnectWithDelay();
return;
}
if (!base::SetCloseOnExec(file_handle.get())) {
PLOG(ERROR) << "Failed setting FD_CLOEXEC on file descriptor";
ReconnectWithDelay();
return;
}
// Connect to mojo in the requesting process.
mojo::IncomingInvitation invitation =
mojo::IncomingInvitation::Accept(mojo::PlatformChannelEndpoint(
mojo::PlatformHandle(std::move(file_handle))));
LOGF(INFO) << "Broker connected";
// Bind primordial message pipe to a SensorHalServer implementation.
sensor_hal_server_ = SensorHalServerImpl::Create(
base::ThreadTaskRunnerHandle::Get(),
mojo::PendingReceiver<cros::mojom::SensorHalServer>(
invitation.ExtractMessagePipe(
::mojo_connection_service::
kBootstrapMojoConnectionForIioServiceChannelToken)),
base::Bind(&Daemon::OnMojoDisconnection, weak_ptr_factory_.GetWeakPtr()));
}
void Daemon::OnMojoDisconnection() {
LOGF(WARNING) << "Chromium crashes. Try to establish a new DBus connection.";
sensor_hal_server_.reset();
ReconnectWithDelay();
}
} // namespace iioservice