chromium/chrome/browser/performance_manager/user_tuning/battery_saver_mode_manager.cc

// 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/public/user_tuning/battery_saver_mode_manager.h"

#include <optional>
#include <utility>

#include "base/check.h"
#include "base/check_deref.h"
#include "base/check_is_test.h"
#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "base/message_loop/message_pump.h"
#include "base/notreached.h"
#include "base/power_monitor/battery_state_sampler.h"
#include "base/power_monitor/power_monitor.h"
#include "base/power_monitor/power_observer.h"
#include "base/run_loop.h"
#include "base/scoped_multi_source_observation.h"
#include "base/values.h"
#include "components/performance_manager/freezing/freezing_policy.h"
#include "components/performance_manager/performance_manager_impl.h"
#include "components/performance_manager/public/features.h"
#include "components/performance_manager/public/user_tuning/prefs.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/browser_child_process_host.h"
#include "content/public/browser/browser_child_process_host_iterator.h"
#include "content/public/browser/browser_child_process_observer.h"
#include "content/public/browser/child_process_data.h"
#include "content/public/browser/frame_rate_throttling.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_process_host_creation_observer.h"
#include "content/public/browser/render_process_host_observer.h"
#include "content/public/common/content_features.h"

#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "ash/constants/ash_features.h"
#include "chromeos/dbus/power/power_manager_client.h"
#endif

