// Copyright 2015 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/memory_dump_manager.h"

#include <inttypes.h>
#include <stdio.h>

#include <algorithm>
#include <memory>
#include <utility>

#include "base/base_switches.h"
#include "base/command_line.h"
#include "base/debug/alias.h"
#include "base/debug/stack_trace.h"
#include "base/debug/thread_heap_usage_tracker.h"
#include "base/memory/ptr_util.h"
#include "base/sequenced_task_runner.h"
#include "base/strings/string_util.h"
#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
#include "base/threading/thread.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/heap_profiler.h"
#include "base/trace_event/heap_profiler_allocation_context_tracker.h"
#include "base/trace_event/heap_profiler_event_filter.h"
#include "base/trace_event/heap_profiler_serialization_state.h"
#include "base/trace_event/heap_profiler_stack_frame_deduplicator.h"
#include "base/trace_event/heap_profiler_type_name_deduplicator.h"
#include "base/trace_event/malloc_dump_provider.h"
#include "base/trace_event/memory_dump_provider.h"
#include "base/trace_event/memory_dump_scheduler.h"
#include "base/trace_event/memory_infra_background_whitelist.h"
#include "base/trace_event/memory_peak_detector.h"
#include "base/trace_event/process_memory_dump.h"
#include "base/trace_event/trace_event.h"
#include "base/trace_event/trace_event_argument.h"
#include "build_config.h"

#if defined(OS_ANDROID)
#include "base/trace_event/java_heap_dump_provider_android.h"

#endif  // defined(OS_ANDROID)

namespace base {
namespace trace_event {

namespace {

const char* const kTraceEventArgNames[] = {"dumps"};
const unsigned char kTraceEventArgTypes[] = {TRACE_VALUE_TYPE_CONVERTABLE};

MemoryDumpManager* g_memory_dump_manager_for_testing = nullptr;

// Temporary (until peak detector and scheduler are moved outside of here)
// trampoline function to match the |request_dump_function| passed to Initialize
// to the callback expected by MemoryPeakDetector and MemoryDumpScheduler.
// TODO(primiano): remove this.
void DoGlobalDumpWithoutCallback(
    MemoryDumpManager::RequestGlobalDumpFunction global_dump_fn,
    MemoryDumpType dump_type,
    MemoryDumpLevelOfDetail level_of_detail) {
  global_dump_fn.Run(dump_type, level_of_detail);
}

// Proxy class which wraps a ConvertableToTraceFormat owned by the
// |heap_profiler_serialization_state| into a proxy object that can be added to
// the trace event log. This is to solve the problem that the
// HeapProfilerSerializationState is refcounted but the tracing subsystem wants
// a std::unique_ptr<ConvertableToTraceFormat>.
template <typename T>
struct SessionStateConvertableProxy : public ConvertableToTraceFormat {
  using GetterFunctPtr = T* (HeapProfilerSerializationState::*)() const;

  SessionStateConvertableProxy(scoped_refptr<HeapProfilerSerializationState>
                                   heap_profiler_serialization_state,
                               GetterFunctPtr getter_function)
      : heap_profiler_serialization_state(heap_profiler_serialization_state),
        getter_function(getter_function) {}

  void AppendAsTraceFormat(std::string* out) const override {
    return (heap_profiler_serialization_state.get()->*getter_function)()
        ->AppendAsTraceFormat(out);
  }

  void EstimateTraceMemoryOverhead(
      TraceEventMemoryOverhead* overhead) override {
    return (heap_profiler_serialization_state.get()->*getter_function)()
        ->EstimateTraceMemoryOverhead(overhead);
  }

