Skip to content

Commit

Permalink
[fuchsia] Implement FDR for Fuchsia RebootShlib
Browse files Browse the repository at this point in the history
Change-Id: I18675b81cde2f48feb77c1d37a552fab2c279d32
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3119989
Reviewed-by: Sean Topping <seantopping@chromium.org>
Auto-Submit: William Xiao <wxyz@google.com>
Commit-Queue: William Xiao <wxyz@google.com>
Cr-Commit-Position: refs/heads/main@{#916600}
  • Loading branch information
PaeP3nguin authored and Chromium LUCI CQ committed Aug 30, 2021
1 parent 135ff06 commit de1c110
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 2 deletions.
2 changes: 2 additions & 0 deletions chromecast/system/reboot/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ test("cast_reboot_unittests") {
"//chromecast/public",
"//third_party/fuchsia-sdk/sdk/fidl/fuchsia.feedback",
"//third_party/fuchsia-sdk/sdk/fidl/fuchsia.hardware.power.statecontrol",
"//third_party/fuchsia-sdk/sdk/fidl/fuchsia.recovery",
"//third_party/fuchsia-sdk/sdk/fidl/fuchsia.io",
"//third_party/fuchsia-sdk/sdk/pkg/fidl_cpp",
"//third_party/fuchsia-sdk/sdk/pkg/sys_cpp",
Expand Down Expand Up @@ -80,6 +81,7 @@ if (is_fuchsia) {
"//base",
"//third_party/fuchsia-sdk/sdk/fidl/fuchsia.feedback",
"//third_party/fuchsia-sdk/sdk/fidl/fuchsia.hardware.power.statecontrol",
"//third_party/fuchsia-sdk/sdk/fidl/fuchsia.recovery",
"//third_party/fuchsia-sdk/sdk/pkg/fidl",
"//third_party/fuchsia-sdk/sdk/pkg/fidl_cpp",
"//third_party/fuchsia-sdk/sdk/pkg/sys_cpp",
Expand Down
36 changes: 34 additions & 2 deletions chromecast/system/reboot/reboot_fuchsia.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include <fuchsia/feedback/cpp/fidl.h>
#include <fuchsia/hardware/power/statecontrol/cpp/fidl.h>
#include <fuchsia/recovery/cpp/fidl.h>
#include <lib/sys/cpp/component_context.h>
#include <lib/sys/cpp/service_directory.h>
#include <zircon/status.h>
Expand All @@ -25,13 +26,17 @@ using fuchsia::feedback::LastRebootInfoProviderSyncPtr;
using fuchsia::feedback::RebootReason;
using fuchsia::hardware::power::statecontrol::Admin_Reboot_Result;
using fuchsia::hardware::power::statecontrol::AdminPtr;
using fuchsia::recovery::FactoryResetPtr;
using StateControlRebootReason =
fuchsia::hardware::power::statecontrol::RebootReason;

namespace chromecast {

namespace {
FuchsiaComponentRestartReason state_;

// If true, the next reboot should trigger a factory data reset.
bool fdr_on_reboot_ = false;
}

AdminPtr& GetAdminPtr() {
Expand All @@ -44,13 +49,22 @@ LastRebootInfoProviderSyncPtr& GetLastRebootInfoProviderSyncPtr() {
return *g_last_reboot_info;
}

fuchsia::recovery::FactoryResetPtr& GetFactoryResetPtr() {
static base::NoDestructor<FactoryResetPtr> g_factory_reset;
return *g_factory_reset;
}

void InitializeRebootShlib(const std::vector<std::string>& argv,
sys::ServiceDirectory* incoming_directory) {
incoming_directory->Connect(GetAdminPtr().NewRequest());
incoming_directory->Connect(GetLastRebootInfoProviderSyncPtr().NewRequest());
incoming_directory->Connect(GetFactoryResetPtr().NewRequest());
GetAdminPtr().set_error_handler([](zx_status_t status) {
ZX_LOG(ERROR, status) << "AdminPtr disconnected";
});
GetFactoryResetPtr().set_error_handler([](zx_status_t status) {
ZX_LOG(ERROR, status) << "FactoryResetPtr disconnected";
});
InitializeRestartCheck();
}

Expand Down Expand Up @@ -85,6 +99,22 @@ bool RebootShlib::IsRebootSourceSupported(

// static
bool RebootShlib::RebootNow(RebootSource reboot_source) {
if (fdr_on_reboot_) {
fdr_on_reboot_ = false;

// Intentionally using async Ptr to avoid deadlock
// Otherwise caller is blocked, and if caller needs to be notified
// as well, it will go into a deadlock state.
GetFactoryResetPtr()->Reset([](zx_status_t status) {
if (status != ZX_OK) {
ZX_LOG(ERROR, status) << "Failed to trigger FDR";
}
});

// FDR will perform its own reboot, return immediately.
return true;
}

StateControlRebootReason reason;
switch (reboot_source) {
case RebootSource::API:
Expand Down Expand Up @@ -118,11 +148,13 @@ bool RebootShlib::RebootNow(RebootSource reboot_source) {

// static
bool RebootShlib::IsFdrForNextRebootSupported() {
return false;
return true;
}

// static
void RebootShlib::SetFdrForNextReboot() {}
void RebootShlib::SetFdrForNextReboot() {
fdr_on_reboot_ = true;
}

// static
bool RebootShlib::IsOtaForNextRebootSupported() {
Expand Down
48 changes: 48 additions & 0 deletions chromecast/system/reboot/reboot_fuchsia_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
#include <fuchsia/feedback/cpp/fidl_test_base.h>
#include <fuchsia/hardware/power/statecontrol/cpp/fidl.h>
#include <fuchsia/hardware/power/statecontrol/cpp/fidl_test_base.h>
#include <fuchsia/recovery/cpp/fidl.h>
#include <fuchsia/recovery/cpp/fidl_test_base.h>
#include <fuchsia/io/cpp/fidl.h>
#include <lib/fidl/cpp/interface_request.h>
#include <lib/sys/cpp/outgoing_directory.h>
Expand Down Expand Up @@ -139,6 +141,31 @@ class FakeLastRebootInfoProvider
fuchsia::feedback::LastReboot last_reboot_;
};

class FakeFactoryReset
: public fuchsia::recovery::testing::FactoryReset_TestBase {
public:
explicit FakeFactoryReset(
sys::OutgoingDirectory* outgoing_directory)
: binding_(outgoing_directory, this) {}

void reset_called(bool* reset_called) {
*reset_called = reset_called_;
}

private:
void Reset(ResetCallback callback) final {
reset_called_ = true;
callback(ZX_OK);
}

void NotImplemented_(const std::string& name) final {
ADD_FAILURE() << "NotImplemented_: " << name;
}

base::ScopedServiceBinding<fuchsia::recovery::FactoryReset> binding_;
bool reset_called_ = false;
};

class RebootFuchsiaTest: public ::testing::Test {
public:
RebootFuchsiaTest()
Expand Down Expand Up @@ -169,6 +196,9 @@ class RebootFuchsiaTest: public ::testing::Test {
last_reboot_info_provider_ =
base::SequenceBound<FakeLastRebootInfoProvider>(
thread_.task_runner(), outgoing_directory_.get());
factory_reset_service_ =
base::SequenceBound<FakeFactoryReset>(
thread_.task_runner(), outgoing_directory_.get());

// Ensure that the services above finish publishing themselves.
thread_.FlushForTesting();
Expand All @@ -195,6 +225,14 @@ class RebootFuchsiaTest: public ::testing::Test {
thread_.FlushForTesting();
}

bool FdrTriggered() {
bool reset_called;
factory_reset_service_.AsyncCall(&FakeFactoryReset::reset_called).WithArgs(
&reset_called);
thread_.FlushForTesting();
return reset_called;
}

private:
void ServeOutgoingDirectory(
fidl::InterfaceRequest<fuchsia::io::Directory> channel) {
Expand All @@ -209,6 +247,7 @@ class RebootFuchsiaTest: public ::testing::Test {
std::unique_ptr<sys::ServiceDirectory> incoming_directory_;
base::SequenceBound<FakeAdmin> admin_;
base::SequenceBound<FakeLastRebootInfoProvider> last_reboot_info_provider_;
base::SequenceBound<FakeFactoryReset> factory_reset_service_;
base::ScopedTempDir dir_;
base::FilePath full_path_;

Expand Down Expand Up @@ -259,6 +298,15 @@ TEST_F(RebootFuchsiaTest, RebootReasonZbiSwapTranslatesFromFuchsia) {
Eq(RebootShlib::RebootSource::OTA));
}

TEST_F(RebootFuchsiaTest, RebootNowTriggersFdr) {
EXPECT_TRUE(RebootShlib::IsFdrForNextRebootSupported());

RebootShlib::SetFdrForNextReboot();

EXPECT_TRUE(RebootShlib::RebootNow(RebootShlib::RebootSource::API));
EXPECT_TRUE(FdrTriggered());
}

class RebootFuchsiaParamTest : public RebootFuchsiaTest,
public ::testing::WithParamInterface<RebootReasonParam> {
public:
Expand Down

0 comments on commit de1c110

Please sign in to comment.