blob: d6cea18224e51776effd44fb57d034de93a7c1e4 [file] [log] [blame]
// Copyright 2025 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <fidl/fuchsia.diagnostics/cpp/fidl.h>
#include <fidl/test.sagcontrol/cpp/fidl.h>
#include <fidl/test.sagcontrol/cpp/natural_ostream.h>
#include <lib/component/incoming/cpp/protocol.h>
#include <lib/diagnostics/reader/cpp/archive_reader.h>
#include <lib/fdio/directory.h>
#include <gtest/gtest.h>
#include "src/power/testing/system-integration/util/test_util.h"
class PowerSystemIntegration : public system_integration_utils::TestLoopBase, public testing::Test {
public:
void SetUp() override {
Initialize();
fence_ = PrepareDriver("mmc-ffe07000", "fuchsia-boot:///aml-sdmmc#meta/aml-sdmmc.cm",
/*expect_new_koid=*/true);
// Helps logs settle a bit, not necessary.
RunLoopWithTimeout(zx::msec(500));
}
void TearDown() override {
fence_.reset();
// Helps ensure driver framework state has had a chance to reset.
RunLoopWithTimeout(zx::sec(1));
}
private:
// Hold on to fence for the test duration.
zx::eventpair fence_;
};
TEST_F(PowerSystemIntegration, StorageSuspendResumeTest) {
// To enable changing SAG's power levels, first trigger the "boot complete" logic. This is done by
// setting both exec state level and app activity level to active.
test_sagcontrol::SystemActivityGovernorState state = GetBootCompleteState();
ASSERT_EQ(ChangeSagState(state), ZX_OK);
ASSERT_TRUE(SetBootComplete());
// There are two archive accessors. One is the test one that is hermetic to the test realm.
// This is where the broker/SAG specific entries can be found.
//
// The other is the real one for the system. This is where the driver entries can be found.
auto test_archives_result = component::Connect<fuchsia_diagnostics::ArchiveAccessor>();
ASSERT_EQ(ZX_OK, test_archives_result.status_value());
diagnostics::reader::ArchiveReader test_reader(dispatcher(), {},
std::move(test_archives_result.value()));
auto real_archives_result = component::Connect<fuchsia_diagnostics::ArchiveAccessor>(
"/svc/fuchsia.diagnostics.RealArchiveAccessor");
ASSERT_EQ(ZX_OK, real_archives_result.status_value());
diagnostics::reader::ArchiveReader real_reader(dispatcher(), {},
std::move(real_archives_result.value()));
const std::string sag_moniker = "system-activity-governor/system-activity-governor";
const std::vector<std::string> sag_exec_state_level = {"root", "power_elements",
"execution_state", "power_level"};
const std::string pb_moniker = "power-broker";
const auto aml_sdmmc_element_id =
GetPowerElementId(test_reader, pb_moniker, "aml-sdmmc-hardware");
ASSERT_TRUE(aml_sdmmc_element_id.is_ok());
const std::vector<std::string> aml_sdmmc_required_level = {
"root", "broker",
"topology", "fuchsia.inspect.Graph",
"topology", aml_sdmmc_element_id.value(),
"meta", "required_level"};
const std::vector<std::string> aml_sdmmc_current_level = {
"root", "broker",
"topology", "fuchsia.inspect.Graph",
"topology", aml_sdmmc_element_id.value(),
"meta", "current_level"};
const auto core_sdmmc_element_id = GetPowerElementId(test_reader, pb_moniker, "sdmmc-hardware");
ASSERT_TRUE(core_sdmmc_element_id.is_ok());
const std::vector<std::string> core_sdmmc_required_level = {
"root", "broker",
"topology", "fuchsia.inspect.Graph",
"topology", core_sdmmc_element_id.value(),
"meta", "required_level"};
const std::vector<std::string> core_sdmmc_current_level = {
"root", "broker",
"topology", "fuchsia.inspect.Graph",
"topology", core_sdmmc_element_id.value(),
"meta", "current_level"};
// Driver monikers are unstable, so wildcard the moniker and use a tree name
const std::string aml_sdmmc_inspect_tree_name = "aml-sd-emmc";
const std::string aml_sdmmc_moniker = "bootstrap/*-drivers*mmc-ffe07000*";
// TODO(b/344044167): Fix inspect node names in aml-sdmmc driver.
const std::vector<std::string> aml_sdmmc_suspended = {"root", "aml-sdmmc-port-mmc@ffe07000",
"power_suspended"};
// Driver monikers are unstable, so wildcard the moniker and use a tree name
const std::string core_sdmmc_moniker = "bootstrap/*-drivers*mmc-ffe07000*";
const std::string sdmmc_root_device_inspect_tree_name = "sdmmc";
const std::vector<std::string> core_sdmmc_suspended = {"root", "sdmmc_core", "power_suspended"};
// Verify boot complete state using inspect data:
// - SAG: exec state level active
// - Power Broker: aml-sdmmc's power element on.
// - aml-sdmmc, core sdmmc: not suspended
MatchInspectData(test_reader, sag_moniker, std::nullopt, sag_exec_state_level,
uint64_t{2}); // kActive
MatchInspectData(test_reader, pb_moniker, std::nullopt, aml_sdmmc_required_level,
uint64_t{1}); // On
MatchInspectData(test_reader, pb_moniker, std::nullopt, aml_sdmmc_current_level,
uint64_t{1}); // On
MatchInspectData(test_reader, pb_moniker, std::nullopt, core_sdmmc_required_level,
uint64_t{1}); // On
MatchInspectData(test_reader, pb_moniker, std::nullopt, core_sdmmc_current_level,
uint64_t{1}); // On
MatchInspectData(real_reader, aml_sdmmc_moniker, aml_sdmmc_inspect_tree_name, aml_sdmmc_suspended,
false);
MatchInspectData(real_reader, core_sdmmc_moniker, sdmmc_root_device_inspect_tree_name,
core_sdmmc_suspended, false);
// Emulate system suspend.
state.execution_state_level(fuchsia_power_system::ExecutionStateLevel::kInactive);
state.application_activity_level(fuchsia_power_system::ApplicationActivityLevel::kInactive);
ASSERT_EQ(ChangeSagState(state), ZX_OK);
ASSERT_EQ(AwaitSystemSuspend(), ZX_OK);
// Verify suspend state using inspect data:
// - SAG: exec state level inactive
// - Power Broker: aml-sdmmc's power element off.
// - aml-sdmmc, core sdmmc: suspended
MatchInspectData(test_reader, sag_moniker, std::nullopt, sag_exec_state_level,
uint64_t{0}); // kInactive
MatchInspectData(test_reader, pb_moniker, std::nullopt, aml_sdmmc_required_level,
uint64_t{0}); // Off
MatchInspectData(test_reader, pb_moniker, std::nullopt, aml_sdmmc_current_level,
uint64_t{0}); // Off
MatchInspectData(test_reader, pb_moniker, std::nullopt, core_sdmmc_required_level,
uint64_t{0}); // Off
MatchInspectData(test_reader, pb_moniker, std::nullopt, core_sdmmc_current_level,
uint64_t{0}); // Off
MatchInspectData(real_reader, aml_sdmmc_moniker, aml_sdmmc_inspect_tree_name, aml_sdmmc_suspended,
true);
MatchInspectData(real_reader, core_sdmmc_moniker, sdmmc_root_device_inspect_tree_name,
core_sdmmc_suspended, true);
// Emulate system resume.
ASSERT_EQ(StartSystemResume(), ZX_OK);
state.execution_state_level(fuchsia_power_system::ExecutionStateLevel::kActive);
state.application_activity_level(fuchsia_power_system::ApplicationActivityLevel::kActive);
ASSERT_EQ(ChangeSagState(state), ZX_OK);
// Verify resume state using inspect data:
// - SAG: exec state level active
// - Power Broker: aml-sdmmc's power element on.
// - aml-sdmmc, core sdmmc: not suspended
MatchInspectData(test_reader, sag_moniker, std::nullopt, sag_exec_state_level,
uint64_t{2}); // kActive
MatchInspectData(test_reader, pb_moniker, std::nullopt, aml_sdmmc_required_level,
uint64_t{1}); // On
MatchInspectData(test_reader, pb_moniker, std::nullopt, aml_sdmmc_current_level,
uint64_t{1}); // On
MatchInspectData(test_reader, pb_moniker, std::nullopt, core_sdmmc_required_level,
uint64_t{1}); // On
MatchInspectData(test_reader, pb_moniker, std::nullopt, core_sdmmc_current_level,
uint64_t{1}); // On
MatchInspectData(real_reader, aml_sdmmc_moniker, aml_sdmmc_inspect_tree_name, aml_sdmmc_suspended,
false);
MatchInspectData(real_reader, core_sdmmc_moniker, sdmmc_root_device_inspect_tree_name,
core_sdmmc_suspended, false);
}