blob: 3dd646965e9337a6c0aa6d3569dcfae2e988881b [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/pressure_manager_impl.h"
#include <utility>
#include "base/functional/bind.h"
#include "base/memory/ptr_util.h"
#include "base/time/time.h"
#include "mojo/public/cpp/bindings/message.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
namespace device {
constexpr base::TimeDelta PressureManagerImpl::kDefaultSamplingInterval;
// static
std::unique_ptr<PressureManagerImpl> PressureManagerImpl::Create() {
return base::WrapUnique(new PressureManagerImpl(kDefaultSamplingInterval));
}
PressureManagerImpl::PressureManagerImpl(base::TimeDelta sampling_interval)
// base::Unretained usage is safe here because the callback is only run
// while `cpu_probe_manager_` is alive, and `cpu_probe_manager_` is owned by
// this instance.
: cpu_probe_manager_(std::make_unique<CpuProbeManager>(
sampling_interval,
base::BindRepeating(&PressureManagerImpl::UpdateClients,
base::Unretained(this),
mojom::PressureSource::kCpu))) {
constexpr size_t kPressureSourceSize =
static_cast<size_t>(mojom::PressureSource::kMaxValue) + 1u;
for (size_t source_index = 0u; source_index < kPressureSourceSize;
++source_index) {
auto source = static_cast<mojom::PressureSource>(source_index);
// base::Unretained use is safe because mojo guarantees the callback will
// not be called after `clients_` is deallocated, and `clients_` is owned by
// PressureManagerImpl.
clients_[source].set_disconnect_handler(
base::BindRepeating(&PressureManagerImpl::OnClientRemoteDisconnected,
base::Unretained(this), source));
}
}
PressureManagerImpl::~PressureManagerImpl() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
}
void PressureManagerImpl::Bind(
mojo::PendingReceiver<mojom::PressureManager> receiver) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
receivers_.Add(this, std::move(receiver));
}
void PressureManagerImpl::AddClient(
mojo::PendingRemote<mojom::PressureClient> client,
mojom::PressureSource source,
AddClientCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
switch (source) {
case mojom::PressureSource::kCpu: {
if (!cpu_probe_manager_) {
std::move(callback).Run(mojom::PressureStatus::kNotSupported);
return;
}
clients_[source].Add(std::move(client));
cpu_probe_manager_->EnsureStarted();
std::move(callback).Run(mojom::PressureStatus::kOk);
break;
}
}
}
void PressureManagerImpl::UpdateClients(mojom::PressureSource source,
mojom::PressureState state) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
const base::Time timestamp = base::Time::Now();
mojom::PressureUpdate update(source, state, timestamp);
for (auto& client : clients_[source]) {
client->OnPressureUpdated(update.Clone());
}
}
void PressureManagerImpl::OnClientRemoteDisconnected(
mojom::PressureSource source,
mojo::RemoteSetElementId /*id*/) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (clients_[source].empty()) {
switch (source) {
case mojom::PressureSource::kCpu: {
cpu_probe_manager_->Stop();
return;
}
}
}
}
void PressureManagerImpl::SetCpuProbeManagerForTesting(
std::unique_ptr<CpuProbeManager> cpu_probe_manager) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
cpu_probe_manager_ = std::move(cpu_probe_manager);
}
} // namespace device