// Copyright 2019 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.

#include "cc/metrics/throughput_ukm_reporter.h"

#include "cc/trees/ukm_manager.h"

namespace cc {

namespace {
// Collect UKM once per kNumberOfSamplesToReport UMA reports.
constexpr unsigned kNumberOfSamplesToReport = 100u;
}  // namespace

ThroughputUkmReporter::ThroughputUkmReporter(UkmManager* ukm_manager)
    : ukm_manager_(ukm_manager) {
  DCHECK(ukm_manager_);
}

ThroughputUkmReporter::~ThroughputUkmReporter() = default;

void ThroughputUkmReporter::ReportThroughputUkm(
    const base::Optional<int>& slower_throughput_percent,
    const base::Optional<int>& impl_throughput_percent,
    const base::Optional<int>& main_throughput_percent,
    FrameSequenceTrackerType type) {
  // It is possible that when a tab shuts down, the ukm_manager_ owned by the
  // LayerTreeHostImpl is cleared, and yet we try to report to UKM here. In this
  // case, the |ukm_manager_| here is null.
  if (!ukm_manager_)
    return;
  if (samples_to_next_event_[static_cast<int>(type)] == 0) {
    // Sample every 100 events. If a tracker reports UMA every 5s, then the
    // system collects UKM once per 100*5 = 500 seconds. This number may need to
    // be tuned to not throttle the UKM system.
    samples_to_next_event_[static_cast<int>(type)] = kNumberOfSamplesToReport;
    if (impl_throughput_percent) {
      ukm_manager_->RecordThroughputUKM(
          type, FrameSequenceMetrics::ThreadType::kCompositor,
          impl_throughput_percent.value());
    }
    if (main_throughput_percent) {
      ukm_manager_->RecordThroughputUKM(type,
                                        FrameSequenceMetrics::ThreadType::kMain,
                                        main_throughput_percent.value());
    }
  }
  DCHECK_GT(samples_to_next_event_[static_cast<int>(type)], 0u);
  samples_to_next_event_[static_cast<int>(type)]--;
}

void ThroughputUkmReporter::ReportAggregateThroughput(
    AggregationType aggregation_type,
    int throughput) {
  if (samples_for_aggregated_report_ == 0) {
    samples_for_aggregated_report_ = kNumberOfSamplesToReport;
    ukm_manager_->RecordAggregateThroughput(aggregation_type, throughput);
  }
  DCHECK_GT(samples_for_aggregated_report_, 0u);
  --samples_for_aggregated_report_;
}

uint32_t ThroughputUkmReporter::GetSamplesToNextEventForTesting(int index) {
  DCHECK_LT(index, static_cast<int>(FrameSequenceTrackerType::kMaxType));
  return samples_to_next_event_[index];
}

}  // namespace cc
