blob: f0019f4c3c08209af773c39d0db2211c6e5c845f [file] [log] [blame]
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/performance_manager/metrics/metrics_provider_desktop.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "chrome/browser/performance_manager/public/user_tuning/user_performance_tuning_manager.h"
#include "chrome/browser/performance_manager/test_support/fake_frame_throttling_delegate.h"
#include "chrome/browser/performance_manager/test_support/test_user_performance_tuning_manager_environment.h"
#include "components/performance_manager/public/features.h"
#include "components/performance_manager/public/user_tuning/prefs.h"
#include "components/prefs/testing_pref_service.h"
#include "testing/gtest/include/gtest/gtest.h"
class FakeHighEfficiencyModeDelegate
: public performance_manager::user_tuning::UserPerformanceTuningManager::
HighEfficiencyModeDelegate {
public:
void ToggleHighEfficiencyMode(bool enabled) override {}
~FakeHighEfficiencyModeDelegate() override = default;
};
class PerformanceManagerMetricsProviderDesktopTest : public testing::Test {
protected:
PrefService* local_state() { return &local_state_; }
void SetHighEfficiencyEnabled(bool enabled) {
local_state()->SetInteger(
performance_manager::user_tuning::prefs::kHighEfficiencyModeState,
static_cast<int>(enabled ? performance_manager::user_tuning::prefs::
HighEfficiencyModeState::kEnabledOnTimer
: performance_manager::user_tuning::prefs::
HighEfficiencyModeState::kDisabled));
}
void SetBatterySaverEnabled(bool enabled) {
local_state()->SetInteger(
performance_manager::user_tuning::prefs::kBatterySaverModeState,
static_cast<int>(enabled ? performance_manager::user_tuning::prefs::
BatterySaverModeState::kEnabled
: performance_manager::user_tuning::prefs::
BatterySaverModeState::kDisabled));
}
void ExpectSingleUniqueSample(
const base::HistogramTester& tester,
performance_manager::MetricsProviderDesktop::EfficiencyMode sample,
int battery_saver_percent,
int memory_saver_percent) {
tester.ExpectUniqueSample("PerformanceManager.UserTuning.EfficiencyMode",
sample, 1);
tester.ExpectUniqueSample(
"PerformanceManager.UserTuning.BatterySaverModeEnabledPercent",
battery_saver_percent, 1);
tester.ExpectUniqueSample(
"PerformanceManager.UserTuning.MemorySaverModeEnabledPercent",
memory_saver_percent, 1);
}
void InitProvider() { provider_->Initialize(); }
performance_manager::MetricsProviderDesktop* provider() {
return provider_.get();
}
void ShutdownUserPerformanceTuningManager() {
user_performance_tuning_env_->TearDown();
user_performance_tuning_env_.reset();
}
void FastForwardBy(base::TimeDelta delta) {
task_environment_.FastForwardBy(delta);
}
private:
void SetUp() override {
performance_manager::user_tuning::prefs::RegisterLocalStatePrefs(
local_state_.registry());
user_performance_tuning_env_ =
std::make_unique<performance_manager::user_tuning::
TestUserPerformanceTuningManagerEnvironment>();
user_performance_tuning_env_->SetUp(&local_state_);
provider_.reset(
new performance_manager::MetricsProviderDesktop(local_state()));
}
void TearDown() override {
// Tests may teardown the environment before this is called to make some
// assertions.
if (user_performance_tuning_env_) {
user_performance_tuning_env_->TearDown();
}
}
base::test::TaskEnvironment task_environment_{
base::test::TaskEnvironment::TimeSource::MOCK_TIME};
TestingPrefServiceSimple local_state_;
std::unique_ptr<performance_manager::user_tuning::
TestUserPerformanceTuningManagerEnvironment>
user_performance_tuning_env_;
std::unique_ptr<performance_manager::MetricsProviderDesktop> provider_;
};
TEST_F(PerformanceManagerMetricsProviderDesktopTest, TestNormalMode) {
SetHighEfficiencyEnabled(false);
InitProvider();
base::HistogramTester tester;
provider()->ProvideCurrentSessionData(nullptr);
ExpectSingleUniqueSample(
tester,
performance_manager::MetricsProviderDesktop::EfficiencyMode::kNormal,
/*battery_saver_percent=*/0, /*memory_saver_percent=*/0);
}
TEST_F(PerformanceManagerMetricsProviderDesktopTest, TestMixedMode) {
// Start in normal mode
SetHighEfficiencyEnabled(false);
InitProvider();
{
base::HistogramTester tester;
provider()->ProvideCurrentSessionData(nullptr);
ExpectSingleUniqueSample(
tester,
performance_manager::MetricsProviderDesktop::EfficiencyMode::kNormal,
/*battery_saver_percent=*/0, /*memory_saver_percent=*/0);
}
{
base::HistogramTester tester;
// Enable High-Efficiency Mode, the next reported value should be "mixed"
// because we transitioned from normal to High-Efficiency during the
// interval. Simulate 10 minutes elapsing before and after the change, which
// should result in memory saver being reported as enabled for 50% of the
// interval
FastForwardBy(base::Minutes(10));
SetHighEfficiencyEnabled(true);
FastForwardBy(base::Minutes(10));
provider()->ProvideCurrentSessionData(nullptr);
ExpectSingleUniqueSample(
tester,
performance_manager::MetricsProviderDesktop::EfficiencyMode::kMixed,
/*battery_saver_percent=*/0, /*memory_saver_percent=*/50);
}
{
base::HistogramTester tester;
// If another UMA upload happens without mode changes, this one will report
// High-Efficiency Mode. Memory Saver is considered on for 100% of the
// interval.
provider()->ProvideCurrentSessionData(nullptr);
ExpectSingleUniqueSample(tester,
performance_manager::MetricsProviderDesktop::
EfficiencyMode::kHighEfficiency,
/*battery_saver_percent=*/0,
/*memory_saver_percent=*/100);
}
{
base::HistogramTester tester;
// Advance time, change battery saver state, then advance time again. The
// Battery Saver Percent histogram should report the correct percentage.
FastForwardBy(base::Minutes(40));
SetBatterySaverEnabled(true);
FastForwardBy(base::Minutes(10));
provider()->ProvideCurrentSessionData(nullptr);
ExpectSingleUniqueSample(
tester,
performance_manager::MetricsProviderDesktop::EfficiencyMode::kMixed,
/*battery_saver_percent=*/20, /*memory_saver_percent=*/100);
}
}
TEST_F(PerformanceManagerMetricsProviderDesktopTest, TestBothModes) {
SetHighEfficiencyEnabled(true);
SetBatterySaverEnabled(true);
InitProvider();
{
base::HistogramTester tester;
// Start with both modes enabled (such as a Chrome startup after having
// enabled both modes in a previous session).
provider()->ProvideCurrentSessionData(nullptr);
ExpectSingleUniqueSample(
tester,
performance_manager::MetricsProviderDesktop::EfficiencyMode::kBoth,
/*battery_saver_percent=*/100, /*memory_saver_percent=*/100);
}
{
base::HistogramTester tester;
// Disabling High-Efficiency Mode will cause the next report to be "mixed".
// Since the time didn't advance, memory saver was off for the entire
// interval and battery saver was on for it.
SetHighEfficiencyEnabled(false);
provider()->ProvideCurrentSessionData(nullptr);
ExpectSingleUniqueSample(
tester,
performance_manager::MetricsProviderDesktop::EfficiencyMode::kMixed,
/*battery_saver_percent=*/100, /*memory_saver_percent=*/0);
}
{
base::HistogramTester tester;
// No changes until the following report, "Battery saver" is reported
provider()->ProvideCurrentSessionData(nullptr);
ExpectSingleUniqueSample(tester,
performance_manager::MetricsProviderDesktop::
EfficiencyMode::kBatterySaver,
/*battery_saver_percent=*/100,
/*memory_saver_percent=*/0);
}
{
base::HistogramTester tester;
// Re-enabling High-Efficiency Mode will cause the next report to indicate
// "mixed".
FastForwardBy(base::Minutes(10));
SetHighEfficiencyEnabled(true);
FastForwardBy(base::Minutes(30));
provider()->ProvideCurrentSessionData(nullptr);
ExpectSingleUniqueSample(
tester,
performance_manager::MetricsProviderDesktop::EfficiencyMode::kMixed,
/*battery_saver_percent=*/100, /*memory_saver_percent=*/75);
}
{
base::HistogramTester tester;
// One more report with no changes, this one reports "both" again.
provider()->ProvideCurrentSessionData(nullptr);
ExpectSingleUniqueSample(
tester,
performance_manager::MetricsProviderDesktop::EfficiencyMode::kBoth,
/*battery_saver_percent=*/100, /*memory_saver_percent=*/100);
}
}
TEST_F(PerformanceManagerMetricsProviderDesktopTest,
TestCorrectlyLoggedDuringShutdown) {
SetHighEfficiencyEnabled(false);
SetBatterySaverEnabled(true);
InitProvider();
{
base::HistogramTester tester;
// No changes until the following report, "Battery saver" is reported
provider()->ProvideCurrentSessionData(nullptr);
ExpectSingleUniqueSample(tester,
performance_manager::MetricsProviderDesktop::
EfficiencyMode::kBatterySaver,
/*battery_saver_percent=*/100,
/*memory_saver_percent=*/0);
}
ShutdownUserPerformanceTuningManager();
// During shutdown, the MetricsProviderDesktop will attempt to record session
// data one last time. This happens after the UserPerformanceTuningManager is
// destroyed, which can cause a crash if the manager is accessed to compute
// the current mode.
{
base::HistogramTester tester;
// No changes until the following report, "Battery saver" is reported
provider()->ProvideCurrentSessionData(nullptr);
ExpectSingleUniqueSample(tester,
performance_manager::MetricsProviderDesktop::
EfficiencyMode::kBatterySaver,
/*battery_saver_percent=*/100,
/*memory_saver_percent=*/0);
}
}