  scoped_refptr<HeapProfilerSerializationState>
      heap_profiler_serialization_state;
  GetterFunctPtr const getter_function;
};

void NotifyHeapProfilingEnabledOnMDPThread(
    scoped_refptr<MemoryDumpProviderInfo> mdpinfo,
    bool profiling_enabled) {
  mdpinfo->dump_provider->OnHeapProfilingEnabled(profiling_enabled);
}

inline bool ShouldEnableMDPAllocatorHooks(HeapProfilingMode mode) {
  return (mode == kHeapProfilingModePseudo) ||
         (mode == kHeapProfilingModeNative) ||
         (mode == kHeapProfilingModeBackground);
}

}  // namespace

// static
const char* const MemoryDumpManager::kTraceCategory =
    TRACE_DISABLED_BY_DEFAULT("memory-infra");

// static
const int MemoryDumpManager::kMaxConsecutiveFailuresCount = 3;

// static
const uint64_t MemoryDumpManager::kInvalidTracingProcessId = 0;

// static
const char* const MemoryDumpManager::kSystemAllocatorPoolName =
#if defined(MALLOC_MEMORY_TRACING_SUPPORTED)
    MallocDumpProvider::kAllocatedObjects;
#else
    nullptr;
#endif

// static
MemoryDumpManager* MemoryDumpManager::GetInstance() {
  if (g_memory_dump_manager_for_testing)
    return g_memory_dump_manager_for_testing;

  return Singleton<MemoryDumpManager,
                   LeakySingletonTraits<MemoryDumpManager>>::get();
}

// static
std::unique_ptr<MemoryDumpManager>
MemoryDumpManager::CreateInstanceForTesting() {
  DCHECK(!g_memory_dump_manager_for_testing);
  std::unique_ptr<MemoryDumpManager> instance(new MemoryDumpManager());
  g_memory_dump_manager_for_testing = instance.get();
  return instance;
}

MemoryDumpManager::MemoryDumpManager()
    : is_coordinator_(false),
      tracing_process_id_(kInvalidTracingProcessId),
      dumper_registrations_ignored_for_testing_(false),
      heap_profiling_mode_(kHeapProfilingModeDisabled) {}

MemoryDumpManager::~MemoryDumpManager() {
  Thread* dump_thread = nullptr;
  {
    AutoLock lock(lock_);
    if (dump_thread_) {
      dump_thread = dump_thread_.get();
    }
  }
  if (dump_thread) {
    dump_thread->Stop();
  }
  AutoLock lock(lock_);
  dump_thread_.reset();
  g_memory_dump_manager_for_testing = nullptr;
}

bool MemoryDumpManager::EnableHeapProfiling(HeapProfilingMode profiling_mode) {
  AutoLock lock(lock_);
  heap_profiling_mode_ = kHeapProfilingModeInvalid;
  return false;
}

HeapProfilingMode MemoryDumpManager::GetHeapProfilingMode() {
  AutoLock lock(lock_);
  return heap_profiling_mode_;
}

void MemoryDumpManager::Initialize(
    RequestGlobalDumpFunction request_dump_function,
    bool is_coordinator) {
  {
    AutoLock lock(lock_);
    DCHECK(!request_dump_function.is_null());
    DCHECK(!can_request_global_dumps());
    request_dump_function_ = request_dump_function;
    is_coordinator_ = is_coordinator;
  }

// Enable the core dump providers.
#if defined(MALLOC_MEMORY_TRACING_SUPPORTED)
  base::trace_event::MemoryDumpProvider::Options options;
  options.supports_heap_profiling = true;
  RegisterDumpProvider(MallocDumpProvider::GetInstance(), "Malloc", nullptr,
                       options);
#endif

#if defined(OS_ANDROID)
  RegisterDumpProvider(JavaHeapDumpProvider::GetInstance(), "JavaHeap",
                       nullptr);
#endif

  TRACE_EVENT_WARMUP_CATEGORY(kTraceCategory);
}

void MemoryDumpManager::RegisterDumpProvider(
    MemoryDumpProvider* mdp,
    const char* name,
    scoped_refptr<SingleThreadTaskRunner> task_runner,
    MemoryDumpProvider::Options options) {
  options.dumps_on_single_thread_task_runner = true;
  RegisterDumpProviderInternal(mdp, name, std::move(task_runner), options);
}

void MemoryDumpManager::RegisterDumpProvider(
    MemoryDumpProvider* mdp,
    const char* name,
    scoped_refptr<SingleThreadTaskRunner> task_runner) {
  // Set |dumps_on_single_thread_task_runner| to true because all providers
  // without task runner are run on dump thread.
  MemoryDumpProvider::Options options;
  options.dumps_on_single_thread_task_runner = true;
  RegisterDumpProviderInternal(mdp, name, std::move(task_runner), options);
}

void MemoryDumpManager::RegisterDumpProviderWithSequencedTaskRunner(
    MemoryDumpProvider* mdp,
    const char* name,
    scoped_refptr<SequencedTaskRunner> task_runner,
    MemoryDumpProvider::Options options) {
  DCHECK(task_runner);
  options.dumps_on_single_thread_task_runner = false;
  RegisterDumpProviderInternal(mdp, name, std::move(task_runner), options);
}

void MemoryDumpManager::RegisterDumpProviderInternal(
    MemoryDumpProvider* mdp,
    const char* name,
    scoped_refptr<SequencedTaskRunner> task_runner,
    const MemoryDumpProvider::Options& options) {
  if (dumper_registrations_ignored_for_testing_)
    return;

  // Only a handful of MDPs are required to compute the memory metrics. These
  // have small enough performance overhead that it is resonable to run them
  // in the background while the user is doing other things. Those MDPs are
  // 'whitelisted for background mode'.
  bool whitelisted_for_background_mode = IsMemoryDumpProviderWhitelisted(name);

  scoped_refptr<MemoryDumpProviderInfo> mdpinfo =
      new MemoryDumpProviderInfo(mdp, name, std::move(task_runner), options,
                                 whitelisted_for_background_mode);

  if (options.is_fast_polling_supported) {
    DCHECK(!mdpinfo->task_runner) << "MemoryDumpProviders capable of fast "
                                     "polling must NOT be thread bound.";
  }

  {
    AutoLock lock(lock_);
    bool already_registered = !dump_providers_.insert(mdpinfo).second;
    // This actually happens in some tests which don't have a clean tear-down
    // path for RenderThreadImpl::Init().
    if (already_registered)
      return;

    if (options.is_fast_polling_supported)
      MemoryPeakDetector::GetInstance()->NotifyMemoryDumpProvidersChanged();

    if (ShouldEnableMDPAllocatorHooks(heap_profiling_mode_))
      NotifyHeapProfilingEnabledLocked(mdpinfo, true);
  }
}

void MemoryDumpManager::UnregisterDumpProvider(MemoryDumpProvider* mdp) {
  UnregisterDumpProviderInternal(mdp, false /* delete_async */);
}

void MemoryDumpManager::UnregisterAndDeleteDumpProviderSoon(
    std::unique_ptr<MemoryDumpProvider> mdp) {
  UnregisterDumpProviderInternal(mdp.release(), true /* delete_async */);
}

void MemoryDumpManager::UnregisterDumpProviderInternal(
    MemoryDumpProvider* mdp,
    bool take_mdp_ownership_and_delete_async) {
  std::unique_ptr<MemoryDumpProvider> owned_mdp;
  if (take_mdp_ownership_and_delete_async)
    owned_mdp.reset(mdp);

  AutoLock lock(lock_);

  auto mdp_iter = dump_providers_.begin();
  for (; mdp_iter != dump_providers_.end(); ++mdp_iter) {
    if ((*mdp_iter)->dump_provider == mdp)
      break;
  }

  if (mdp_iter == dump_providers_.end())
    return;  // Not registered / already unregistered.

  if (take_mdp_ownership_and_delete_async) {
    // The MDP will be deleted whenever the MDPInfo struct will, that is either:
    // - At the end of this function, if no dump is in progress.
    // - In ContinueAsyncProcessDump() when MDPInfo is removed from
    //   |pending_dump_providers|.
    // - When the provider is removed from other clients (MemoryPeakDetector).
    DCHECK(!(*mdp_iter)->owned_dump_provider);
    (*mdp_iter)->owned_dump_provider = std::move(owned_mdp);
  } else {
    // If you hit this DCHECK, your dump provider has a bug.
    // Unregistration of a MemoryDumpProvider is safe only if:
    // - The MDP has specified a sequenced task runner affinity AND the
    //   unregistration happens on the same task runner. So that the MDP cannot
    //   unregister and be in the middle of a OnMemoryDump() at the same time.
    // - The MDP has NOT specified a task runner affinity and its ownership is
    //   transferred via UnregisterAndDeleteDumpProviderSoon().
    // In all the other cases, it is not possible to guarantee that the
    // unregistration will not race with OnMemoryDump() calls.
    DCHECK((*mdp_iter)->task_runner &&
           (*mdp_iter)->task_runner->RunsTasksInCurrentSequence())
        << "MemoryDumpProvider \"" << (*mdp_iter)->name << "\" attempted to "
        << "unregister itself in a racy way. Please file a crbug.";
  }

  if ((*mdp_iter)->options.is_fast_polling_supported) {
    DCHECK(take_mdp_ownership_and_delete_async);
    MemoryPeakDetector::GetInstance()->NotifyMemoryDumpProvidersChanged();
  }

  // The MDPInfo instance can still be referenced by the
  // |ProcessMemoryDumpAsyncState.pending_dump_providers|. For this reason
  // the MDPInfo is flagged as disabled. It will cause InvokeOnMemoryDump()
  // to just skip it, without actually invoking the |mdp|, which might be
  // destroyed by the caller soon after this method returns.
  (*mdp_iter)->disabled = true;
  dump_providers_.erase(mdp_iter);
}

void MemoryDumpManager::GetDumpProvidersForPolling(
    std::vector<scoped_refptr<MemoryDumpProviderInfo>>* providers) {
  DCHECK(providers->empty());
  AutoLock lock(lock_);
  for (const scoped_refptr<MemoryDumpProviderInfo>& mdp : dump_providers_) {
    if (mdp->options.is_fast_polling_supported)
      providers->push_back(mdp);
  }
}

bool MemoryDumpManager::IsDumpProviderRegisteredForTesting(
    MemoryDumpProvider* provider) {
  AutoLock lock(lock_);

  for (const auto& info : dump_providers_) {
    if (info->dump_provider == provider)
      return true;
  }
  return false;
}

scoped_refptr<base::SequencedTaskRunner>
MemoryDumpManager::GetOrCreateBgTaskRunnerLocked() {
  lock_.AssertAcquired();

  if (dump_thread_)
    return dump_thread_->task_runner();

  dump_thread_ = std::make_unique<Thread>("MemoryInfra");
  bool started = dump_thread_->Start();
  CHECK(started);

  return dump_thread_->task_runner();
}

void MemoryDumpManager::CreateProcessDump(
    const MemoryDumpRequestArgs& args,
    const ProcessMemoryDumpCallback& callback) {
  char guid_str[20];
  sprintf(guid_str, "0x%" PRIx64, args.dump_guid);
  TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(kTraceCategory, "ProcessMemoryDump",
                                    TRACE_ID_LOCAL(args.dump_guid), "dump_guid",
                                    TRACE_STR_COPY(guid_str));

  // If argument filter is enabled then only background mode dumps should be
  // allowed. In case the trace config passed for background tracing session
  // missed the allowed modes argument, it crashes here instead of creating
  // unexpected dumps.
  if (TraceLog::GetInstance()
          ->GetCurrentTraceConfig()
          .IsArgumentFilterEnabled()) {
    CHECK_EQ(MemoryDumpLevelOfDetail::BACKGROUND, args.level_of_detail);
  }

  std::unique_ptr<ProcessMemoryDumpAsyncState> pmd_async_state;
  {
    AutoLock lock(lock_);

    // MDM could have been disabled by this point destroying
    // |heap_profiler_serialization_state|. If heap profiling is enabled we
    // require session state so if heap profiling is on and session state is
    // absent we fail the dump immediately. If heap profiler is enabled during
    // the dump, then the dump succeeds since the dump was requested before, and
    // the future process dumps will contain heap dumps.
    if (args.dump_type != MemoryDumpType::SUMMARY_ONLY &&
        ShouldEnableMDPAllocatorHooks(heap_profiling_mode_) &&
        !heap_profiler_serialization_state_) {
      callback.Run(false /* success */, args.dump_guid, nullptr);
      return;
    }

    pmd_async_state.reset(new ProcessMemoryDumpAsyncState(
        args, dump_providers_, heap_profiler_serialization_state_, callback,
        GetOrCreateBgTaskRunnerLocked()));

    // If enabled, holds back the peak detector resetting its estimation window.
    MemoryPeakDetector::GetInstance()->Throttle();
  }

  // Start the process dump. This involves task runner hops as specified by the
  // MemoryDumpProvider(s) in RegisterDumpProvider()).
  ContinueAsyncProcessDump(pmd_async_state.release());
}

// Invokes OnMemoryDump() on all MDPs that are next in the pending list and run
// on the current sequenced task runner. If the next MDP does not run in current
// sequenced task runner, then switches to that task runner and continues. All
// OnMemoryDump() invocations are linearized. |lock_| is used in these functions
// purely to ensure consistency w.r.t. (un)registrations of |dump_providers_|.
void MemoryDumpManager::ContinueAsyncProcessDump(
    ProcessMemoryDumpAsyncState* owned_pmd_async_state) {
  HEAP_PROFILER_SCOPED_IGNORE;
  // Initalizes the ThreadLocalEventBuffer to guarantee that the TRACE_EVENTs
  // in the PostTask below don't end up registering their own dump providers
  // (for discounting trace memory overhead) while holding the |lock_|.
  TraceLog::GetInstance()->InitializeThreadLocalEventBufferIfSupported();

  // In theory |owned_pmd_async_state| should be a unique_ptr. The only reason
  // why it isn't is because of the corner case logic of |did_post_task|
  // above, which needs to take back the ownership of the |pmd_async_state| when
  // the PostTask() fails.
  // Unfortunately, PostTask() destroys the unique_ptr arguments upon failure
  // to prevent accidental leaks. Using a unique_ptr would prevent us to to
  // skip the hop and move on. Hence the manual naked -> unique ptr juggling.
  auto pmd_async_state = WrapUnique(owned_pmd_async_state);
  owned_pmd_async_state = nullptr;

  while (!pmd_async_state->pending_dump_providers.empty()) {
    // Read MemoryDumpProviderInfo thread safety considerations in
    // memory_dump_manager.h when accessing |mdpinfo| fields.
    MemoryDumpProviderInfo* mdpinfo =
        pmd_async_state->pending_dump_providers.back().get();

    // If we are in background mode, we should invoke only the whitelisted
    // providers. Ignore other providers and continue.
    if (pmd_async_state->req_args.level_of_detail ==
            MemoryDumpLevelOfDetail::BACKGROUND &&
        !mdpinfo->whitelisted_for_background_mode) {
      pmd_async_state->pending_dump_providers.pop_back();
      continue;
    }

    // If the dump provider did not specify a task runner affinity, dump on
    // |dump_thread_|.
    scoped_refptr<SequencedTaskRunner> task_runner = mdpinfo->task_runner;
    if (!task_runner) {
      DCHECK(mdpinfo->options.dumps_on_single_thread_task_runner);
      task_runner = pmd_async_state->dump_thread_task_runner;
      DCHECK(task_runner);
    }

    // If |RunsTasksInCurrentSequence()| is true then no PostTask is
    // required since we are on the right SequencedTaskRunner.
    if (task_runner->RunsTasksInCurrentSequence()) {
      InvokeOnMemoryDump(mdpinfo, pmd_async_state->process_memory_dump.get());
      pmd_async_state->pending_dump_providers.pop_back();
      continue;
    }

    bool did_post_task = task_runner->PostTask(
        FROM_HERE,
        BindOnce(&MemoryDumpManager::ContinueAsyncProcessDump, Unretained(this),
                 Unretained(pmd_async_state.get())));

    if (did_post_task) {
      // Ownership is tranferred to the posted task.
      ignore_result(pmd_async_state.release());
      return;
    }

    // PostTask usually fails only if the process or thread is shut down. So,
    // the dump provider is disabled here. But, don't disable unbound dump
    // providers, since the |dump_thread_| is controlled by MDM.
    if (mdpinfo->task_runner) {
      // A locked access is required to R/W |disabled| (for the
      // UnregisterAndDeleteDumpProviderSoon() case).
      AutoLock lock(lock_);
      mdpinfo->disabled = true;
    }

    // PostTask failed. Ignore the dump provider and continue.
    pmd_async_state->pending_dump_providers.pop_back();
  }

  FinishAsyncProcessDump(std::move(pmd_async_state));
}

// This function is called on the right task runner for current MDP. It is
// either the task runner specified by MDP or |dump_thread_task_runner| if the
// MDP did not specify task runner. Invokes the dump provider's OnMemoryDump()
// (unless disabled).
void MemoryDumpManager::InvokeOnMemoryDump(MemoryDumpProviderInfo* mdpinfo,
                                           ProcessMemoryDump* pmd) {
  HEAP_PROFILER_SCOPED_IGNORE;
  DCHECK(!mdpinfo->task_runner ||
         mdpinfo->task_runner->RunsTasksInCurrentSequence());

  TRACE_EVENT1(kTraceCategory, "MemoryDumpManager::InvokeOnMemoryDump",
               "dump_provider.name", mdpinfo->name);

  // Do not add any other TRACE_EVENT macro (or function that might have them)
  // below this point. Under some rare circunstances, they can re-initialize
  // and invalide the current ThreadLocalEventBuffer MDP, making the
  // |should_dump| check below susceptible to TOCTTOU bugs
  // (https://crbug.com/763365).

  bool is_thread_bound;
  {
    // A locked access is required to R/W |disabled| (for the
    // UnregisterAndDeleteDumpProviderSoon() case).
    AutoLock lock(lock_);

    // Unregister the dump provider if it failed too many times consecutively.
    if (!mdpinfo->disabled &&
        mdpinfo->consecutive_failures >= kMaxConsecutiveFailuresCount) {
      mdpinfo->disabled = true;
      DLOG(ERROR) << "Disabling MemoryDumpProvider \"" << mdpinfo->name
                  << "\". Dump failed multiple times consecutively.";
    }
    if (mdpinfo->disabled)
      return;

    is_thread_bound = mdpinfo->task_runner != nullptr;
  }  // AutoLock lock(lock_);

  // Invoke the dump provider.

  // A stack allocated string with dump provider name is useful to debug
  // crashes while invoking dump after a |dump_provider| is not unregistered
  // in safe way.
  char provider_name_for_debugging[16];
  strncpy(provider_name_for_debugging, mdpinfo->name,
          sizeof(provider_name_for_debugging) - 1);
  provider_name_for_debugging[sizeof(provider_name_for_debugging) - 1] = '\0';
  base::debug::Alias(provider_name_for_debugging);

  ANNOTATE_BENIGN_RACE(&mdpinfo->disabled, "best-effort race detection");
  CHECK(!is_thread_bound ||
        !*(static_cast<volatile bool*>(&mdpinfo->disabled)));
  bool dump_successful =
      mdpinfo->dump_provider->OnMemoryDump(pmd->dump_args(), pmd);
  mdpinfo->consecutive_failures =
      dump_successful ? 0 : mdpinfo->consecutive_failures + 1;
}

void MemoryDumpManager::FinishAsyncProcessDump(
    std::unique_ptr<ProcessMemoryDumpAsyncState> pmd_async_state) {
  HEAP_PROFILER_SCOPED_IGNORE;
  DCHECK(pmd_async_state->pending_dump_providers.empty());
  const uint64_t dump_guid = pmd_async_state->req_args.dump_guid;
  if (!pmd_async_state->callback_task_runner->BelongsToCurrentThread()) {
    scoped_refptr<SingleThreadTaskRunner> callback_task_runner =
        pmd_async_state->callback_task_runner;
    callback_task_runner->PostTask(
        FROM_HERE, BindOnce(&MemoryDumpManager::FinishAsyncProcessDump,
                            Unretained(this), std::move(pmd_async_state)));
    return;
  }

  TRACE_EVENT0(kTraceCategory, "MemoryDumpManager::FinishAsyncProcessDump");

  // In the general case (allocators and edges) the serialization into the trace
  // buffer is handled by the memory-infra service (see tracing_observer.cc).
  // This special case below deals only with serialization of the heap profiler
  // and is temporary given the upcoming work on the out-of-process heap
  // profiler.
  const auto& args = pmd_async_state->req_args;
  if (!pmd_async_state->process_memory_dump->heap_dumps().empty()) {
    std::unique_ptr<TracedValue> traced_value = std::make_unique<TracedValue>();
    pmd_async_state->process_memory_dump->SerializeHeapProfilerDumpsInto(
        traced_value.get());

    traced_value->SetString("level_of_detail",
                            base::trace_event::MemoryDumpLevelOfDetailToString(
                                args.level_of_detail));
    std::unique_ptr<base::trace_event::ConvertableToTraceFormat> event_value(
        std::move(traced_value));
    TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_PROCESS_ID(
        TRACE_EVENT_PHASE_MEMORY_DUMP,
        base::trace_event::TraceLog::GetCategoryGroupEnabled(
            base::trace_event::MemoryDumpManager::kTraceCategory),
        base::trace_event::MemoryDumpTypeToString(args.dump_type),
        trace_event_internal::kGlobalScope, args.dump_guid,
        base::kNullProcessId, 1 /* num_args */, kTraceEventArgNames,
        kTraceEventArgTypes, nullptr /* arg_values */, &event_value,
        TRACE_EVENT_FLAG_HAS_ID);
  }

  if (!pmd_async_state->callback.is_null()) {
    pmd_async_state->callback.Run(
        true /* success */, dump_guid,
        std::move(pmd_async_state->process_memory_dump));
    pmd_async_state->callback.Reset();
  }

  TRACE_EVENT_NESTABLE_ASYNC_END0(kTraceCategory, "ProcessMemoryDump",
                                  TRACE_ID_LOCAL(dump_guid));
}

void MemoryDumpManager::SetupForTracing(
    const TraceConfig::MemoryDumpConfig& memory_dump_config) {
  AutoLock lock(lock_);
  heap_profiler_serialization_state_ = new HeapProfilerSerializationState();
  heap_profiler_serialization_state_
      ->set_heap_profiler_breakdown_threshold_bytes(
          memory_dump_config.heap_profiler_options.breakdown_threshold_bytes);
  InitializeHeapProfilerStateIfNeededLocked();

  // At this point we must have the ability to request global dumps.
  DCHECK(can_request_global_dumps());

  MemoryDumpScheduler::Config periodic_config;
  bool peak_detector_configured = false;
  for (const auto& trigger : memory_dump_config.triggers) {
    if (trigger.trigger_type == MemoryDumpType::PERIODIC_INTERVAL) {
      if (periodic_config.triggers.empty()) {
        periodic_config.callback =
            BindRepeating(&DoGlobalDumpWithoutCallback, request_dump_function_,
                          MemoryDumpType::PERIODIC_INTERVAL);
      }
      periodic_config.triggers.push_back(
          {trigger.level_of_detail, trigger.min_time_between_dumps_ms});
    } else if (trigger.trigger_type == MemoryDumpType::PEAK_MEMORY_USAGE) {
      // At most one peak trigger is allowed.
      CHECK(!peak_detector_configured);
      peak_detector_configured = true;
      MemoryPeakDetector::GetInstance()->Setup(
          BindRepeating(&MemoryDumpManager::GetDumpProvidersForPolling,
                        Unretained(this)),
          GetOrCreateBgTaskRunnerLocked(),
          BindRepeating(&DoGlobalDumpWithoutCallback, request_dump_function_,
                        MemoryDumpType::PEAK_MEMORY_USAGE,
                        trigger.level_of_detail));

      MemoryPeakDetector::Config peak_config;
      peak_config.polling_interval_ms = 10;
      peak_config.min_time_between_peaks_ms = trigger.min_time_between_dumps_ms;
      peak_config.enable_verbose_poll_tracing =
          trigger.level_of_detail == MemoryDumpLevelOfDetail::DETAILED;
      MemoryPeakDetector::GetInstance()->Start(peak_config);

      // When peak detection is enabled, trigger a dump straight away as it
      // gives a good reference point for analyzing the trace.
      if (is_coordinator_) {
        GetOrCreateBgTaskRunnerLocked()->PostTask(
            FROM_HERE,
            BindOnce(&DoGlobalDumpWithoutCallback, request_dump_function_,
                     MemoryDumpType::PEAK_MEMORY_USAGE,
                     trigger.level_of_detail));
      }
    }
  }

  // Only coordinator process triggers periodic memory dumps.
  if (is_coordinator_ && !periodic_config.triggers.empty()) {
    MemoryDumpScheduler::GetInstance()->Start(periodic_config,
                                              GetOrCreateBgTaskRunnerLocked());
  }
}

void MemoryDumpManager::TeardownForTracing() {
  // There might be a memory dump in progress while this happens. Therefore,
  // ensure that the MDM state which depends on the tracing enabled / disabled
  // state is always accessed by the dumping methods holding the |lock_|.
  AutoLock lock(lock_);

  MemoryDumpScheduler::GetInstance()->Stop();
  MemoryPeakDetector::GetInstance()->TearDown();
  heap_profiler_serialization_state_ = nullptr;
}

void MemoryDumpManager::InitializeHeapProfilerStateIfNeededLocked() {
  lock_.AssertAcquired();
  if (!ShouldEnableMDPAllocatorHooks(heap_profiling_mode_) ||
      !heap_profiler_serialization_state_ ||
      heap_profiler_serialization_state_->is_initialized()) {
    return;
  }
  // If heap profiling is enabled, the stack frame deduplicator and type name
  // deduplicator will be in use. Add a metadata events to write the frames
  // and type IDs.
  heap_profiler_serialization_state_->SetStackFrameDeduplicator(
      WrapUnique(new StackFrameDeduplicator));
  heap_profiler_serialization_state_->SetTypeNameDeduplicator(
      WrapUnique(new TypeNameDeduplicator));

  TRACE_EVENT_API_ADD_METADATA_EVENT(
      TraceLog::GetCategoryGroupEnabled("__metadata"), "stackFrames",
      "stackFrames",
      std::make_unique<SessionStateConvertableProxy<StackFrameDeduplicator>>(
          heap_profiler_serialization_state_,
          &HeapProfilerSerializationState::stack_frame_deduplicator));

  TRACE_EVENT_API_ADD_METADATA_EVENT(
      TraceLog::GetCategoryGroupEnabled("__metadata"), "typeNames", "typeNames",
      std::make_unique<SessionStateConvertableProxy<TypeNameDeduplicator>>(
          heap_profiler_serialization_state_,
          &HeapProfilerSerializationState::type_name_deduplicator));
}

void MemoryDumpManager::NotifyHeapProfilingEnabledLocked(
    scoped_refptr<MemoryDumpProviderInfo> mdpinfo,
    bool enabled) {
  lock_.AssertAcquired();
  if (!mdpinfo->options.supports_heap_profiling)
    return;

  const auto& task_runner = mdpinfo->task_runner
                                ? mdpinfo->task_runner
                                : GetOrCreateBgTaskRunnerLocked();
  // TODO(ssid): Post tasks only for MDPs that support heap profiling.
  task_runner->PostTask(
      FROM_HERE,
      BindOnce(&NotifyHeapProfilingEnabledOnMDPThread, mdpinfo, enabled));
}

MemoryDumpManager::ProcessMemoryDumpAsyncState::ProcessMemoryDumpAsyncState(
    MemoryDumpRequestArgs req_args,
    const MemoryDumpProviderInfo::OrderedSet& dump_providers,
    scoped_refptr<HeapProfilerSerializationState>
        heap_profiler_serialization_state_in,
    ProcessMemoryDumpCallback callback,
    scoped_refptr<SequencedTaskRunner> dump_thread_task_runner)
    : req_args(req_args),
      heap_profiler_serialization_state(
          std::move(heap_profiler_serialization_state_in)),
      callback(callback),
      callback_task_runner(ThreadTaskRunnerHandle::Get()),
      dump_thread_task_runner(std::move(dump_thread_task_runner)) {
  pending_dump_providers.reserve(dump_providers.size());
  pending_dump_providers.assign(dump_providers.rbegin(), dump_providers.rend());
  MemoryDumpArgs args = {req_args.level_of_detail, req_args.dump_guid};
  process_memory_dump = std::make_unique<ProcessMemoryDump>(
      heap_profiler_serialization_state, args);
}

MemoryDumpManager::ProcessMemoryDumpAsyncState::~ProcessMemoryDumpAsyncState() =
    default;

}  // namespace trace_event
}  // namespace base
