blob: 1cc4e3caf3458b4a42cac67b4f6b3455a291d3f1 [file] [log] [blame]
// Copyright 2020 The ChromiumOS Authors
// 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 <string>
#include <utility>
#include <base/check.h>
#include <base/files/file_util.h>
#include <base/files/scoped_file.h>
#include <base/functional/bind.h>
#include <base/task/single_thread_task_runner.h>
#include <chromeos/dbus/service_constants.h>
#include <chromeos/mojo/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 <mojo_service_manager/lib/connect.h>
#include "iioservice/daemon/iio_sensor.h"
#include "iioservice/daemon/sensor_metrics.h"
#include "iioservice/include/common.h"
#include "iioservice/include/dbus-constants.h"
namespace iioservice {
Daemon::~Daemon() {
iio_sensor_.reset();
SensorMetrics::Shutdown();
}
int Daemon::OnInit() {
int exit_code = DBusDaemon::OnInit();
if (exit_code != EX_OK)
return exit_code;
SensorMetrics::Initialize();
InitDBus();
mojo::core::Init();
ipc_support_ = std::make_unique<mojo::core::ScopedIPCSupport>(
base::SingleThreadTaskRunner::GetCurrentDefault(),
mojo::core::ScopedIPCSupport::ShutdownPolicy::CLEAN);
ConnectToMojoServiceManager();
return 0;
}
void Daemon::InitDBus() {
dbus::ExportedObject* const iioservice_exported_object =
bus_->GetExportedObject(
dbus::ObjectPath(::iioservice::kIioserviceServicePath));
CHECK(iioservice_exported_object);
// Register a handler of the MemsSetupDone method.
CHECK(iioservice_exported_object->ExportMethodAndBlock(
::iioservice::kIioserviceInterface, ::iioservice::kMemsSetupDoneMethod,
base::BindRepeating(&Daemon::HandleMemsSetupDone,
weak_factory_.GetWeakPtr())));
// Register a handler of the MemsRemoveDone method.
CHECK(iioservice_exported_object->ExportMethodAndBlock(
::iioservice::kIioserviceInterface, ::iioservice::kMemsRemoveDoneMethod,
base::BindRepeating(&Daemon::HandleMemsRemoveDone,
weak_factory_.GetWeakPtr())));
// Take ownership of the IIO service.
CHECK(bus_->RequestOwnershipAndBlock(::iioservice::kIioserviceServiceName,
dbus::Bus::REQUIRE_PRIMARY));
}
void Daemon::ConnectToMojoServiceManager() {
auto service_manager_remote =
chromeos::mojo_service_manager::ConnectToMojoServiceManager();
if (!service_manager_remote) {
LOGF(FATAL) << "Failed to connect to Mojo Service Manager";
}
service_manager_.Bind(std::move(service_manager_remote));
service_manager_.set_disconnect_with_reason_handler(base::BindOnce(
&Daemon::ServiceManagerDisconnected, base::Unretained(this)));
mojo::PendingRemote<chromeos::mojo_service_manager::mojom::ServiceProvider>
service_provider_remote;
iio_sensor_ = IioSensor::Create(
base::SingleThreadTaskRunner::GetCurrentDefault(),
service_provider_remote.InitWithNewPipeAndPassReceiver());
service_manager_->Register(chromeos::mojo_services::kIioSensor,
std::move(service_provider_remote));
}
void Daemon::ServiceManagerDisconnected(uint32_t custom_reason,
const std::string& description) {
auto error = static_cast<chromeos::mojo_service_manager::mojom::ErrorCode>(
custom_reason);
LOG(ERROR) << "ServiceManagerDisconnected, error: " << error
<< ", description: " << description;
// As iioservice couldn't handle any error properly, and it still might need
// to rely on the Mojo Service Manager's restart, quit and restart iioservice
// directly.
Quit();
}
void Daemon::HandleMemsSetupDone(
dbus::MethodCall* method_call,
dbus::ExportedObject::ResponseSender response_sender) {
if (iio_sensor_) {
dbus::MessageReader reader(method_call);
int32_t iio_device_id;
if (!reader.PopInt32(&iio_device_id) || iio_device_id < 0) {
LOGF(ERROR) << "Couldn't extract iio_device_id (int32_t) from D-Bus call";
std::move(response_sender)
.Run(dbus::ErrorResponse::FromMethodCall(
method_call, DBUS_ERROR_FAILED,
"Couldn't extract iio_device_id (int32_t)"));
return;
}
iio_sensor_->OnDeviceAdded(iio_device_id);
}
// Send success response.
std::move(response_sender).Run(dbus::Response::FromMethodCall(method_call));
}
void Daemon::HandleMemsRemoveDone(
dbus::MethodCall* method_call,
dbus::ExportedObject::ResponseSender response_sender) {
if (iio_sensor_) {
dbus::MessageReader reader(method_call);
int32_t iio_device_id;
if (!reader.PopInt32(&iio_device_id) || iio_device_id < 0) {
LOGF(ERROR) << "Couldn't extract iio_device_id (int32_t) from D-Bus call";
std::move(response_sender)
.Run(dbus::ErrorResponse::FromMethodCall(
method_call, DBUS_ERROR_FAILED,
"Couldn't extract iio_device_id (int32_t)"));
return;
}
iio_sensor_->OnDeviceRemoved(iio_device_id);
}
// Send success response.
std::move(response_sender).Run(dbus::Response::FromMethodCall(method_call));
}
} // namespace iioservice