//
// Copyright (C) 2017 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 "update_engine/aosp/metrics_reporter_android.h"

#include <stdint.h>

#include <algorithm>
#include <any>
#include <memory>
#include <string>

#include <android-base/properties.h>
#include <base/strings/string_util.h>
#include <fs_mgr.h>
#include <libdm/dm.h>
#include <liblp/builder.h>
#include <liblp/liblp.h>
#include <statslog.h>

#include "update_engine/common/constants.h"
#include "update_engine/payload_consumer/install_plan.h"

using android::fs_mgr::GetPartitionGroupName;
using android::fs_mgr::LpMetadata;
using android::fs_mgr::MetadataBuilder;
using android::fs_mgr::ReadMetadata;
using android::fs_mgr::SlotNumberForSlotSuffix;
using base::EndsWith;

namespace {
// A number offset adds on top of the enum value. e.g. ErrorCode::SUCCESS will
// be reported as 10000, and AttemptResult::UPDATE_CANCELED will be reported as
// 10011. This keeps the ordering of update engine's enum definition when statsd
// atoms reserve the value 0 for unknown state.
constexpr auto kMetricsReporterEnumOffset = 10000;

int32_t GetStatsdEnumValue(int32_t value) {
  return kMetricsReporterEnumOffset + value;
}

bool IsHashTreeEnabled(
    const chromeos_update_engine::InstallPlan* install_plan) {
  return std::any_of(
      install_plan->partitions.begin(),
      install_plan->partitions.end(),
      [](const auto& partition) { return partition.hash_tree_size > 0; });
}

bool IsFECEnabled(const chromeos_update_engine::InstallPlan* install_plan) {
  return std::any_of(
      install_plan->partitions.begin(),
      install_plan->partitions.end(),
      [](const auto& partition) { return partition.fec_size > 0; });
}

}  // namespace

namespace chromeos_update_engine {

namespace metrics {

std::unique_ptr<MetricsReporterInterface> CreateMetricsReporter(
    DynamicPartitionControlInterface* dynamic_partition_control,
    const InstallPlan* install_plan) {
  return std::make_unique<MetricsReporterAndroid>(dynamic_partition_control,
                                                  install_plan);
}

}  // namespace metrics

void MetricsReporterAndroid::ReportUpdateAttemptMetrics(
    int attempt_number,
    PayloadType payload_type,
    base::TimeDelta duration,
    base::TimeDelta duration_uptime,
    int64_t payload_size,
    metrics::AttemptResult attempt_result,
    ErrorCode error_code) {
  int64_t payload_size_mib = payload_size / kNumBytesInOneMiB;

  int64_t super_partition_size_bytes = 0;
  int64_t super_free_space = 0;
  int64_t slot_size_bytes = 0;

  if (android::base::GetBoolProperty("ro.boot.dynamic_partitions", false)) {
    uint32_t slot = SlotNumberForSlotSuffix(fs_mgr_get_slot_suffix());
    auto super_device = fs_mgr_get_super_partition_name();
    std::unique_ptr<LpMetadata> metadata = ReadMetadata(super_device, slot);
    if (metadata) {
      super_partition_size_bytes = GetTotalSuperPartitionSize(*metadata);

      for (const auto& group : metadata->groups) {
        if (EndsWith(GetPartitionGroupName(group),
                     fs_mgr_get_slot_suffix(),
                     base::CompareCase::SENSITIVE)) {
          slot_size_bytes += group.maximum_size;
        }
      }

      auto metadata_builder = MetadataBuilder::New(*metadata);
      if (metadata_builder) {
        auto free_regions = metadata_builder->GetFreeRegions();
        for (const auto& interval : free_regions) {
          super_free_space += interval.length();
        }
        super_free_space *= android::dm::kSectorSize;
      } else {
        LOG(ERROR) << "Cannot create metadata builder.";
      }
    } else {
      LOG(ERROR) << "Could not read dynamic partition metadata for device: "
                 << super_device;
    }
  }

  bool vab_compression_enabled = android::base::GetBoolProperty(
      "ro.virtual_ab.compression.enabled", false);
  bool vab_compression_used =
      dynamic_partition_control_->UpdateUsesSnapshotCompression();

  android::util::stats_write(
      android::util::UPDATE_ENGINE_UPDATE_ATTEMPT_REPORTED,
      attempt_number,
      GetStatsdEnumValue(static_cast<int32_t>(payload_type)),
      duration.InMinutes(),
      duration_uptime.InMinutes(),
      payload_size_mib,
      GetStatsdEnumValue(static_cast<int32_t>(attempt_result)),
      GetStatsdEnumValue(static_cast<int32_t>(error_code)),
      android::base::GetProperty("ro.build.fingerprint", "").c_str(),
      super_partition_size_bytes,
      slot_size_bytes,
      super_free_space,
      vab_compression_enabled,
      vab_compression_used);
}

void MetricsReporterAndroid::ReportUpdateAttemptDownloadMetrics(
    int64_t payload_bytes_downloaded,
    int64_t /* payload_download_speed_bps */,
    DownloadSource /* download_source */,
    metrics::DownloadErrorCode /* payload_download_error_code */,
    metrics::ConnectionType /* connection_type */) {
  // TODO(xunchang) add statsd reporting
  LOG(INFO) << "Current update attempt downloads "
            << payload_bytes_downloaded / kNumBytesInOneMiB << " bytes data";
}

void MetricsReporterAndroid::ReportSuccessfulUpdateMetrics(
    int attempt_count,
    int /* updates_abandoned_count */,
    PayloadType payload_type,
    int64_t payload_size,
    int64_t num_bytes_downloaded[kNumDownloadSources],
    int download_overhead_percentage,
    base::TimeDelta total_duration,
    base::TimeDelta /* total_duration_uptime */,
    int reboot_count,
    int /* url_switch_count */) {
  int64_t payload_size_mib = payload_size / kNumBytesInOneMiB;
  int64_t total_bytes_downloaded = 0;
  for (size_t i = 0; i < kNumDownloadSources; i++) {
    total_bytes_downloaded += num_bytes_downloaded[i] / kNumBytesInOneMiB;
  }

  android::util::stats_write(
      android::util::UPDATE_ENGINE_SUCCESSFUL_UPDATE_REPORTED,
      static_cast<int32_t>(attempt_count),
      GetStatsdEnumValue(static_cast<int32_t>(payload_type)),
      static_cast<int32_t>(payload_size_mib),
      static_cast<int32_t>(total_bytes_downloaded),
      static_cast<int32_t>(download_overhead_percentage),
      static_cast<int32_t>(total_duration.InMinutes()),
      static_cast<int32_t>(reboot_count),
      IsHashTreeEnabled(install_plan_),
      IsFECEnabled(install_plan_));
}

void MetricsReporterAndroid::ReportAbnormallyTerminatedUpdateAttemptMetrics() {
  int attempt_result =
      static_cast<int>(metrics::AttemptResult::kAbnormalTermination);
  // TODO(xunchang) add statsd reporting
  LOG(INFO) << "Abnormally terminated update attempt result " << attempt_result;
}

};  // namespace chromeos_update_engine
