blob: abbd9bc22a9eebf677c4b6ffc6fee728c3abb895 [file] [log] [blame]
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_PERFORMANCE_MANAGER_PUBLIC_USER_TUNING_USER_PERFORMANCE_TUNING_MANAGER_H_
#define CHROME_BROWSER_PERFORMANCE_MANAGER_PUBLIC_USER_TUNING_USER_PERFORMANCE_TUNING_MANAGER_H_
#include <memory>
#include "base/observer_list.h"
#include "base/observer_list_types.h"
#include "base/scoped_observation.h"
#include "base/time/time.h"
#include "chrome/browser/performance_manager/user_tuning/user_performance_tuning_notifier.h"
#include "chrome/browser/resource_coordinator/lifecycle_unit_state.mojom-shared.h"
#include "components/prefs/pref_change_registrar.h"
#include "content/public/browser/web_contents_user_data.h"
class ChromeBrowserMainExtraPartsPerformanceManager;
class PerformanceManagerMetricsProviderTest;
class PrefService;
namespace performance_manager::user_tuning {
// This singleton is responsible for managing the state of high efficiency mode
// and battery saver mode, as well as the different signals surrounding their
// toggling.
//
// It is created and owned by `ChromeBrowserMainExtraPartsPerformanceManager`
// and initialized in 2 parts:
// - Created in PostCreateThreads (so that UI can start observing it as soon as
// the first views are created) and
// - Starts to manage the modes when Start() is called in PreMainMessageLoopRun.
//
// This object lives on the main thread and should be used from it exclusively.
class UserPerformanceTuningManager {
public:
// The percentage of battery that is considered "low". For instance, this
// would be `20` for 20%.
static const uint64_t kLowBatteryThresholdPercent;
// Command line switch for setting the discard time.
static const char kTimeBeforeDiscardInMinutesSwitch[];
class FrameThrottlingDelegate {
public:
virtual void StartThrottlingAllFrameSinks() = 0;
virtual void StopThrottlingAllFrameSinks() = 0;
virtual ~FrameThrottlingDelegate() = default;
};
class HighEfficiencyModeDelegate {
public:
virtual void ToggleHighEfficiencyMode(bool enabled) = 0;
virtual void SetTimeBeforeDiscard(base::TimeDelta time_before_discard) = 0;
virtual ~HighEfficiencyModeDelegate() = default;
};
class Observer : public base::CheckedObserver {
public:
// Raised when the battery saver mode interventions are activated or
// deactivated
virtual void OnBatterySaverModeChanged(bool is_active) {}
// Raised when the high efficiency mode setting is changed. Get the new
// state using `UserPerformanceTuningManager::IsHighEfficiencyModeActive()`
virtual void OnHighEfficiencyModeChanged() {}
// Raised when the device is plugged in or unplugged
// Can be used by the UI to show a promo if BSM isn't configured to be
// enabled when on battery power.
// If the connection/disconnection from power causes battery saver to be
// enabled/disabled, the state of battery saver will not yet be updated when
// this is invoked. `OnBatterySaverModeChanged` will be invoked after the
// state is updated.
virtual void OnExternalPowerConnectedChanged(bool on_battery_power) {}
// Raised when it becomes known that the device has a battery installed, or
// when a device that previously had a battery is now reported as not having
// one anymore. Overloading this function is particularly useful for code
// that wants to know if the device has a battery during startup, because
// `DeviceHasBattery` can wrongly return `false` for an unbounded period
// of time until the OS provides battery data.
virtual void OnDeviceHasBatteryChanged(bool device_has_battery) {}
// Raised when the battery has reached the 20% threshold
// Can be used by the UI to show a promo if BSM isn't configured to be
// enabled when on battery power under a certain threshold.
virtual void OnBatteryThresholdReached() {}
// Raised when the total memory footprint reaches X%.
// Can be used by the UI to show a promo
virtual void OnMemoryThresholdReached() {}
// Raised when the tab count reaches X.
// Can be used by the UI to show a promo
virtual void OnTabCountThresholdReached() {}
// Raised when the count of janky intervals reaches X.
// Can be used by the UI to show a promo
virtual void OnJankThresholdReached() {}
// Raised when memory metrics for a discarded page becomes available to read
virtual void OnMemoryMetricsRefreshed() {}
};
class PreDiscardResourceUsage
: public content::WebContentsUserData<PreDiscardResourceUsage> {
public:
PreDiscardResourceUsage(content::WebContents* contents,
uint64_t memory_footprint_estimate,
::mojom::LifecycleUnitDiscardReason discard_reason);
~PreDiscardResourceUsage() override;
// Returns the resource usage estimate in kilobytes.
uint64_t memory_footprint_estimate_kb() const {
return memory_footprint_estimate_;
}
::mojom::LifecycleUnitDiscardReason discard_reason() const {
return discard_reason_;
}
base::LiveTicks discard_liveticks() const { return discard_liveticks_; }
private:
friend WebContentsUserData;
WEB_CONTENTS_USER_DATA_KEY_DECL();
uint64_t memory_footprint_estimate_ = 0;
::mojom::LifecycleUnitDiscardReason discard_reason_;
base::LiveTicks discard_liveticks_;
};
// Returns whether a UserPerformanceTuningManager was created and installed.
// Should only return false in unit tests.
static bool HasInstance();
static UserPerformanceTuningManager* GetInstance();
~UserPerformanceTuningManager();
void AddObserver(Observer* o);
void RemoveObserver(Observer* o);
// Returns true if High Efficiency mode is currently enabled.
bool IsHighEfficiencyModeActive();
// Returns true if the prefs underlying High Efficiency Mode are managed by an
// enterprise policy.
bool IsHighEfficiencyModeManaged() const;
// Returns true if the prefs underlying High Efficiency Mode are still in the
// default state.
bool IsHighEfficiencyModeDefault() const;
// Enables high efficiency mode and sets the relevant prefs accordingly.
void SetHighEfficiencyModeEnabled(bool enabled);
// Sets the default value of the discard time pref using the command line
// switch, if the pref is in the default state.
static void SetDefaultTimeBeforeDiscardFromSwitch(PrefService* local_state);
// Discards the given WebContents with the same mechanism as one that is
// discarded through a natural timeout
void DiscardPageForTesting(content::WebContents* web_contents);
// Returns true if the device is a portable device that can run on battery
// power, false otherwise.
// This is determined asynchronously, so it may indicate false for an
// undetermined amount of time at startup, until the battery state is
// sampled for the first time.
bool DeviceHasBattery() const;
// Returns true if Battery Saver Mode interventions are active. If any state
// transitions cause an observer notification, this is guaranteed to reflect
// the *new* value when the observers are notified so the UI layer can make
// decisions based on the most up-to-date state.
bool IsBatterySaverActive() const;
// Returns true if the device is unplugged and using battery power.
bool IsUsingBatteryPower() const;
// Returns the time of the last use of battery for the device.
base::Time GetLastBatteryUsageTimestamp() const;
// Returns the last sampled device battery percentage. A percentage of -1
// indicates that the battery state has not been sampled yet.
int SampledBatteryPercentage() const;
// If called with `disabled = true`, will disable battery saver mode until
// the device is plugged in or the user configures the battery saver mode
// state preference.
void SetTemporaryBatterySaverDisabledForSession(bool disabled);
bool IsBatterySaverModeDisabledForSession() const;
private:
friend class ::ChromeBrowserMainExtraPartsPerformanceManager;
friend class ::PerformanceManagerMetricsProviderTest;
friend class UserPerformanceTuningManagerTest;
friend class TestUserPerformanceTuningManagerEnvironment;
friend class ChromeOSBatterySaverProvider;
friend class DesktopBatterySaverProvider;
// An implementation of UserPerformanceTuningNotifier::Receiver that
// forwards the notifications to the UserPerformanceTuningManager on the Main
// Thread.
class UserPerformanceTuningReceiverImpl
: public UserPerformanceTuningNotifier::Receiver {
public:
~UserPerformanceTuningReceiverImpl() override;
void NotifyTabCountThresholdReached() override;
void NotifyMemoryThresholdReached() override;
void NotifyMemoryMetricsRefreshed() override;
};
explicit UserPerformanceTuningManager(
PrefService* local_state,
std::unique_ptr<UserPerformanceTuningNotifier> notifier = nullptr,
std::unique_ptr<FrameThrottlingDelegate> frame_throttling_delegate =
nullptr,
std::unique_ptr<HighEfficiencyModeDelegate>
high_efficiency_mode_delegate = nullptr);
class BatterySaverProvider {
public:
virtual ~BatterySaverProvider() = default;
virtual bool DeviceHasBattery() const = 0;
virtual bool IsBatterySaverActive() const = 0;
virtual bool IsUsingBatteryPower() const = 0;
virtual base::Time GetLastBatteryUsageTimestamp() const = 0;
virtual int SampledBatteryPercentage() const = 0;
virtual void SetTemporaryBatterySaverDisabledForSession(bool disabled) = 0;
virtual bool IsBatterySaverModeDisabledForSession() const = 0;
};
void Start();
void OnHighEfficiencyModePrefChanged();
void OnHighEfficiencyModeTimeBeforeDiscardChanged();
void NotifyTabCountThresholdReached();
void NotifyMemoryThresholdReached();
void NotifyMemoryMetricsRefreshed();
// Called from the installed BatterySaverProvider to signify a change in
// battery saver mode related state.
void NotifyOnBatterySaverModeChanged(bool battery_saver_mode_enabled);
void NotifyOnExternalPowerConnectedChanged(bool on_battery_power);
void NotifyOnDeviceHasBatteryChanged(bool has_battery);
void NotifyOnBatteryThresholdReached();
std::unique_ptr<FrameThrottlingDelegate> frame_throttling_delegate_;
std::unique_ptr<HighEfficiencyModeDelegate> high_efficiency_mode_delegate_;
std::unique_ptr<BatterySaverProvider> battery_saver_provider_;
PrefChangeRegistrar pref_change_registrar_;
base::ObserverList<Observer> observers_;
// Command line switch for overriding the device has battery flag.
static const char kForceDeviceHasBatterySwitch[];
};
} // namespace performance_manager::user_tuning
#endif // CHROME_BROWSER_PERFORMANCE_MANAGER_PUBLIC_USER_TUNING_USER_PERFORMANCE_TUNING_MANAGER_H_