blob: f6e09f97d4ba9c3ca9923e66e3db9b5ce4c3abc2 [file] [log] [blame]
// Copyright 2021 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_POWER_SCHEDULER_POWER_MODE_ARBITER_H_
#define COMPONENTS_POWER_SCHEDULER_POWER_MODE_ARBITER_H_
#include <map>
#include <memory>
#include "base/component_export.h"
#include "base/gtest_prod_util.h"
#include "base/memory/scoped_refptr.h"
#include "base/observer_list_threadsafe.h"
#include "base/synchronization/lock.h"
#include "base/task/task_runner.h"
#include "base/thread_annotations.h"
#include "base/time/time.h"
#include "base/trace_event/trace_log.h"
#include "components/power_scheduler/power_mode.h"
#include "components/power_scheduler/power_mode_voter.h"
#include "components/power_scheduler/traced_power_mode.h"
namespace power_scheduler {
// Decides the active PowerMode for a process. To do this, it collects votes
// from various instrumentation points in Chromium.
//
// Each instrumentation point can instantiate a PowerModeVoter and submit votes:
// auto voter = PowerModeArbiter::GetInstance()->NewVoter("MyVoter");
// voter->VoteFor(PowerMode::kCharging);
//
// The active PowerMode is decided via a prioritization mechanism, see
// ComputeActiveModeLocked().
class COMPONENT_EXPORT(POWER_SCHEDULER) PowerModeArbiter
: public base::trace_event::TraceLog::EnabledStateObserver,
public base::trace_event::TraceLog::IncrementalStateObserver,
public PowerModeVoter::Delegate {
public:
class COMPONENT_EXPORT(POWER_SCHEDULER) Observer {
public:
virtual ~Observer();
virtual void OnPowerModeChanged(PowerMode old_mode, PowerMode new_mode) = 0;
};
// Limits the frequency at which we can run the UpdatePendingResets() task.
// All pending resets are aligned to this time resolution. Public for testing.
static constexpr base::TimeDelta kResetVoteTimeResolution =
base::Milliseconds(100);
static PowerModeArbiter* GetInstance();
// Public for testing.
PowerModeArbiter();
~PowerModeArbiter() override;
PowerModeArbiter(const PowerModeArbiter&) = delete;
PowerModeArbiter& operator=(const PowerModeArbiter&) = delete;
// Instantiates a new Voter for an instrumentation site. |name| must be a
// static string and is used for tracing instrumentation.
std::unique_ptr<PowerModeVoter> NewVoter(const char* name);
// Adds/removes an observer that is notified for every change of the
// process-wide mode. The observer is notified on the task sequence it
// registered on.
void AddObserver(Observer*);
void RemoveObserver(Observer*);
// Should be called by the embedder during process startup, once the thread
// pool is available.
void OnThreadPoolAvailable();
// Enables or disables the kCharging PowerMode. Defaults to enabled, i.e.
// kCharging will preempt all other PowerModes while the device is on a
// charger.
void SetChargingModeEnabled(bool enabled);
// Provide a custom task runner for unit tests. Replaces a call to
// OnThreadPoolAvailable().
void SetTaskRunnerForTesting(scoped_refptr<base::SequencedTaskRunner>);
PowerMode GetActiveModeForTesting();
// TODO(eseckler): Replace this with SetChargingModeEnabled() in tests.
void SetOnBatteryPowerForTesting(bool on_battery_power);
private:
FRIEND_TEST_ALL_PREFIXES(PowerModeArbiterTest, ObserverEnablesResetTasks);
class ChargingPowerModeVoter;
// PowerModeVoter::Delegate implementation:
void OnVoterDestroyed(PowerModeVoter*) override;
void SetVote(PowerModeVoter*, PowerMode) override;
void ResetVoteAfterTimeout(PowerModeVoter*, base::TimeDelta timeout) override;
void OnTaskRunnerAvailable(scoped_refptr<base::SequencedTaskRunner>,
int sequence_number);
void UpdatePendingResets(int sequence_number);
void OnVotesUpdated();
void ServicePendingResetsLocked() EXCLUSIVE_LOCKS_REQUIRED(lock_);
PowerMode ComputeActiveModeLocked() EXCLUSIVE_LOCKS_REQUIRED(lock_);
void UpdateTraceObserver() LOCKS_EXCLUDED(lock_, trace_observer_lock_);
// trace_event::TraceLog::EnabledStateObserver implementation:
void OnTraceLogEnabled() override;
void OnTraceLogDisabled() override;
// trace_event::TraceLog::IncrementalStateObserver implementation:
void OnIncrementalStateCleared() override;
// Protects trace_observer_{,added_}. Should only be acquired when |lock_| is
// not held.
base::Lock trace_observer_lock_;
std::unique_ptr<Observer> trace_observer_ GUARDED_BY(trace_observer_lock_);
bool trace_observer_added_ GUARDED_BY(trace_observer_lock_) = false;
base::Lock lock_; // Protects subsequent members.
scoped_refptr<base::SequencedTaskRunner> task_runner_ GUARDED_BY(lock_);
std::map<PowerModeVoter*, TracedPowerMode> votes_ GUARDED_BY(lock_);
std::map<PowerModeVoter*, base::TimeTicks /*effective_time*/> pending_resets_
GUARDED_BY(lock_);
base::TimeTicks next_pending_vote_update_time_ GUARDED_BY(lock_);
TracedPowerMode active_mode_ GUARDED_BY(lock_);
base::TimeTicks active_mode_changed_timestamp_ GUARDED_BY(lock_);
int update_task_sequence_number_ GUARDED_BY(lock_) = 0;
scoped_refptr<base::ObserverListThreadSafe<Observer>> observers_
GUARDED_BY(lock_);
bool has_observers_ GUARDED_BY(lock_) = false;
bool charging_mode_enabled_ = true;
// Owned by the arbiter but otherwise behaves like a regular voter.
std::unique_ptr<ChargingPowerModeVoter> charging_voter_;
};
} // namespace power_scheduler
#endif // COMPONENTS_POWER_SCHEDULER_POWER_MODE_ARBITER_H_