Skip to content

Commit

Permalink
[fuchsia] Provide FIDL reboot reason in RebootNow
Browse files Browse the repository at this point in the history
Updates the RebootNow implementation on Fuchsia to use the Reboot FIDL
interface instead of Suspend in order to provide granular reboot reasons.

Bug: 158707064
Test: cast_reboot_unittests (with target_os="fuchsia")
Change-Id: Ie13d2082937b191bcc118a6caf37518d94a8a30a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2250079
Commit-Queue: Akira Baruah <akirabaruah@google.com>
Reviewed-by: Michael Spang <spang@chromium.org>
Cr-Commit-Position: refs/heads/master@{#779927}
  • Loading branch information
akirabaruah authored and Commit Bot committed Jun 18, 2020
1 parent fc336fc commit 777d63c
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 24 deletions.
1 change: 1 addition & 0 deletions chromecast/system/reboot/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ test("cast_reboot_unittests") {
":fuchsia",
"//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.io",
"//third_party/fuchsia-sdk/sdk/pkg/fidl_cpp",
"//third_party/fuchsia-sdk/sdk/pkg/sys_cpp",
Expand Down
25 changes: 20 additions & 5 deletions chromecast/system/reboot/reboot_fuchsia.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@
using fuchsia::feedback::LastReboot;
using fuchsia::feedback::LastRebootInfoProviderSyncPtr;
using fuchsia::feedback::RebootReason;
using fuchsia::hardware::power::statecontrol::Admin_Suspend_Result;
using fuchsia::hardware::power::statecontrol::Admin_Reboot_Result;
using fuchsia::hardware::power::statecontrol::AdminSyncPtr;
using fuchsia::hardware::power::statecontrol::SystemPowerState;
using StateControlRebootReason =
fuchsia::hardware::power::statecontrol::RebootReason;

namespace chromecast {

Expand Down Expand Up @@ -63,9 +64,23 @@ bool RebootShlib::IsRebootSourceSupported(

// static
bool RebootShlib::RebootNow(RebootSource reboot_source) {
Admin_Suspend_Result out_result;
zx_status_t status =
GetAdminSyncPtr()->Suspend(SystemPowerState::REBOOT, &out_result);
StateControlRebootReason reason;
switch (reboot_source) {
case RebootSource::API:
reason = StateControlRebootReason::USER_REQUEST;
break;
case RebootSource::OTA:
reason = StateControlRebootReason::SYSTEM_UPDATE;
break;
case RebootSource::OVERHEAT:
reason = StateControlRebootReason::HIGH_TEMPERATURE;
break;
default:
reason = StateControlRebootReason::USER_REQUEST;
break;
}
Admin_Reboot_Result out_result;
zx_status_t status = GetAdminSyncPtr()->Reboot(reason, &out_result);
ZX_CHECK(status == ZX_OK, status) << "Failed to suspend device";
return !out_result.is_err();
}
Expand Down
116 changes: 97 additions & 19 deletions chromecast/system/reboot/reboot_fuchsia_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@

#include <fuchsia/feedback/cpp/fidl.h>
#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/io/cpp/fidl.h>
#include <lib/fidl/cpp/interface_request.h>
#include <lib/sys/cpp/outgoing_directory.h>
#include <lib/sys/cpp/service_directory.h>
#include <memory>
#include <tuple>

#include "base/bind.h"
#include "base/fuchsia/scoped_service_binding.h"
#include "base/location.h"
#include "base/message_loop/message_pump_type.h"
Expand All @@ -30,11 +33,15 @@ namespace {
using ::testing::Eq;

using fuchsia::feedback::RebootReason;
using StateControlRebootReason =
fuchsia::hardware::power::statecontrol::RebootReason;

struct RebootReasonParam {
RebootReason reason;
RebootShlib::RebootSource source;
bool graceful;
StateControlRebootReason state_control_reason =
StateControlRebootReason::USER_REQUEST;
};

const RebootReasonParam kRebootReasonParams[] = {
Expand All @@ -52,38 +59,63 @@ const RebootReasonParam kRebootReasonParams[] = {
RebootShlib::RebootSource::WATCHDOG, false},

// Graceful reboot reasons.
{RebootReason::USER_REQUEST, RebootShlib::RebootSource::API, true},
{RebootReason::SYSTEM_UPDATE, RebootShlib::RebootSource::OTA, true},
{RebootReason::HIGH_TEMPERATURE, RebootShlib::RebootSource::OVERHEAT, true},
{RebootReason::USER_REQUEST, RebootShlib::RebootSource::API, true,
StateControlRebootReason::USER_REQUEST},
{RebootReason::SYSTEM_UPDATE, RebootShlib::RebootSource::OTA, true,
StateControlRebootReason::SYSTEM_UPDATE},
{RebootReason::HIGH_TEMPERATURE, RebootShlib::RebootSource::OVERHEAT, true,
StateControlRebootReason::HIGH_TEMPERATURE},
{RebootReason::SESSION_FAILURE, RebootShlib::RebootSource::SW_OTHER, true},
};

class FakeAdmin
: public fuchsia::hardware::power::statecontrol::testing::Admin_TestBase {
public:
explicit FakeAdmin(sys::OutgoingDirectory* outgoing_directory)
: binding_(outgoing_directory, this) {}

void GetLastRebootReason(StateControlRebootReason* reason) {
*reason = last_reboot_reason_;
}

private:
void Reboot(StateControlRebootReason reason, RebootCallback callback) final {
last_reboot_reason_ = reason;
fuchsia::hardware::power::statecontrol::Admin_Reboot_Response response;
fuchsia::hardware::power::statecontrol::Admin_Reboot_Result result;
result.set_response(response);
callback(std::move(result));
}

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

base::fuchsia::ScopedServiceBinding<
fuchsia::hardware::power::statecontrol::Admin>
binding_;
StateControlRebootReason last_reboot_reason_;
};

class FakeLastRebootInfoProvider
: public fuchsia::feedback::testing::LastRebootInfoProvider_TestBase {
public:
explicit FakeLastRebootInfoProvider(
fidl::InterfaceRequest<fuchsia::io::Directory> channel) {
outgoing_directory_.GetOrCreateDirectory("svc")->Serve(
fuchsia::io::OPEN_RIGHT_READABLE | fuchsia::io::OPEN_RIGHT_WRITABLE,
channel.TakeChannel());
binding_ = std::make_unique<base::fuchsia::ScopedServiceBinding<
fuchsia::feedback::LastRebootInfoProvider>>(&outgoing_directory_, this);
}
sys::OutgoingDirectory* outgoing_directory)
: binding_(outgoing_directory, this) {}

void SetLastReboot(fuchsia::feedback::LastReboot last_reboot) {
last_reboot_ = std::move(last_reboot);
}

void Get(GetCallback callback) override { callback(std::move(last_reboot_)); }
private:
void Get(GetCallback callback) final { callback(std::move(last_reboot_)); }

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

private:
sys::OutgoingDirectory outgoing_directory_;
std::unique_ptr<base::fuchsia::ScopedServiceBinding<
fuchsia::feedback::LastRebootInfoProvider>>
base::fuchsia::ScopedServiceBinding<fuchsia::feedback::LastRebootInfoProvider>
binding_;
fuchsia::feedback::LastReboot last_reboot_;
};
Expand All @@ -100,29 +132,75 @@ class RebootFuchsiaTest : public ::testing::TestWithParam<RebootReasonParam> {
void SetUp() override {
// Create incoming (service) and outgoing directories that are connected.
fidl::InterfaceHandle<::fuchsia::io::Directory> directory;

// The thread handling fidl calls to the fake service must also be the
// thread that we start the serve operation on. Since all fakes require the
// same output directory handle, we post a task here to begin the serve
// operation, then flush the task runner queue to ensure that output
// directory is safe to pass to the fakes.
thread_.task_runner()->PostTask(
FROM_HERE,
base::BindOnce(&RebootFuchsiaTest::ServeOutgoingDirectory,
base::Unretained(this), directory.NewRequest()));
thread_.FlushForTesting();

// Initialize and publish fake fidl services.
admin_ = base::SequenceBound<FakeAdmin>(thread_.task_runner(),
outgoing_directory_.get());
last_reboot_info_provider_ =
base::SequenceBound<FakeLastRebootInfoProvider>(thread_.task_runner(),
directory.NewRequest());
base::SequenceBound<FakeLastRebootInfoProvider>(
thread_.task_runner(), outgoing_directory_.get());

// Ensure that the services above finish publishing themselves.
thread_.FlushForTesting();

// Use a service directory backed by the fakes above for tests.
incoming_directory_ =
std::make_unique<sys::ServiceDirectory>(std::move(directory));
InitializeRebootShlib({}, incoming_directory_.get());
}

void TearDown() override { RebootUtil::Finalize(); }
void TearDown() override {
RebootUtil::Finalize();
thread_.FlushForTesting();
}

StateControlRebootReason GetLastRebootReason() {
StateControlRebootReason reason;
admin_.Post(FROM_HERE, &FakeAdmin::GetLastRebootReason, &reason);
thread_.FlushForTesting();
return reason;
}

void SetLastReboot(fuchsia::feedback::LastReboot last_reboot) {
last_reboot_info_provider_.Post(FROM_HERE,
&FakeLastRebootInfoProvider::SetLastReboot,
std::move(last_reboot));
thread_.FlushForTesting();
}

private:
void ServeOutgoingDirectory(
fidl::InterfaceRequest<fuchsia::io::Directory> channel) {
outgoing_directory_ = std::make_unique<sys::OutgoingDirectory>();
outgoing_directory_->GetOrCreateDirectory("svc")->Serve(
fuchsia::io::OPEN_RIGHT_READABLE | fuchsia::io::OPEN_RIGHT_WRITABLE,
channel.TakeChannel());
}

const base::test::SingleThreadTaskEnvironment task_environment_;
std::unique_ptr<sys::OutgoingDirectory> outgoing_directory_;
std::unique_ptr<sys::ServiceDirectory> incoming_directory_;
base::Thread thread_;
base::SequenceBound<FakeAdmin> admin_;
base::SequenceBound<FakeLastRebootInfoProvider> last_reboot_info_provider_;
};

TEST_P(RebootFuchsiaTest, RebootNowSendsFidlRebootReason) {
EXPECT_TRUE(RebootShlib::RebootNow(GetParam().source));
EXPECT_THAT(GetLastRebootReason(), Eq(GetParam().state_control_reason));
}

TEST_F(RebootFuchsiaTest, GetLastRebootSourceDefaultsToUnknown) {
EXPECT_THAT(RebootUtil::GetLastRebootSource(),
Eq(RebootShlib::RebootSource::UNKNOWN));
Expand Down

0 comments on commit 777d63c

Please sign in to comment.