910e62b5创建于 1月15日历史提交
// Copyright 2024 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/probes_manager.h"

#include "base/time/time.h"
#include "components/system_cpu/cpu_probe.h"
#include "services/device/compute_pressure/cpu_probe_manager.h"
#include "services/device/public/mojom/pressure_manager.mojom.h"
#include "services/device/public/mojom/pressure_update.mojom.h"

namespace device {

ProbesManager::ProbesManager(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.
    : sampling_interval_(sampling_interval),
      cpu_probe_sampling_callback_(
          base::BindRepeating(&ProbesManager::UpdateClients,
                              base::Unretained(this),
                              mojom::PressureSource::kCpu)),
      cpu_probe_manager_(
          CpuProbeManager::Create(sampling_interval,
                                  cpu_probe_sampling_callback_)) {
  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
    // this instance.
    associated_clients_[source].set_disconnect_handler(
        base::BindRepeating(&ProbesManager::OnClientRemoteDisconnected,
                            base::Unretained(this), source));
  }
}

ProbesManager::~ProbesManager() = default;

bool ProbesManager::is_supported(mojom::PressureSource source) const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  switch (source) {
    case mojom::PressureSource::kCpu:
      return !!cpu_probe_manager_;
  }
}

void ProbesManager::RegisterClientRemote(
    mojo::PendingAssociatedRemote<mojom::PressureClient> associated_client,
    mojom::PressureSource source) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  switch (source) {
    case mojom::PressureSource::kCpu: {
      CHECK(cpu_probe_manager_);
      associated_clients_[source].Add(std::move(associated_client));
      cpu_probe_manager_->EnsureStarted();
    }
  }
}

base::TimeDelta ProbesManager::sampling_interval_for_testing() const {
  return sampling_interval_;
}

void ProbesManager::UpdateClients(mojom::PressureSource source,
                                  mojom::PressureDataPtr data) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  const base::TimeTicks timestamp = base::TimeTicks::Now();

  mojom::PressureUpdate update(source, std::move(data), timestamp);
  for (auto& client : associated_clients_[source]) {
    client->OnPressureUpdated(update.Clone());
  }
}

void ProbesManager::OnClientRemoteDisconnected(
    mojom::PressureSource source,
    mojo::RemoteSetElementId /*id*/) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  if (associated_clients_[source].empty()) {
    switch (source) {
      case mojom::PressureSource::kCpu: {
        if (cpu_probe_manager_) {
          cpu_probe_manager_->Stop();
        }
        return;
      }
    }
  }
}

CpuProbeManager* ProbesManager::cpu_probe_manager() const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  return cpu_probe_manager_.get();
}

void ProbesManager::set_cpu_probe_manager(
    std::unique_ptr<CpuProbeManager> cpu_probe_manager) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  cpu_probe_manager_ = std::move(cpu_probe_manager);
}

const base::RepeatingCallback<void(mojom::PressureDataPtr)>&
ProbesManager::cpu_probe_sampling_callback() const {
  return cpu_probe_sampling_callback_;
}

}  // namespace device