/*
 * Copyright (C) 2021 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "reporter.h"

#include <android-base/parseint.h>

#include <algorithm>

#include "base/flags.h"
#include "base/stl_util.h"
#include "oat/oat_file_manager.h"
#include "runtime.h"
#include "runtime_options.h"
#include "statsd.h"
#include "thread-current-inl.h"

#pragma clang diagnostic push
#pragma clang diagnostic error "-Wconversion"

namespace art HIDDEN {
namespace metrics {

std::unique_ptr<MetricsReporter> MetricsReporter::Create(
    const ReportingConfig& config, Runtime* runtime) {
  // We can't use std::make_unique here because the MetricsReporter constructor is private.
  return std::unique_ptr<MetricsReporter>{new MetricsReporter{std::move(config), runtime}};
}

MetricsReporter::MetricsReporter(const ReportingConfig& config, Runtime* runtime)
    : config_{config},
      runtime_{runtime},
      startup_reported_{false},
      report_interval_index_{0} {}

MetricsReporter::~MetricsReporter() { MaybeStopBackgroundThread(); }

void MetricsReporter::ReloadConfig(const ReportingConfig& config) {
  DCHECK(!thread_.has_value()) << "The config cannot be reloaded after the background "
                                  "reporting thread is started.";
  config_ = config;
}

bool MetricsReporter::IsMetricsReportingEnabled(const SessionData& session_data) const {
  return session_data.session_id % config_.reporting_num_mods < config_.reporting_mods;
}

bool MetricsReporter::MaybeStartBackgroundThread(SessionData session_data) {
  CHECK(!thread_.has_value());

  session_data_ = session_data;
  LOG_STREAM(DEBUG) << "Received session metadata: " << session_data_.session_id;

  if (!IsMetricsReportingEnabled(session_data_)) {
    return false;
  }

  thread_.emplace(&MetricsReporter::BackgroundThreadRun, this);
  return true;
}

void MetricsReporter::MaybeStopBackgroundThread() {
  if (thread_.has_value()) {
    messages_.SendMessage(ShutdownRequestedMessage{});
    thread_->join();
    thread_.reset();
  }
}

void MetricsReporter::NotifyStartupCompleted() {
  if (ShouldReportAtStartup() && thread_.has_value()) {
    messages_.SendMessage(StartupCompletedMessage{});
  }
}

void MetricsReporter::NotifyAppInfoUpdated(AppInfo* app_info) {
  std::string compilation_reason;
  std::string compiler_filter;

  app_info->GetPrimaryApkOptimizationStatus(
      &compiler_filter, &compilation_reason);

  SetCompilationInfo(
      CompilationReasonFromName(compilation_reason),
      CompilerFilterReportingFromName(compiler_filter));
}

void MetricsReporter::RequestMetricsReport(bool synchronous) {
  if (thread_.has_value()) {
    messages_.SendMessage(RequestMetricsReportMessage{synchronous});
    if (synchronous) {
      thread_to_host_messages_.ReceiveMessage();
    }
  }
}

void MetricsReporter::SetCompilationInfo(CompilationReason compilation_reason,
                                         CompilerFilterReporting compiler_filter) {
  if (thread_.has_value()) {
    messages_.SendMessage(CompilationInfoMessage{compilation_reason, compiler_filter});
  }
}

void MetricsReporter::BackgroundThreadRun() {
  LOG_STREAM(DEBUG) << "Metrics reporting thread started";

  // AttachCurrentThread is needed so we can safely use the ART concurrency primitives within the
  // messages_ MessageQueue.
  const bool attached = runtime_->AttachCurrentThread(kBackgroundThreadName,
                                                      /*as_daemon=*/true,
                                                      runtime_->GetSystemThreadGroup(),
                                                      /*create_peer=*/true);
  bool running = true;

  // Configure the backends
  if (config_.dump_to_logcat) {
    backends_.emplace_back(new LogBackend(std::make_unique<TextFormatter>(), LogSeverity::INFO));
  }
  if (config_.dump_to_file.has_value()) {
    std::unique_ptr<MetricsFormatter> formatter;
    if (config_.metrics_format == "xml") {
      formatter = std::make_unique<XmlFormatter>();
    } else {
      formatter = std::make_unique<TextFormatter>();
    }

    backends_.emplace_back(new FileBackend(std::move(formatter), config_.dump_to_file.value()));
  }
  if (config_.dump_to_statsd) {
    auto backend = CreateStatsdBackend();
    if (backend != nullptr) {
      backends_.emplace_back(std::move(backend));
    }
  }

  MaybeResetTimeout();

  while (running) {
    messages_.SwitchReceive(
        [&]([[maybe_unused]] ShutdownRequestedMessage message) {
          LOG_STREAM(DEBUG) << "Shutdown request received " << session_data_.session_id;
          running = false;

          ReportMetrics();
        },
        [&](RequestMetricsReportMessage message) {
          LOG_STREAM(DEBUG) << "Explicit report request received " << session_data_.session_id;
          ReportMetrics();
          if (message.synchronous) {
            thread_to_host_messages_.SendMessage(ReportCompletedMessage{});
          }
        },
        [&]([[maybe_unused]] TimeoutExpiredMessage message) {
          LOG_STREAM(DEBUG) << "Timer expired, reporting metrics " << session_data_.session_id;

          ReportMetrics();
          MaybeResetTimeout();
        },
        [&]([[maybe_unused]] StartupCompletedMessage message) {
          LOG_STREAM(DEBUG) << "App startup completed, reporting metrics "
              << session_data_.session_id;
          ReportMetrics();
          startup_reported_ = true;
          MaybeResetTimeout();
        },
        [&](CompilationInfoMessage message) {
          LOG_STREAM(DEBUG) << "Compilation info received " << session_data_.session_id;
          session_data_.compilation_reason = message.compilation_reason;
          session_data_.compiler_filter = message.compiler_filter;

          UpdateSessionInBackends();
        });
  }

  if (attached) {
    runtime_->DetachCurrentThread();
  }
  LOG_STREAM(DEBUG) << "Metrics reporting thread terminating " << session_data_.session_id;
}

