// Copyright (c) 2012 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 "base/trace_event/trace_event_impl.h"

#include <fcntl.h>
#include <stddef.h>
#include <stdint.h>

#include "base/format_macros.h"
#include "base/logging.h"
#include "base/posix/eintr_wrapper.h"
#include "base/strings/stringprintf.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread.h"
#include "base/trace_event/trace_event.h"

namespace base {
namespace trace_event {

namespace {

int g_atrace_fd = -1;
const char kATraceMarkerFile[] = "/sys/kernel/debug/tracing/trace_marker";

void WriteToATrace(int fd, const char* buffer, size_t size) {
  size_t total_written = 0;
  while (total_written < size) {
    ssize_t written = HANDLE_EINTR(write(
        fd, buffer + total_written, size - total_written));
    if (written <= 0)
      break;
    total_written += written;
  }
  if (total_written < size) {
    PLOG(WARNING) << "Failed to write buffer '" << std::string(buffer, size)
                  << "' to " << kATraceMarkerFile;
  }
}

void WriteEvent(
    char phase,
    const char* category_group,
    const char* name,
    unsigned long long id,
    const char** arg_names,
    const unsigned char* arg_types,
    const TraceEvent::TraceValue* arg_values,
    const std::unique_ptr<ConvertableToTraceFormat>* convertable_values,
    unsigned int flags) {
  std::string out = StringPrintf("%c|%d|%s", phase, getpid(), name);
  if (flags & TRACE_EVENT_FLAG_HAS_ID)
    StringAppendF(&out, "-%" PRIx64, static_cast<uint64_t>(id));
  out += '|';

  for (int i = 0; i < kTraceMaxNumArgs && arg_names[i];
       ++i) {
    if (i)
      out += ';';
    out += arg_names[i];
    out += '=';
    std::string::size_type value_start = out.length();
    if (arg_types[i] == TRACE_VALUE_TYPE_CONVERTABLE)
      convertable_values[i]->AppendAsTraceFormat(&out);
    else
      TraceEvent::AppendValueAsJSON(arg_types[i], arg_values[i], &out);

    // Remove the quotes which may confuse the atrace script.
    ReplaceSubstringsAfterOffset(&out, value_start, "\\\"", "'");
    ReplaceSubstringsAfterOffset(&out, value_start, "\"", "");
    // Replace chars used for separators with similar chars in the value.
    std::replace(out.begin() + value_start, out.end(), ';', ',');
    std::replace(out.begin() + value_start, out.end(), '|', '!');
  }

  out += '|';
  out += category_group;
  WriteToATrace(g_atrace_fd, out.c_str(), out.size());
}

void NoOpOutputCallback(WaitableEvent* complete_event,
                        const scoped_refptr<RefCountedString>&,
                        bool has_more_events) {
  if (!has_more_events)
    complete_event->Signal();
}

void EndChromeTracing(TraceLog* trace_log,
                      WaitableEvent* complete_event) {
  trace_log->SetDisabled();
  // Delete the buffered trace events as they have been sent to atrace.
  trace_log->Flush(Bind(&NoOpOutputCallback, complete_event));
}

}  // namespace

// These functions support Android systrace.py when 'webview' category is
// traced. With the new adb_profile_chrome, we may have two phases:
// - before WebView is ready for combined tracing, we can use adb_profile_chrome
//   to trace android categories other than 'webview' and chromium categories.
//   In this way we can avoid the conflict between StartATrace/StopATrace and
//   the intents.
// - TODO(wangxianzhu): after WebView is ready for combined tracing, remove
//   StartATrace, StopATrace and SendToATrace, and perhaps send Java traces
//   directly to atrace in trace_event_binding.cc.

void TraceLog::StartATrace() {
  if (g_atrace_fd != -1)
    return;

  g_atrace_fd = HANDLE_EINTR(open(kATraceMarkerFile, O_WRONLY));
  if (g_atrace_fd == -1) {
    PLOG(WARNING) << "Couldn't open " << kATraceMarkerFile;
    return;
  }
  TraceConfig trace_config;
  trace_config.SetTraceRecordMode(RECORD_CONTINUOUSLY);
  SetEnabled(trace_config, TraceLog::RECORDING_MODE);
}

void TraceLog::StopATrace() {
  if (g_atrace_fd == -1)
    return;

  close(g_atrace_fd);
  g_atrace_fd = -1;

  // TraceLog::Flush() requires the current thread to have a message loop, but
  // this thread called from Java may not have one, so flush in another thread.
  Thread end_chrome_tracing_thread("end_chrome_tracing");
  WaitableEvent complete_event(WaitableEvent::ResetPolicy::AUTOMATIC,
                               WaitableEvent::InitialState::NOT_SIGNALED);
  end_chrome_tracing_thread.Start();
  end_chrome_tracing_thread.task_runner()->PostTask(
      FROM_HERE, base::Bind(&EndChromeTracing, Unretained(this),
                            Unretained(&complete_event)));
  complete_event.Wait();
}

void TraceEvent::SendToATrace() {
  if (g_atrace_fd == -1)
    return;

  const char* category_group =
      TraceLog::GetCategoryGroupName(category_group_enabled_);

  switch (phase_) {
    case TRACE_EVENT_PHASE_BEGIN:
      WriteEvent('B', category_group, name_, id_,
                 arg_names_, arg_types_, arg_values_, convertable_values_,
                 flags_);
      break;

    case TRACE_EVENT_PHASE_COMPLETE:
      WriteEvent(duration_.ToInternalValue() == -1 ? 'B' : 'E',
                 category_group, name_, id_,
                 arg_names_, arg_types_, arg_values_, convertable_values_,
                 flags_);
      break;

    case TRACE_EVENT_PHASE_END:
      // Though a single 'E' is enough, here append pid, name and
      // category_group etc. So that unpaired events can be found easily.
      WriteEvent('E', category_group, name_, id_,
                 arg_names_, arg_types_, arg_values_, convertable_values_,
                 flags_);
      break;

    case TRACE_EVENT_PHASE_INSTANT:
      // Simulate an instance event with a pair of begin/end events.
      WriteEvent('B', category_group, name_, id_,
                 arg_names_, arg_types_, arg_values_, convertable_values_,
                 flags_);
      WriteToATrace(g_atrace_fd, "E", 1);
      break;

    case TRACE_EVENT_PHASE_COUNTER:
      for (int i = 0; i < kTraceMaxNumArgs && arg_names_[i]; ++i) {
        DCHECK(arg_types_[i] == TRACE_VALUE_TYPE_INT);
        std::string out = base::StringPrintf(
            "C|%d|%s-%s", getpid(), name_, arg_names_[i]);
        if (flags_ & TRACE_EVENT_FLAG_HAS_ID)
          StringAppendF(&out, "-%" PRIx64, static_cast<uint64_t>(id_));
        StringAppendF(&out, "|%d|%s",
                      static_cast<int>(arg_values_[i].as_int), category_group);
        WriteToATrace(g_atrace_fd, out.c_str(), out.size());
      }
      break;

    default:
      // Do nothing.
      break;
  }
}

void TraceLog::AddClockSyncMetadataEvent() {
  int atrace_fd = HANDLE_EINTR(open(kATraceMarkerFile, O_WRONLY | O_APPEND));
  if (atrace_fd == -1) {
    PLOG(WARNING) << "Couldn't open " << kATraceMarkerFile;
    return;
  }

  // Android's kernel trace system has a trace_marker feature: this is a file on
  // debugfs that takes the written data and pushes it onto the trace
  // buffer. So, to establish clock sync, we write our monotonic clock into that
  // trace buffer.
  double now_in_seconds = (TRACE_TIME_TICKS_NOW() - TimeTicks()).InSecondsF();
  std::string marker = StringPrintf(
      "trace_event_clock_sync: parent_ts=%f\n", now_in_seconds);
  WriteToATrace(atrace_fd, marker.c_str(), marker.size());
  close(atrace_fd);
}

}  // namespace trace_event
}  // namespace base
