| // 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_ |