void MetricsReporter::MaybeResetTimeout() {
  if (ShouldContinueReporting()) {
    messages_.SetTimeout(SecondsToMs(GetNextPeriodSeconds()));
  }
}

ArtMetrics* MetricsReporter::GetMetrics() { return runtime_->GetMetrics(); }

void MetricsReporter::ReportMetrics() {
  ArtMetrics* metrics = GetMetrics();

  if (!session_started_) {
    for (auto& backend : backends_) {
      backend->BeginOrUpdateSession(session_data_);
    }
    session_started_ = true;
  }

  metrics->ReportAllMetricsAndResetValueMetrics(MakeNonOwningPointerVector(backends_));
}

void MetricsReporter::UpdateSessionInBackends() {
  if (session_started_) {
    for (auto& backend : backends_) {
      backend->BeginOrUpdateSession(session_data_);
    }
  }
}

bool MetricsReporter::ShouldReportAtStartup() const {
  return IsMetricsReportingEnabled(session_data_) &&
      config_.period_spec.has_value() &&
      config_.period_spec->report_startup_first;
}

bool MetricsReporter::ShouldContinueReporting() const {
  bool result =
      // Only if the reporting is enabled
      IsMetricsReportingEnabled(session_data_) &&
      // and if we have period spec
      config_.period_spec.has_value() &&
      // and the periods are non empty
      !config_.period_spec->periods_seconds.empty() &&
      // and we already reported startup or not required to report startup
      (startup_reported_ || !config_.period_spec->report_startup_first) &&
      // and we still have unreported intervals or we are asked to report continuously.
      (config_.period_spec->continuous_reporting ||
              (report_interval_index_ < config_.period_spec->periods_seconds.size()));
  return result;
}

