blob: a3e1979971ea3890bc5bc6f07ee63270ea944506 [file] [log] [blame]
// Copyright 2021 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.
#ifndef RMAD_DBUS_SERVICE_H_
#define RMAD_DBUS_SERVICE_H_
#include <memory>
#include <string>
#include <utility>
#include <base/files/file_path.h>
#include <brillo/daemons/dbus_daemon.h>
#include <brillo/dbus/data_serialization.h>
#include <brillo/dbus/dbus_method_response.h>
#include <brillo/dbus/dbus_object.h>
#include <brillo/dbus/dbus_signal.h>
#include <dbus/bus.h>
#include "rmad/rmad_interface.h"
#include "rmad/system/tpm_manager_client.h"
namespace brillo {
namespace dbus_utils {
void AppendValueToWriter(dbus::MessageWriter* writer,
const rmad::HardwareVerificationResult& value);
void AppendValueToWriter(dbus::MessageWriter* writer,
const rmad::CalibrationComponentStatus& value);
void AppendValueToWriter(dbus::MessageWriter* writer,
const rmad::ProvisionStatus& value);
void AppendValueToWriter(dbus::MessageWriter* writer,
const rmad::FinalizeStatus& value);
bool PopValueFromReader(dbus::MessageReader* reader,
rmad::HardwareVerificationResult* value);
bool PopValueFromReader(dbus::MessageReader* reader,
rmad::CalibrationComponentStatus* value);
bool PopValueFromReader(dbus::MessageReader* reader,
rmad::ProvisionStatus* value);
bool PopValueFromReader(dbus::MessageReader* reader,
rmad::FinalizeStatus* value);
} // namespace dbus_utils
} // namespace brillo
namespace rmad {
class DBusService : public brillo::DBusServiceDaemon {
public:
explicit DBusService(RmadInterface* rmad_interface);
// Used to inject a mock bus.
DBusService(const scoped_refptr<dbus::Bus>& bus,
RmadInterface* rmad_interface,
const base::FilePath& state_file_path,
std::unique_ptr<TpmManagerClient> tpm_manager_client);
DBusService(const DBusService&) = delete;
DBusService& operator=(const DBusService&) = delete;
~DBusService() override = default;
bool SendErrorSignal(RmadErrorCode error);
bool SendHardwareVerificationResultSignal(
const HardwareVerificationResult& result);
bool SendUpdateRoFirmwareStatusSignal(UpdateRoFirmwareStatus status);
bool SendCalibrationSetupSignal(CalibrationSetupInstruction instruction);
bool SendCalibrationOverallSignal(CalibrationOverallStatus status);
bool SendCalibrationProgressSignal(CalibrationComponentStatus status);
bool SendProvisionProgressSignal(const ProvisionStatus& status);
bool SendFinalizeProgressSignal(const FinalizeStatus& status);
bool SendHardwareWriteProtectionStateSignal(bool enabled);
bool SendPowerCableStateSignal(bool plugged_in);
void SetTestMode() { test_mode_ = true; }
protected:
// brillo::DBusServiceDaemon overrides.
int OnEventLoopStarted() override;
void RegisterDBusObjectsAsync(
brillo::dbus_utils::AsyncEventSequencer* sequencer) override;
// Provide callbacks to rmad_interface.
void SetUpInterfaceCallbacks();
private:
friend class DBusServiceTest;
bool CheckRmaCriteria() const;
bool SetUpInterface();
template <typename... Types>
using DBusMethodResponse = brillo::dbus_utils::DBusMethodResponse<Types...>;
// Template for handling D-Bus methods with a request.
template <typename RequestType, typename ReplyType>
using HandlerFunction = void (RmadInterface::*)(
const RequestType&, base::OnceCallback<void(const ReplyType&)>);
template <typename RequestType,
typename ReplyType,
DBusService::HandlerFunction<RequestType, ReplyType> func>
void DelegateToInterface(
std::unique_ptr<DBusMethodResponse<ReplyType>> response,
const RequestType& request) {
if (is_rma_required_ && !SetUpInterface()) {
SendErrorSignal(RMAD_ERROR_DAEMON_INITIALIZATION_FAILED);
return;
}
(rmad_interface_->*func)(
request, base::BindOnce(&DBusService::SendReply<ReplyType>,
base::Unretained(this), std::move(response)));
}
// Template for handling D-Bus methods without a request.
template <typename ReplyType>
using HandlerFunctionEmptyRequest =
void (RmadInterface::*)(base::OnceCallback<void(const ReplyType&)>);
template <typename ReplyType,
DBusService::HandlerFunctionEmptyRequest<ReplyType> func>
void DelegateToInterface(
std::unique_ptr<DBusMethodResponse<ReplyType>> response) {
if (is_rma_required_ && !SetUpInterface()) {
SendErrorSignal(RMAD_ERROR_DAEMON_INITIALIZATION_FAILED);
return;
}
(rmad_interface_->*func)(base::BindOnce(&DBusService::SendReply<ReplyType>,
base::Unretained(this),
std::move(response)));
}
void HandleIsRmaRequiredMethod(
std::unique_ptr<DBusMethodResponse<bool>> response);
// Template for sending out the reply.
template <typename ReplyType>
void SendReply(std::unique_ptr<DBusMethodResponse<ReplyType>> response,
const ReplyType& reply) {
response->Return(reply);
if (!is_rma_required_ || quit_requested_) {
PostQuitTask();
}
}
// Request to quit the daemon. This is used as a callback by state handlers.
void RequestQuit() { quit_requested_ = true; }
// Schedule an asynchronous D-Bus shutdown and exit the daemon.
void PostQuitTask();
std::unique_ptr<brillo::dbus_utils::DBusObject> dbus_object_;
// D-Bus signals.
std::weak_ptr<brillo::dbus_utils::DBusSignal<RmadErrorCode>> error_signal_;
std::weak_ptr<brillo::dbus_utils::DBusSignal<HardwareVerificationResult>>
hardware_verification_signal_;
std::weak_ptr<brillo::dbus_utils::DBusSignal<UpdateRoFirmwareStatus>>
update_ro_firmware_status_signal_;
std::weak_ptr<brillo::dbus_utils::DBusSignal<CalibrationSetupInstruction>>
calibration_setup_signal_;
std::weak_ptr<brillo::dbus_utils::DBusSignal<CalibrationOverallStatus>>
calibration_overall_signal_;
std::weak_ptr<brillo::dbus_utils::DBusSignal<CalibrationComponentStatus>>
calibration_component_signal_;
std::weak_ptr<brillo::dbus_utils::DBusSignal<ProvisionStatus>>
provision_signal_;
std::weak_ptr<brillo::dbus_utils::DBusSignal<FinalizeStatus>>
finalize_signal_;
std::weak_ptr<brillo::dbus_utils::DBusSignal<bool>> hwwp_signal_;
std::weak_ptr<brillo::dbus_utils::DBusSignal<bool>> power_cable_signal_;
// RMA interface for handling most of the D-Bus requests.
RmadInterface* rmad_interface_;
// RMA state file path.
base::FilePath state_file_path_;
// External utils to communicate with tpm_manager.
std::unique_ptr<TpmManagerClient> tpm_manager_client_;
// External utils initialization status.
bool is_external_utils_initialized_;
// RMA interface setup status. Only set up the interface when RMA is required
// to avoid unnecessary code paths.
bool is_interface_set_up_;
// Whether the device should trigger shimless RMA.
bool is_rma_required_;
// Whether we should quit the daemon after handling a method.
bool quit_requested_;
// Test mode daemon.
bool test_mode_;
};
} // namespace rmad
#endif // RMAD_DBUS_SERVICE_H_