blob: e4efcd5d7ada68e0565ae111cf2764a379b32382 [file] [log] [blame]
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "services/device/compute_pressure/cpu_probe_manager.h"
#include <memory>
#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/functional/callback_helpers.h"
#include "base/location.h"
#include "base/memory/weak_ptr.h"
#include "base/rand_util.h"
#include "build/build_config.h"
#include "components/system_cpu/cpu_probe.h"
#include "services/device/public/cpp/device_features.h"
namespace device {
namespace {
using system_cpu::CpuProbe;
using system_cpu::CpuSample;
} // namespace
// static
std::unique_ptr<CpuProbeManager> CpuProbeManager::Create(
base::TimeDelta sampling_interval,
base::RepeatingCallback<void(mojom::PressureDataPtr)> sampling_callback) {
std::unique_ptr<CpuProbe> system_cpu_probe = CpuProbe::Create();
if (!system_cpu_probe) {
return nullptr;
}
return base::WrapUnique(new CpuProbeManager(
sampling_interval, sampling_callback, std::move(system_cpu_probe)));
}
// static
std::unique_ptr<CpuProbeManager> CpuProbeManager::CreateForTesting(
base::TimeDelta sampling_interval,
base::RepeatingCallback<void(mojom::PressureDataPtr)> sampling_callback,
std::unique_ptr<CpuProbe> system_cpu_probe) {
if (!system_cpu_probe) {
return nullptr;
}
return base::WrapUnique(new CpuProbeManager(
sampling_interval, sampling_callback, std::move(system_cpu_probe)));
}
CpuProbeManager::CpuProbeManager(
base::TimeDelta sampling_interval,
base::RepeatingCallback<void(mojom::PressureDataPtr)> sampling_callback,
std::unique_ptr<CpuProbe> system_cpu_probe)
: sampling_interval_(sampling_interval),
sampling_callback_(std::move(sampling_callback)),
system_cpu_probe_(std::move(system_cpu_probe)) {
CHECK(system_cpu_probe_);
CHECK(sampling_callback_);
}
CpuProbeManager::~CpuProbeManager() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
}
void CpuProbeManager::EnsureStarted() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (timer_.IsRunning()) {
// Already started.
return;
}
// The CpuSample reported by many CpuProbe implementations relies on the
// differences observed between two Update() calls. For this reason, the
// CpuSample reported from StartSampling() is not reported via
// `sampling_callback_`.
system_cpu_probe_->StartSampling(base::DoNothing());
timer_.Start(FROM_HERE, sampling_interval_,
base::BindRepeating(
&CpuProbe::RequestSample, system_cpu_probe_->GetWeakPtr(),
base::BindRepeating(&CpuProbeManager::OnCpuSampleAvailable,
weak_factory_.GetWeakPtr())));
}
void CpuProbeManager::Stop() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
timer_.Stop();
weak_factory_.InvalidateWeakPtrs();
}
system_cpu::CpuProbe* CpuProbeManager::cpu_probe() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return system_cpu_probe_.get();
}
void CpuProbeManager::OnCpuSampleAvailable(std::optional<CpuSample> sample) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// If the timer was stopped, OnCpuSampleAvailable should have been cancelled
// by InvalidateWeakPtrs().
CHECK(timer_.IsRunning());
if (sample.has_value()) {
auto data = mojom::PressureData::New(
sample.value().cpu_utilization, mojom::kDefaultOwnContributionEstimate);
sampling_callback_.Run(std::move(data));
}
}
void CpuProbeManager::SetCpuProbeForTesting(
std::unique_ptr<system_cpu::CpuProbe> cpu_probe) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
CHECK(!timer_.IsRunning());
system_cpu_probe_ = std::move(cpu_probe);
}
} // namespace device