uint32_t MetricsReporter::GetNextPeriodSeconds() {
  DCHECK(ShouldContinueReporting());

  // The index is either the current report_interval_index or the last index
  // if we are in continuous mode and reached the end.
  uint32_t index = std::min(
      report_interval_index_,
      static_cast<uint32_t>(config_.period_spec->periods_seconds.size() - 1));

  uint32_t result = config_.period_spec->periods_seconds[index];

  // Advance the index if we didn't get to the end.
  if (report_interval_index_ < config_.period_spec->periods_seconds.size()) {
    report_interval_index_++;
  }
  return result;
}

ReportingConfig ReportingConfig::FromFlags(bool is_system_server) {
  std::optional<std::string> spec_str = is_system_server
      ? gFlags.MetricsReportingSpecSystemServer.GetValueOptional()
      : gFlags.MetricsReportingSpec.GetValueOptional();

  std::optional<ReportingPeriodSpec> period_spec = std::nullopt;

  if (spec_str.has_value()) {
    std::string error;
    period_spec = ReportingPeriodSpec::Parse(spec_str.value(), &error);
    if (!period_spec.has_value()) {
      LOG(ERROR) << "Failed to create metrics reporting spec from: " << spec_str.value()
          << " with error: " << error;
    }
  }

  uint32_t reporting_num_mods = is_system_server
      ? gFlags.MetricsReportingNumModsServer()
      : gFlags.MetricsReportingNumMods();
  uint32_t reporting_mods = is_system_server
      ? gFlags.MetricsReportingModsServer()
      : gFlags.MetricsReportingMods();

  if (reporting_mods > reporting_num_mods || reporting_num_mods == 0) {
    LOG(ERROR) << "Invalid metrics reporting mods: " << reporting_mods
        << " num modes=" << reporting_num_mods
        << ". The reporting is disabled";
    reporting_mods = 0;
    reporting_num_mods = 100;
  }

  return {
      .dump_to_logcat = gFlags.MetricsWriteToLogcat(),
      .dump_to_statsd = gFlags.MetricsWriteToStatsd(),
      .dump_to_file = gFlags.MetricsWriteToFile.GetValueOptional(),
      .metrics_format = gFlags.MetricsFormat(),
      .period_spec = period_spec,
      .reporting_mods = reporting_mods,
      .reporting_num_mods = reporting_num_mods,
  };
}

std::optional<ReportingPeriodSpec> ReportingPeriodSpec::Parse(
    const std::string& spec_str, std::string* error_msg) {
  *error_msg = "";
  if (spec_str.empty()) {
    *error_msg = "Invalid empty spec.";
    return std::nullopt;
  }

  // Split the string. Each element is separated by comma.
  std::vector<std::string> elems;
  Split(spec_str, ',', &elems);

  // Check the startup marker (front) and the continuous one (back).
  std::optional<ReportingPeriodSpec> spec = std::make_optional(ReportingPeriodSpec());
  spec->spec = spec_str;
  spec->report_startup_first = elems.front() == "S";
  spec->continuous_reporting = elems.back() == "*";

  // Compute the indices for the period values.
  size_t start_interval_idx = spec->report_startup_first ? 1 : 0;
  size_t end_interval_idx = spec->continuous_reporting ? (elems.size() - 1) : elems.size();

  // '*' needs a numeric interval before in order to be valid.
  if (spec->continuous_reporting &&
      end_interval_idx == start_interval_idx) {
    *error_msg = "Invalid period value in spec: " + spec_str;
    return std::nullopt;
  }

  // Parse the periods.
  for (size_t i = start_interval_idx; i < end_interval_idx; i++) {
    uint32_t period;
    if (!android::base::ParseUint(elems[i], &period)) {
        *error_msg = "Invalid period value in spec: " + spec_str;
        return std::nullopt;
    }
    spec->periods_seconds.push_back(period);
  }

  return spec;
}

}  // namespace metrics
}  // namespace art

#pragma clang diagnostic pop  // -Wconversion