namespace performance_manager::user_tuning {
namespace {

BatterySaverModeManager* g_battery_saver_mode_manager =;

constexpr base::TimeDelta kBatteryUsageWriteFrequency =;

BatterySaverModeState;

// On certain platforms (ChromeOS), the battery level displayed to the user is
// artificially lower than the actual battery level. Unfortunately, the battery
// level that Battery Saver Mode looks at is the "actual" level, so users on
// that platform may see Battery Saver Mode trigger at say 17% rather than the
// "advertised" 20%. This parameter allows us to heuristically tweak the
// threshold on those platforms, by being added to the 20% threshold value (so
// setting this parameter to 3 would result in battery saver being activated at
// 23% actual battery level).
#if BUILDFLAG(IS_CHROMEOS_ASH)

// On ChromeOS, the adjustment generally seems to be around 3%, sometimes 2%. We
// choose 3% because it gets us close enough, or overestimates (which is better
// than underestimating in this instance).
constexpr int kBatterySaverModeThresholdAdjustmentForDisplayLevel = 3;
#else
constexpr int kBatterySaverModeThresholdAdjustmentForDisplayLevel =;
#endif  // BUILDFLAG(IS_CHROMEOS_ASH)

class FrameThrottlingDelegateImpl
    : public performance_manager::user_tuning::BatterySaverModeManager::
          FrameThrottlingDelegate {};

class ChildProcessTuningDelegateImpl
    : public BatterySaverModeManager::ChildProcessTuningDelegate,
      public content::RenderProcessHostCreationObserver,
      public content::BrowserChildProcessObserver,
      public content::RenderProcessHostObserver {};

class FreezingDelegateImpl : public BatterySaverModeManager::FreezingDelegate {};

}  // namespace

class DesktopBatterySaverProvider
    : public BatterySaverModeManager::BatterySaverProvider,
      public base::PowerStateObserver,
      public base::BatteryStateSampler::Observer {};

#if BUILDFLAG(IS_CHROMEOS_ASH)
class ChromeOSBatterySaverProvider
    : public BatterySaverModeManager::BatterySaverProvider,
      public chromeos::PowerManagerClient::Observer {
 public:
  explicit ChromeOSBatterySaverProvider(BatterySaverModeManager* manager)
      : manager_(manager) {
    CHECK(manager_);

    chromeos::PowerManagerClient* client = chromeos::PowerManagerClient::Get();
    if (client) {
      power_manager_client_observer_.Observe(client);
      client->GetBatterySaverModeState(base::BindOnce(
          &ChromeOSBatterySaverProvider::OnInitialBatterySaverModeObtained,
          weak_ptr_factory_.GetWeakPtr()));
    } else {
      // We must be in a test that didn't set up PowerManagerClient, so we don't
      // need to listen for updates from it.
      CHECK_IS_TEST();
    }

    base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
    if (command_line->HasSwitch(
            BatterySaverModeManager::kForceDeviceHasBatterySwitch)) {
      force_has_battery_ = true;
      has_battery_ = true;
    }
  }

  ~ChromeOSBatterySaverProvider() override = default;

  void OnInitialBatterySaverModeObtained(
      std::optional<power_manager::BatterySaverModeState> state) {
    if (state) {
      BatterySaverModeStateChanged(*state);
    }
  }

  // chromeos::PowerManagerClient::Observer:
  void BatterySaverModeStateChanged(
      const power_manager::BatterySaverModeState& state) override {
    if (!state.has_enabled() || enabled_ == state.enabled()) {
      return;
    }

    enabled_ = state.enabled();

    manager_->NotifyOnBatterySaverActiveChanged(enabled_);
  }

  void PowerChanged(
      const power_manager::PowerSupplyProperties& proto) override {
    bool device_has_battery =
        proto.battery_state() !=
        power_manager::PowerSupplyProperties_BatteryState_NOT_PRESENT;
    has_battery_ = force_has_battery_ || device_has_battery;
  }

  // BatterySaverProvider:
  bool DeviceHasBattery() const override { return has_battery_; }
  bool IsBatterySaverModeEnabled() override { return false; }
  bool IsBatterySaverModeManaged() override { return false; }
  bool IsBatterySaverActive() const override { return enabled_; }
  bool IsUsingBatteryPower() const override { return false; }
  base::Time GetLastBatteryUsageTimestamp() const override {
    return base::Time();
  }
  int SampledBatteryPercentage() const override { return -1; }
  void SetTemporaryBatterySaverDisabledForSession(bool disabled) override {
    NOTREACHED_IN_MIGRATION();
    // No-op when BSM is controlled by the OS
  }
  bool IsBatterySaverModeDisabledForSession() const override { return false; }

 private:
  bool enabled_ = false;
  bool has_battery_ = false;
  bool force_has_battery_ = false;

  base::ScopedObservation<chromeos::PowerManagerClient,
                          chromeos::PowerManagerClient::Observer>
      power_manager_client_observer_{this};

  raw_ptr<BatterySaverModeManager> manager_;

  base::WeakPtrFactory<ChromeOSBatterySaverProvider> weak_ptr_factory_{this};
};
#endif

const uint64_t BatterySaverModeManager::kLowBatteryThresholdPercent =;

const char BatterySaverModeManager::kForceDeviceHasBatterySwitch[] =;

// static
bool BatterySaverModeManager::HasInstance() {}

// static
BatterySaverModeManager* BatterySaverModeManager::GetInstance() {}

BatterySaverModeManager::~BatterySaverModeManager() {}

void BatterySaverModeManager::AddObserver(Observer* o) {}

void BatterySaverModeManager::RemoveObserver(Observer* o) {}

bool BatterySaverModeManager::DeviceHasBattery() const {}

bool BatterySaverModeManager::IsBatterySaverModeEnabled() {}

bool BatterySaverModeManager::IsBatterySaverModeManaged() const {}

bool BatterySaverModeManager::IsBatterySaverActive() const {}

bool BatterySaverModeManager::IsUsingBatteryPower() const {}

base::Time BatterySaverModeManager::GetLastBatteryUsageTimestamp() const {}

int BatterySaverModeManager::SampledBatteryPercentage() const {}

void BatterySaverModeManager::SetTemporaryBatterySaverDisabledForSession(
    bool disabled) {}

bool BatterySaverModeManager::IsBatterySaverModeDisabledForSession() const {}

BatterySaverModeManager::BatterySaverModeManager(
    PrefService* local_state,
    std::unique_ptr<FrameThrottlingDelegate> frame_throttling_delegate,
    std::unique_ptr<ChildProcessTuningDelegate> child_process_tuning_delegate,
    std::unique_ptr<FreezingDelegate> freezing_delegate)
    :{}

void BatterySaverModeManager::Start() {}

void BatterySaverModeManager::NotifyOnBatterySaverModeChanged(
    bool battery_saver_mode_enabled) {}

void BatterySaverModeManager::NotifyOnBatterySaverActiveChanged(
    bool battery_saver_mode_active) {}

void BatterySaverModeManager::NotifyOnExternalPowerConnectedChanged(
    bool on_battery_power) {}

void BatterySaverModeManager::NotifyOnDeviceHasBatteryChanged(
    bool has_battery) {}
void BatterySaverModeManager::NotifyOnBatteryThresholdReached() {}

}  // namespace performance_manager::user_tuning