blob: 946627ec617b05e4dea89efcb233dc06be40c3dd [file] [log] [blame] [edit]
// Copyright 2021 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef RMAD_INTERFACE_RMAD_INTERFACE_IMPL_H_
#define RMAD_INTERFACE_RMAD_INTERFACE_IMPL_H_
#include "rmad/interface/rmad_interface.h"
#include <algorithm>
#include <list>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include <base/functional/callback.h>
#include <base/memory/scoped_refptr.h>
#include <base/timer/timer.h>
#include "rmad/constants.h"
#include "rmad/daemon/daemon_callback.h"
#include "rmad/metrics/metrics_utils.h"
#include "rmad/state_handler/state_handler_manager.h"
#include "rmad/system/power_manager_client.h"
#include "rmad/system/runtime_probe_client.h"
#include "rmad/system/shill_client.h"
#include "rmad/system/tpm_manager_client.h"
#include "rmad/udev/udev_utils.h"
#include "rmad/utils/cmd_utils.h"
#include "rmad/utils/json_store.h"
namespace rmad {
class RmadInterfaceImpl final : public RmadInterface {
public:
static constexpr base::TimeDelta kTestModeMonitorInterval = base::Seconds(2);
RmadInterfaceImpl();
// Used to inject mocked |json_store_|, |state_handler_manager_|,
// |runtime_probe_client_|, |shill_client_|, |tpm_manager_client_|,
// |power_manager_client_|, |udev_utils_|, |cmd_utils_| and
// |metrics_utils_|.
explicit RmadInterfaceImpl(
scoped_refptr<JsonStore> json_store,
const base::FilePath& working_dir_path,
const base::FilePath& unencrypted_rma_dir_path,
std::unique_ptr<StateHandlerManager> state_handler_manager,
std::unique_ptr<RuntimeProbeClient> runtime_probe_client,
std::unique_ptr<ShillClient> shill_client,
std::unique_ptr<TpmManagerClient> tpm_manager_client,
std::unique_ptr<PowerManagerClient> power_manager_client,
std::unique_ptr<UdevUtils> udev_utils,
std::unique_ptr<CmdUtils> cmd_utils_,
std::unique_ptr<MetricsUtils> metrics_utils);
RmadInterfaceImpl(const RmadInterfaceImpl&) = delete;
RmadInterfaceImpl& operator=(const RmadInterfaceImpl&) = delete;
~RmadInterfaceImpl() override = default;
bool SetUp(scoped_refptr<DaemonCallback> daemon_callback) override;
RmadState::StateCase GetCurrentStateCase() override {
return current_state_case_;
}
bool CanAbort() const override { return can_abort_; }
void TryTransitionNextStateFromCurrentState() override;
void GetCurrentState(GetStateCallback callback) override;
void TransitionNextState(const TransitionNextStateRequest& request,
GetStateCallback callback) override;
void TransitionPreviousState(GetStateCallback callback) override;
void AbortRma(AbortRmaCallback callback) override;
void GetLog(GetLogCallback callback) override;
void SaveLog(const std::string& diagnostics_log,
SaveLogCallback callback) override;
void RecordBrowserActionMetric(
const RecordBrowserActionMetricRequest& browser_action,
RecordBrowserActionMetricCallback callback) override;
void ExtractExternalDiagnosticsApp(
const ExtractExternalDiagnosticsAppCallback callback) override;
void InstallExtractedDiagnosticsApp(
const InstallExtractedDiagnosticsAppCallback callback) override;
void GetInstalledDiagnosticsApp(
const GetInstalledDiagnosticsAppCallback callback) override;
private:
void InitializeExternalUtils(scoped_refptr<DaemonCallback> daemon_callback);
bool WaitForServices();
bool StartFromInitialState();
std::string GetSystemLog() const;
bool GetLogString(std::string* log_string) const;
std::list<uint8_t> GetUniqueRemovableBlockDeviceIds() const;
// Wrapper to trigger D-Bus callbacks.
template <typename ReplyProtobufType>
using ReplyCallbackType =
base::OnceCallback<void(const ReplyProtobufType&, bool)>;
template <typename ReplyProtobufType>
void ReplyCallback(ReplyCallbackType<ReplyProtobufType> callback,
const ReplyProtobufType& reply) {
// Quit the daemon if we are no longer in RMA.
bool quit_daemon = false;
if (reply.error() == RMAD_ERROR_RMA_NOT_REQUIRED) {
quit_daemon = true;
}
std::move(callback).Run(reply, quit_daemon);
}
template <typename... RpcOutputTypes>
using RpcCallbackType = base::OnceCallback<void(RpcOutputTypes...)>;
// Helper functions for GetLog.
void SaveLogRpc(
const std::string& text_log,
const std::string& json_log,
const std::string& system_log,
const std::string& diagnostics_log,
uint8_t device_id,
RpcCallbackType<const std::optional<std::string>&> rpc_callback);
void SaveLogSuccessHandler(ReplyCallbackType<SaveLogReply> callback,
const std::optional<std::string>& file_name);
void SaveLogFailHandler(ReplyCallbackType<SaveLogReply> callback);
// Helper functions for ExtractExternalDiagnosticsApp.
void ExtractExternalDiagnosticsAppRpc(
uint8_t device_id,
RpcCallbackType<const std::optional<DiagnosticsAppInfo>&> rpc_callback);
void SetDiagnosticsAppNameHandler(
ReplyCallbackType<ExtractExternalDiagnosticsAppReply> callback,
const std::optional<DiagnosticsAppInfo>& info);
void SetDiagnosticsAppNotFoundHandler(
ReplyCallbackType<ExtractExternalDiagnosticsAppReply> callback);
// Helper functions for running RPCs over a list.
template <typename ReplyProtobufType, typename... RpcReplyTypes>
void RunRpcWithRemovableBlockDevices(
ReplyCallbackType<ReplyProtobufType> callback,
base::RepeatingCallback<void(uint8_t, RpcCallbackType<RpcReplyTypes...>)>
rpc,
base::RepeatingCallback<bool(RpcReplyTypes...)> rpc_output_checker,
base::OnceCallback<void(ReplyCallbackType<ReplyProtobufType>,
RpcReplyTypes...)> success_callback,
base::OnceCallback<void(ReplyCallbackType<ReplyProtobufType>)>
fail_callback);
// Get and initialize the state handler for |state case|, and store it to
// |state_handler|. If there's no state handler for |state_case|, or the
// initialization fails, return an error, and |state_handler| is unchanged.
RmadErrorCode GetInitializedStateHandler(
RmadState::StateCase state_case,
scoped_refptr<BaseStateHandler>* state_handler) const;
GetStateReply GetCurrentStateInternal();
GetStateReply TransitionNextStateInternal(
const TransitionNextStateRequest& request, bool try_at_boot);
GetStateReply TransitionPreviousStateInternal();
// Store the state history to |json_store_|.
bool StoreStateHistory();
// Check if it's allowed to go back to the previous state.
bool CanGoBack() const;
// External utilities.
scoped_refptr<JsonStore> json_store_;
base::FilePath working_dir_path_;
base::FilePath unencrypted_rma_dir_path_;
std::unique_ptr<StateHandlerManager> state_handler_manager_;
std::unique_ptr<RuntimeProbeClient> runtime_probe_client_;
std::unique_ptr<ShillClient> shill_client_;
std::unique_ptr<TpmManagerClient> tpm_manager_client_;
std::unique_ptr<PowerManagerClient> power_manager_client_;
std::unique_ptr<UdevUtils> udev_utils_;
std::unique_ptr<CmdUtils> cmd_utils_;
std::unique_ptr<MetricsUtils> metrics_utils_;
// External Callbacks.
scoped_refptr<DaemonCallback> daemon_callback_;
// Internal states.
bool external_utils_initialized_;
RmadState::StateCase current_state_case_;
std::vector<RmadState::StateCase> state_history_;
bool can_abort_;
};
} // namespace rmad
#endif // RMAD_INTERFACE_RMAD_INTERFACE_IMPL_H_