/*
 * Copyright (C) 2018 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 "src/ftrace_reader/ftrace_config_muxer.h"

#include <stdint.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>

#include <algorithm>

#include "atrace_wrapper.h"
#include "perfetto/base/utils.h"
#include "proto_translation_table.h"

namespace perfetto {
namespace {

// trace_clocks in preference order.
constexpr const char* kClocks[] = {"boot", "global", "local"};

constexpr int kDefaultPerCpuBufferSizeKb = 512;   // 512kb
constexpr int kMaxPerCpuBufferSizeKb = 2 * 1024;  // 2mb

std::vector<std::string> difference(const std::set<std::string>& a,
                                    const std::set<std::string>& b) {
  std::vector<std::string> result;
  result.reserve(std::max(b.size(), a.size()));
  std::set_difference(a.begin(), a.end(), b.begin(), b.end(),
                      std::inserter(result, result.begin()));
  return result;
}

void AddEventGroup(const ProtoTranslationTable* table,
                   const std::string& group,
                   std::set<std::string>* to) {
  const std::vector<const Event*>* events = table->GetEventsByGroup(group);
  if (!events)
    return;
  for (const Event* event : *events)
    to->insert(event->name);
}

}  // namespace

std::set<std::string> GetFtraceEvents(const FtraceConfig& request,
                                      const ProtoTranslationTable* table) {
  std::set<std::string> events;
  events.insert(request.ftrace_events().begin(), request.ftrace_events().end());
  if (RequiresAtrace(request)) {
    events.insert("print");

    // Ideally we should keep this code in sync with:
    // platform/frameworks/native/cmds/atrace/atrace.cpp
    // It's not a disaster if they go out of sync, we can always add the ftrace
    // categories manually server side but this is user friendly and reduces the
    // size of the configs.
    for (const std::string& category : request.atrace_categories()) {
      if (category == "gfx") {
        AddEventGroup(table, "mdss", &events);
        AddEventGroup(table, "sde", &events);
        continue;
      }

      if (category == "sched") {
        events.insert("sched_switch");
        events.insert("sched_wakeup");
        events.insert("sched_waking");
        events.insert("sched_blocked_reason");
        events.insert("sched_cpu_hotplug");
        AddEventGroup(table, "cgroup", &events);
        continue;
      }

      if (category == "irq") {
        AddEventGroup(table, "irq", &events);
        AddEventGroup(table, "ipi", &events);
        continue;
      }

      if (category == "irqoff") {
        events.insert("irq_enable");
        events.insert("irq_disable");
        continue;
      }

      if (category == "preemptoff") {
        events.insert("preempt_enable");
        events.insert("preempt_disable");
        continue;
      }

      if (category == "i2c") {
        AddEventGroup(table, "i2c", &events);
        continue;
      }

      if (category == "freq") {
        events.insert("cpu_frequency");
        events.insert("clock_set_rate");
        events.insert("clock_disable");
        events.insert("clock_enable");
        events.insert("clk_set_rate");
        events.insert("clk_disable");
        events.insert("clk_enable");
        events.insert("cpu_frequency_limits");
        continue;
      }

      if (category == "membus") {
        AddEventGroup(table, "memory_bus", &events);
        continue;
      }

      if (category == "idle") {
        events.insert("cpu_idle");
        continue;
      }

      if (category == "disk") {
        events.insert("f2fs_sync_file_enter");
        events.insert("f2fs_sync_file_exit");
        events.insert("f2fs_write_begin");
        events.insert("f2fs_write_end");
        events.insert("ext4_da_write_begin");
        events.insert("ext4_da_write_end");
        events.insert("ext4_sync_file_enter");
        events.insert("ext4_sync_file_exit");
        events.insert("block_rq_issue");
        events.insert("block_rq_complete");
        continue;
      }

      if (category == "mmc") {
        AddEventGroup(table, "mmc", &events);
        continue;
      }

      if (category == "load") {
        AddEventGroup(table, "cpufreq_interactive", &events);
        continue;
      }

      if (category == "sync") {
        AddEventGroup(table, "sync", &events);
        continue;
      }

      if (category == "workq") {
        AddEventGroup(table, "workqueue", &events);
        continue;
      }

      if (category == "memreclaim") {
        events.insert("mm_vmscan_direct_reclaim_begin");
        events.insert("mm_vmscan_direct_reclaim_end");
        events.insert("mm_vmscan_kswapd_wake");
        events.insert("mm_vmscan_kswapd_sleep");
        AddEventGroup(table, "lowmemorykiller", &events);
        continue;
      }

      if (category == "regulators") {
        AddEventGroup(table, "regulator", &events);
        continue;
      }

      if (category == "binder_driver") {
        events.insert("binder_transaction");
        events.insert("binder_transaction_received");
        events.insert("binder_set_priority");
        continue;
      }

      if (category == "binder_lock") {
        events.insert("binder_lock");
        events.insert("binder_locked");
        events.insert("binder_unlock");
        continue;
      }

      if (category == "pagecache") {
        AddEventGroup(table, "pagecache", &events);
        continue;
      }
    }
  }
  return events;
}

// Post-conditions:
// 1. result >= 1 (should have at least one page per CPU)
// 2. result * 4 < kMaxTotalBufferSizeKb
// 3. If input is 0 output is a good default number.
size_t ComputeCpuBufferSizeInPages(size_t requested_buffer_size_kb) {
  if (requested_buffer_size_kb == 0)
    requested_buffer_size_kb = kDefaultPerCpuBufferSizeKb;
  if (requested_buffer_size_kb > kMaxPerCpuBufferSizeKb)
    requested_buffer_size_kb = kDefaultPerCpuBufferSizeKb;

  size_t pages = requested_buffer_size_kb / (base::kPageSize / 1024);
  if (pages == 0)
    return 1;

  return pages;
}

FtraceConfigMuxer::FtraceConfigMuxer(FtraceProcfs* ftrace,
                                     const ProtoTranslationTable* table)
    : ftrace_(ftrace), table_(table), current_state_(), configs_() {}
FtraceConfigMuxer::~FtraceConfigMuxer() = default;

FtraceConfigId FtraceConfigMuxer::RequestConfig(const FtraceConfig& request) {
  FtraceConfig actual;

  bool is_ftrace_enabled = ftrace_->IsTracingEnabled();
  if (configs_.empty()) {
    PERFETTO_DCHECK(!current_state_.tracing_on);

    // If someone outside of perfetto is using ftrace give up now.
    if (is_ftrace_enabled)
      return 0;

    // If we're about to turn tracing on use this opportunity do some setup:
    if (RequiresAtrace(request))
      EnableAtrace(request);
    SetupClock(request);
    SetupBufferSize(request);
  } else {
    // Did someone turn ftrace off behind our back? If so give up.
    if (!is_ftrace_enabled)
      return 0;
  }

  std::set<std::string> events = GetFtraceEvents(request, table_);

  for (auto& name : events) {
    const Event* event = table_->GetEventByName(name);
    if (!event) {
      PERFETTO_DLOG("Can't enable %s, event not known", name.c_str());
      continue;
    }
    if (current_state_.ftrace_events.count(name) ||
        std::string("ftrace") == event->group) {
      *actual.add_ftrace_events() = name;
      continue;
    }
    if (ftrace_->EnableEvent(event->group, event->name)) {
      current_state_.ftrace_events.insert(name);
      *actual.add_ftrace_events() = name;
    }
  }

  if (configs_.empty()) {
    PERFETTO_DCHECK(!current_state_.tracing_on);
    ftrace_->EnableTracing();
    current_state_.tracing_on = true;
  }

  FtraceConfigId id = ++last_id_;
  configs_.emplace(id, std::move(actual));
  return id;
}

bool FtraceConfigMuxer::RemoveConfig(FtraceConfigId id) {
  if (!id || !configs_.erase(id))
    return false;

  std::set<std::string> expected_ftrace_events;
  for (const auto& id_config : configs_) {
    const FtraceConfig& config = id_config.second;
    expected_ftrace_events.insert(config.ftrace_events().begin(),
                                  config.ftrace_events().end());
  }

  std::vector<std::string> events_to_disable =
      difference(current_state_.ftrace_events, expected_ftrace_events);

  for (auto& name : events_to_disable) {
    const Event* event = table_->GetEventByName(name);
    if (!event)
      continue;
    if (ftrace_->DisableEvent(event->group, event->name))
      current_state_.ftrace_events.erase(name);
  }

  if (configs_.empty()) {
    PERFETTO_DCHECK(current_state_.tracing_on);
    ftrace_->DisableTracing();
    ftrace_->SetCpuBufferSizeInPages(0);
    ftrace_->DisableAllEvents();
    ftrace_->ClearTrace();
    current_state_.tracing_on = false;
    if (current_state_.atrace_on)
      DisableAtrace();
  }

  return true;
}

const FtraceConfig* FtraceConfigMuxer::GetConfig(FtraceConfigId id) {
  if (!configs_.count(id))
    return nullptr;
  return &configs_.at(id);
}

void FtraceConfigMuxer::SetupClock(const FtraceConfig&) {
  std::string current_clock = ftrace_->GetClock();
  std::set<std::string> clocks = ftrace_->AvailableClocks();

  for (size_t i = 0; i < base::ArraySize(kClocks); i++) {
    std::string clock = std::string(kClocks[i]);
    if (!clocks.count(clock))
      continue;
    if (current_clock == clock)
      break;
    ftrace_->SetClock(clock);
    break;
  }
}

void FtraceConfigMuxer::SetupBufferSize(const FtraceConfig& request) {
  size_t pages = ComputeCpuBufferSizeInPages(request.buffer_size_kb());
  ftrace_->SetCpuBufferSizeInPages(pages);
  current_state_.cpu_buffer_size_pages = pages;
}

void FtraceConfigMuxer::EnableAtrace(const FtraceConfig& request) {
  PERFETTO_DCHECK(!current_state_.atrace_on);

  PERFETTO_DLOG("Start atrace...");

  std::vector<std::string> args;
  args.push_back("atrace");  // argv0 for exec()
  args.push_back("--async_start");
  for (const auto& category : request.atrace_categories())
    args.push_back(category);
  if (!request.atrace_apps().empty()) {
    args.push_back("-a");
    for (const auto& app : request.atrace_apps())
      args.push_back(app);
  }

  if (RunAtrace(args))
    current_state_.atrace_on = true;

  PERFETTO_DLOG("...done");
}

void FtraceConfigMuxer::DisableAtrace() {
  PERFETTO_DCHECK(current_state_.atrace_on);

  PERFETTO_DLOG("Stop atrace...");

  if (RunAtrace({"atrace", "--async_stop"}))
    current_state_.atrace_on = false;

  PERFETTO_DLOG("...done");
}

}  // namespace perfetto
