Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/third_party/perfetto/sdk/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 6 MB image not shown  

Bilddatei perfetto.h

  Sprache: C
 

// Copyright (C) 2019 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.
//
// This file is automatically generated by gen_amalgamated. Do not edit.

// gen_amalgamated begin header: include/perfetto/tracing.h
// gen_amalgamated begin header: include/perfetto/base/time.h
// gen_amalgamated begin header: include/perfetto/base/build_config.h
// gen_amalgamated begin header: gen/build_config/perfetto_build_flags.h
/*
 * Copyright (C) 2019 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.
 */


// Generated by write_buildflag_header.py

// fix_include_guards: off
#ifndef GEN_BUILD_CONFIG_PERFETTO_BUILD_FLAGS_H_
#define GEN_BUILD_CONFIG_PERFETTO_BUILD_FLAGS_H_

// clang-format off
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_ANDROID_BUILD() (0)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_CHROMIUM_BUILD() (0)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_STANDALONE_BUILD() (0)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_START_DAEMONS() (1)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_IPC() (1)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_WATCHDOG() (0)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_COMPONENT_BUILD() (0)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_ENABLE_ETM_IMPORTER() (0)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_FORCE_DLOG_ON() (0)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_FORCE_DLOG_OFF() (0)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_FORCE_DCHECK_ON() (0)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_FORCE_DCHECK_OFF() (0)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_VERBOSE_LOGS() (1)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_VERSION_GEN() (1)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_PERCENTILE() (0)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_LINENOISE() (0)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_HTTPD() (0)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_JSON() (1)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_INSTRUMENTS() (1)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_LOCAL_SYMBOLIZER() (0)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_ZLIB() (0)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TRACED_PERF() (0)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_HEAPPROFD() (0)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_STDERR_CRASH_DUMP() (0)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_X64_CPU_OPT() (0)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_LLVM_DEMANGLE() (0)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_SYSTEM_CONSUMER() (1)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_THREAD_SAFETY_ANNOTATIONS() (0)

// clang-format on
#endif  // GEN_BUILD_CONFIG_PERFETTO_BUILD_FLAGS_H_
/*
 * 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.
 */


#ifndef INCLUDE_PERFETTO_BASE_BUILD_CONFIG_H_
#define INCLUDE_PERFETTO_BASE_BUILD_CONFIG_H_

// Allows to define build flags that give a compiler error if the header that
// defined the flag is not included, instead of silently ignoring the #if block.
#define PERFETTO_BUILDFLAG_CAT_INDIRECT(a, b) a##b
#define PERFETTO_BUILDFLAG_CAT(a, b) PERFETTO_BUILDFLAG_CAT_INDIRECT(a, b)
#define PERFETTO_BUILDFLAG(flag) \
  (PERFETTO_BUILDFLAG_CAT(PERFETTO_BUILDFLAG_DEFINE_, flag)())

#if defined(__ANDROID__)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_ANDROID() 1
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX_BUT_NOT_QNX() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WIN() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_APPLE() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_MAC() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_IOS() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WASM() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_FUCHSIA() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_NACL() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_QNX() 0
#elif defined(__APPLE__)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_ANDROID() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_APPLE() 1
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX_BUT_NOT_QNX() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WIN() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WASM() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_FUCHSIA() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_NACL() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_QNX() 0
// Include TARGET_OS_IPHONE when on __APPLE__ systems.
#include <TargetConditionals.h>
#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_MAC() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_IOS() 1
#else
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_MAC() 1
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_IOS() 0
#endif
#elif defined(__linux__)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_ANDROID() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX() 1
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX_BUT_NOT_QNX() 1
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WIN() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_APPLE() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_MAC() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_IOS() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WASM() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_FUCHSIA() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_NACL() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_QNX() 0
#elif defined(__QNXNTO__)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_ANDROID() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX() 1
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX_BUT_NOT_QNX() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WIN() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_APPLE() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_MAC() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_IOS() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WASM() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_FUCHSIA() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_NACL() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_QNX() 1
#elif defined(_WIN32)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_ANDROID() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX_BUT_NOT_QNX() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WIN() 1
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_APPLE() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_MAC() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_IOS() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WASM() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_FUCHSIA() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_NACL() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_QNX() 0
#elif defined(__EMSCRIPTEN__)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_ANDROID() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX_BUT_NOT_QNX() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WIN() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_APPLE() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_MAC() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_IOS() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WASM() 1
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_FUCHSIA() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_NACL() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_QNX() 0
#elif defined(__Fuchsia__)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_ANDROID() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_APPLE() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_MAC() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_IOS() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX_BUT_NOT_QNX() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WIN() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WASM() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_FUCHSIA() 1
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_NACL() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_QNX() 0
#elif defined(__native_client__)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_ANDROID() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX_BUT_NOT_QNX() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WIN() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_APPLE() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_MAC() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_IOS() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WASM() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_FUCHSIA() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_NACL() 1
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_QNX() 0
#else
#error OS not supported (see build_config.h)
#endif

#if defined(__clang__)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_COMPILER_CLANG() 1
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_COMPILER_GCC() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_COMPILER_MSVC() 0
#elif defined(__GNUC__)  // Careful: Clang also defines this!
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_COMPILER_CLANG() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_COMPILER_GCC() 1
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_COMPILER_MSVC() 0
#elif defined(_MSC_VER)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_COMPILER_CLANG() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_COMPILER_GCC() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_COMPILER_MSVC() 1
#else
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_COMPILER_CLANG() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_COMPILER_GCC() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_COMPILER_MSVC() 0
#endif

#if defined(PERFETTO_BUILD_WITH_ANDROID_USERDEBUG)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_ANDROID_USERDEBUG_BUILD() 1
#else
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_ANDROID_USERDEBUG_BUILD() 0
#endif

// Processor architecture detection.  For more info on what's defined, see:
//   http://msdn.microsoft.com/en-us/library/b0084kay.aspx
//   http://www.agner.org/optimize/calling_conventions.pdf
//   or with gcc, run: "echo | gcc -E -dM -"
#if defined(__aarch64__) || defined(_M_ARM64)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_ARCH_CPU_ARM64() 1
#else
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_ARCH_CPU_ARM64() 0
#endif

#if defined(__x86_64__) || defined(_M_X64)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_ARCH_CPU_X86_64() 1
#else
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_ARCH_CPU_X86_64() 0
#endif

// TODO(primiano): add a preprocessor macro to detect RISC-V on MSVC.
#if defined(__riscv)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_ARCH_CPU_RISCV() 1
#else
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_ARCH_CPU_RISCV() 0
#endif

// perfetto_build_flags.h contains the tweakable build flags defined via GN.
// - In GN builds (e.g., standalone, chromium, v8) this file is generated at
//   build time via the gen_rule //gn/gen_buildflags.
// - In Android in-tree builds, this file is generated by tools/gen_android_bp
//   and checked in into include/perfetto/base/build_configs/android_tree/. The
//   default cflags add this path to the default include path.
// - Similarly, in bazel builds, this file is generated by tools/gen_bazel and
//   checked in into include/perfetto/base/build_configs/bazel/.
// - In amalgamated builds, this file is generated by tools/gen_amalgamated and
//   added to the amalgamated headers.
// gen_amalgamated expanded: #include "perfetto_build_flags.h"  // no-include-violation-check

#endif  // INCLUDE_PERFETTO_BASE_BUILD_CONFIG_H_
// gen_amalgamated begin header: include/perfetto/base/logging.h
// gen_amalgamated begin header: include/perfetto/base/compiler.h
// gen_amalgamated begin header: include/perfetto/public/compiler.h
/*
 * Copyright (C) 2022 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.
 */


#ifndef INCLUDE_PERFETTO_PUBLIC_COMPILER_H_
#define INCLUDE_PERFETTO_PUBLIC_COMPILER_H_

#include <stddef.h>

#if defined(__GNUC__) || defined(__clang__)
#define PERFETTO_LIKELY(_x) __builtin_expect(!!(_x), 1)
#define PERFETTO_UNLIKELY(_x) __builtin_expect(!!(_x), 0)
#else
#define PERFETTO_LIKELY(_x) (_x)
#define PERFETTO_UNLIKELY(_x) (_x)
#endif

// PERFETTO_STATIC_CAST(TYPE, VAL): avoids the -Wold-style-cast warning when
// writing code that needs to be compiled as C and C++.
#ifdef __cplusplus
#define PERFETTO_STATIC_CAST(TYPE, VAL) static_cast<TYPE>(VAL)
#else
#define PERFETTO_STATIC_CAST(TYPE, VAL) ((TYPE)(VAL))
#endif

// PERFETTO_REINTERPRET_CAST(TYPE, VAL): avoids the -Wold-style-cast warning
// when writing code that needs to be compiled as C and C++.
#ifdef __cplusplus
#define PERFETTO_REINTERPRET_CAST(TYPE, VAL) reinterpret_cast<TYPE>(VAL)
#else
#define PERFETTO_REINTERPRET_CAST(TYPE, VAL) ((TYPE)(VAL))
#endif

// PERFETTO_NULL: avoids the -Wzero-as-null-pointer-constant warning when
// writing code that needs to be compiled as C and C++.
#ifdef __cplusplus
#define PERFETTO_NULL nullptr
#else
#define PERFETTO_NULL NULL
#endif

#if defined(__clang__)
#define PERFETTO_ALWAYS_INLINE __attribute__((__always_inline__))
#define PERFETTO_NO_INLINE __attribute__((__noinline__))
#else
// GCC is too pedantic and often fails with the error:
// "always_inline function might not be inlinable"
#define PERFETTO_ALWAYS_INLINE
#define PERFETTO_NO_INLINE
#endif

#endif  // INCLUDE_PERFETTO_PUBLIC_COMPILER_H_
/*
 * Copyright (C) 2019 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.
 */


#ifndef INCLUDE_PERFETTO_BASE_COMPILER_H_
#define INCLUDE_PERFETTO_BASE_COMPILER_H_

#include <cstddef>
#include <type_traits>
#include <variant>

// gen_amalgamated expanded: #include "perfetto/public/compiler.h"

// __has_attribute is supported only by clang and recent versions of GCC.
// Add a layer to wrap the __has_attribute macro.
#if defined(__has_attribute)
#define PERFETTO_HAS_ATTRIBUTE(x) __has_attribute(x)
#else
#define PERFETTO_HAS_ATTRIBUTE(x) 0
#endif

#if defined(__GNUC__) || defined(__clang__)
#define PERFETTO_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
#else
#define PERFETTO_WARN_UNUSED_RESULT
#endif

#if defined(__GNUC__) || defined(__clang__)
#define PERFETTO_UNUSED __attribute__((unused))
#else
#define PERFETTO_UNUSED
#endif

#if defined(__GNUC__) || defined(__clang__)
#define PERFETTO_NORETURN __attribute__((__noreturn__))
#else
#define PERFETTO_NORETURN __declspec(noreturn)
#endif

#if defined(__GNUC__) || defined(__clang__)
#define PERFETTO_DEBUG_FUNCTION_IDENTIFIER() __PRETTY_FUNCTION__
#elif defined(_MSC_VER)
#define PERFETTO_DEBUG_FUNCTION_IDENTIFIER() __FUNCSIG__
#else
#define PERFETTO_DEBUG_FUNCTION_IDENTIFIER() \
  static_assert(false"Not implemented for this compiler")
#endif

#if defined(__GNUC__) || defined(__clang__)
#define PERFETTO_PRINTF_FORMAT(x, y) \
  __attribute__((__format__(__printf__, x, y)))
#else
#define PERFETTO_PRINTF_FORMAT(x, y)
#endif

#if defined(__GNUC__) || defined(__clang__)
#define PERFETTO_POPCOUNT(x) __builtin_popcountll(x)
#else
#include <intrin.h>
#define PERFETTO_POPCOUNT(x) __popcnt64(x)
#endif

#if defined(__clang__)
#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
#include "mozilla/MemoryChecking.h"
#define PERFETTO_ASAN_POISON(a, s) __asan_poison_memory_region((a), (s))
#define PERFETTO_ASAN_UNPOISON(a, s) __asan_unpoison_memory_region((a), (s))
#else
#define PERFETTO_ASAN_POISON(addr, size)
#define PERFETTO_ASAN_UNPOISON(addr, size)
#endif  // __has_feature(address_sanitizer)
#else
#define PERFETTO_ASAN_POISON(addr, size)
#define PERFETTO_ASAN_UNPOISON(addr, size)
#endif  // __clang__

#if defined(__GNUC__) || defined(__clang__)
#define PERFETTO_IS_LITTLE_ENDIAN() __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#else
// Assume all MSVC targets are little endian.
#define PERFETTO_IS_LITTLE_ENDIAN() 1
#endif

// This is used for exporting xxxMain() symbols (e.g., PerfettoCmdMain,
// ProbesMain) from libperfetto.so when the GN arg monolithic_binaries = false.
#if defined(__GNUC__) || defined(__clang__)
#define PERFETTO_EXPORT_ENTRYPOINT __attribute__((visibility("default")))
#else
// TODO(primiano): on Windows this should be a pair of dllexport/dllimport. But
// that requires a -DXXX_IMPLEMENTATION depending on whether we are on the
// impl-site or call-site. Right now it's not worth the trouble as we
// force-export the xxxMain() symbols only on Android, where we pack all the
// code for N binaries into one .so to save binary size. On Windows we support
// only monolithic binaries, as they are easier to deal with.
#define PERFETTO_EXPORT_ENTRYPOINT
#endif

// Disables undefined behavior analysis for a function.
#if defined(__clang__)
#define PERFETTO_NO_SANITIZE_UNDEFINED __attribute__((no_sanitize("undefined")))
#else
#define PERFETTO_NO_SANITIZE_UNDEFINED
#endif

// Avoid calling the exit-time destructor on an object with static lifetime.
#if PERFETTO_HAS_ATTRIBUTE(no_destroy)
#define PERFETTO_HAS_NO_DESTROY() 1
#define PERFETTO_NO_DESTROY __attribute__((no_destroy))
#else
#define PERFETTO_HAS_NO_DESTROY() 0
#define PERFETTO_NO_DESTROY
#endif

// Macro for telling -Wimplicit-fallthrough that a fallthrough is intentional.
#define PERFETTO_FALLTHROUGH [[fallthrough]]

// Depending on the version of the compiler, __has_builtin can be provided or
// not.
#if defined(__has_builtin)
#if __has_builtin(__builtin_stack_address)
#define PERFETTO_HAS_BUILTIN_STACK_ADDRESS() 1
#else
#define PERFETTO_HAS_BUILTIN_STACK_ADDRESS() 0
#endif
#else
#define PERFETTO_HAS_BUILTIN_STACK_ADDRESS() 0
#endif

namespace perfetto::base {

template <typename... T>
inline void ignore_result(const T&...) {}

// Given a std::variant and a type T, returns the index of the T in the variant.
template <typename VariantType, typename T, size_t i = 0>
constexpr size_t variant_index() {
  static_assert(i < std::variant_size_v<VariantType>,
                "Type not found in variant");
  if constexpr (std::is_same_v<std::variant_alternative_t<i, VariantType>, T>) {
    return i;
  } else {
    return variant_index<VariantType, T, i + 1>();
  }
}

}  // namespace perfetto::base

#endif  // INCLUDE_PERFETTO_BASE_COMPILER_H_
// gen_amalgamated begin header: include/perfetto/base/export.h
// gen_amalgamated begin header: include/perfetto/public/abi/export.h
/*
 * Copyright (C) 2022 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.
 */


#ifndef INCLUDE_PERFETTO_PUBLIC_ABI_EXPORT_H_
#define INCLUDE_PERFETTO_PUBLIC_ABI_EXPORT_H_

#ifdef _WIN32
#define PERFETTO_INTERNAL_DLL_EXPORT __declspec(dllexport)
#define PERFETTO_INTERNAL_DLL_IMPORT __declspec(dllimport)
#else
#define PERFETTO_INTERNAL_DLL_EXPORT __attribute__((visibility("default")))
#define PERFETTO_INTERNAL_DLL_IMPORT
#endif

// PERFETTO_SDK_EXPORT: Exports a symbol from the perfetto SDK shared library.
//
// This is controlled by two defines (that likely come from the compiler command
// line):
// * PERFETTO_SDK_DISABLE_SHLIB_EXPORT: If this is defined, no export
//   annotations are added. This might be useful when static linking.
// * PERFETTO_SDK_SHLIB_IMPLEMENTATION: This must be defined when compiling the
//   shared library itself (in order to export the symbols), but must be
//   undefined when compiling objects that use the shared library (in order to
//   import the symbols).
#if !defined(PERFETTO_SDK_DISABLE_SHLIB_EXPORT)
#if defined(PERFETTO_SHLIB_SDK_IMPLEMENTATION)
#define PERFETTO_SDK_EXPORT PERFETTO_INTERNAL_DLL_EXPORT
#else
#define PERFETTO_SDK_EXPORT PERFETTO_INTERNAL_DLL_IMPORT
#endif
#else  // defined(PERFETTO_SDK_DISABLE_SHLIB_EXPORT)
#define PERFETTO_SDK_EXPORT
#endif  // defined(PERFETTO_SDK_DISABLE_SHLIB_EXPORT)

#endif  // INCLUDE_PERFETTO_PUBLIC_ABI_EXPORT_H_
/*
 * 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.
 */


#ifndef INCLUDE_PERFETTO_BASE_EXPORT_H_
#define INCLUDE_PERFETTO_BASE_EXPORT_H_

// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
// gen_amalgamated expanded: #include "perfetto/public/abi/export.h"

// PERFETTO_EXPORT_COMPONENT: Exports a symbol among C++ components when
// building with is_component = true (mostly used by chromium build).
#if PERFETTO_BUILDFLAG(PERFETTO_COMPONENT_BUILD)

#if defined(PERFETTO_IMPLEMENTATION)
#define PERFETTO_EXPORT_COMPONENT PERFETTO_INTERNAL_DLL_EXPORT
#else
#define PERFETTO_EXPORT_COMPONENT PERFETTO_INTERNAL_DLL_IMPORT
#endif

#else  // !PERFETTO_BUILDFLAG(PERFETTO_COMPONENT_BUILD)

#if !defined(PERFETTO_EXPORT_COMPONENT)
#define PERFETTO_EXPORT_COMPONENT
#endif  // !defined(PERFETTO_EXPORT_COMPONENT)

#endif  // PERFETTO_BUILDFLAG(PERFETTO_COMPONENT_BUILD)

#endif  // INCLUDE_PERFETTO_BASE_EXPORT_H_
/*
 * 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.
 */


#ifndef INCLUDE_PERFETTO_BASE_LOGGING_H_
#define INCLUDE_PERFETTO_BASE_LOGGING_H_

#include <errno.h>
#include <string.h>  // For strerror.

// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
// gen_amalgamated expanded: #include "perfetto/base/compiler.h"
// gen_amalgamated expanded: #include "perfetto/base/export.h"

#if defined(__GNUC__) || defined(__clang__)
// Ignore GCC warning about a missing argument for a variadic macro parameter.
#pragma GCC system_header
#endif

#if PERFETTO_BUILDFLAG(PERFETTO_FORCE_DCHECK_ON)
#define PERFETTO_DCHECK_IS_ON() 1
#elif PERFETTO_BUILDFLAG(PERFETTO_FORCE_DCHECK_OFF)
#define PERFETTO_DCHECK_IS_ON() 0
#elif defined(DCHECK_ALWAYS_ON) ||                                         \
    (!defined(NDEBUG) && (PERFETTO_BUILDFLAG(PERFETTO_STANDALONE_BUILD) || \
                          PERFETTO_BUILDFLAG(PERFETTO_CHROMIUM_BUILD) ||   \
                          PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)))
#define PERFETTO_DCHECK_IS_ON() 1
#else
#define PERFETTO_DCHECK_IS_ON() 0
#endif

#if PERFETTO_BUILDFLAG(PERFETTO_FORCE_DLOG_ON)
#define PERFETTO_DLOG_IS_ON() 1
#elif PERFETTO_BUILDFLAG(PERFETTO_FORCE_DLOG_OFF)
#define PERFETTO_DLOG_IS_ON() 0
#else
#define PERFETTO_DLOG_IS_ON() PERFETTO_DCHECK_IS_ON()
#endif

#if defined(PERFETTO_ANDROID_ASYNC_SAFE_LOG)
#if !PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
    !PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
#error "Async-safe logging is limited to Android tree builds"
#endif
// For binaries which need a very lightweight logging implementation.
// Note that this header is incompatible with android/log.h.
#include <async_safe/log.h>
#elif PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
// Normal android logging.
#include <android/log.h>
#endif

// Enable the "Print the most recent PERFETTO_LOG(s) before crashing" feature
// on Android in-tree builds and on standalone builds (mainly for testing).
// This is deliberately no PERFETTO_OS_ANDROID because we don't want this
// feature when perfetto is embedded in other Android projects (e.g. SDK).
// TODO(b/203795298): TFLite is using the client library in blaze builds and is
// targeting API 19. For now disable the feature based on API level.
#if defined(PERFETTO_ANDROID_ASYNC_SAFE_LOG)
#define PERFETTO_ENABLE_LOG_RING_BUFFER() 0
#elif PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
#define PERFETTO_ENABLE_LOG_RING_BUFFER() 1
#elif PERFETTO_BUILDFLAG(PERFETTO_STANDALONE_BUILD) && \
    (!PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) ||       \
     (defined(__ANDROID_API__) && __ANDROID_API__ >= 21))
#define PERFETTO_ENABLE_LOG_RING_BUFFER() 1
#else
#define PERFETTO_ENABLE_LOG_RING_BUFFER() 0
#endif

namespace perfetto {
namespace base {

// Constexpr functions to extract basename(__FILE__), e.g.: ../foo/f.c -> f.c .
constexpr const char* StrEnd(const char* s) {
  return *s ? StrEnd(s + 1) : s;
}

constexpr const char* BasenameRecursive(const char* s,
                                        const char* begin,
                                        const char* end) {
  return (*s == '/' && s < end)
             ? (s + 1)
             : ((s > begin) ? BasenameRecursive(s - 1, begin, end) : s);
}

constexpr const char* Basename(const char* str) {
  return BasenameRecursive(StrEnd(str), str, StrEnd(str));
}

enum LogLev { kLogDebug = 0, kLogInfo, kLogImportant, kLogError };

struct LogMessageCallbackArgs {
  LogLev level;
  int line;
  const char* filename;
  const char* message;
};

using LogMessageCallback = void (*)(LogMessageCallbackArgs);

// This is not thread safe and must be called before using tracing from other
// threads.
PERFETTO_EXPORT_COMPONENT void SetLogMessageCallback(
    LogMessageCallback callback);

PERFETTO_EXPORT_COMPONENT void LogMessage(LogLev,
                                          const char* fname,
                                          int line,
                                          const char* fmt,
                                          ...) PERFETTO_PRINTF_FORMAT(4, 5);

// This is defined in debug_crash_stack_trace.cc, but that is only linked in
// standalone && debug builds, see enable_perfetto_stderr_crash_dump in
// perfetto.gni.
PERFETTO_EXPORT_COMPONENT void EnableStacktraceOnCrashForDebug();

#if PERFETTO_ENABLE_LOG_RING_BUFFER()
// Gets a snapshot of the logs from the internal log ring buffer and:
// - On Android in-tree builds: Passes that to android_set_abort_message().
//   That will attach the logs to the crash report.
// - On standalone builds (all otther OSes) prints that on stderr.
// This function must called only once, right before inducing a crash (This is
// because android_set_abort_message() can only be called once).
PERFETTO_EXPORT_COMPONENT void MaybeSerializeLastLogsForCrashReporting();
#else
inline void MaybeSerializeLastLogsForCrashReporting() {}
#endif

#if defined(PERFETTO_ANDROID_ASYNC_SAFE_LOG)
#define PERFETTO_XLOG(level, fmt, ...)                                        \
  do {                                                                        \
    async_safe_format_log((ANDROID_LOG_DEBUG + level), "perfetto",            \
                          "%s:%d " fmt, ::perfetto::base::Basename(__FILE__), \
                          __LINE__, ##__VA_ARGS__);                           \
  } while (0)
#elif defined(PERFETTO_DISABLE_LOG)
#define PERFETTO_XLOG(level, fmt, ...) \
  ::perfetto::base::ignore_result(level, fmt, ##__VA_ARGS__)
#else
#define PERFETTO_XLOG(level, fmt, ...)                                      \
  ::perfetto::base::LogMessage(level, ::perfetto::base::Basename(__FILE__), \
                               __LINE__, fmt, ##__VA_ARGS__)
#endif

#if defined(_MSC_VER)
#define PERFETTO_IMMEDIATE_CRASH()                               \
  do {                                                           \
    ::perfetto::base::MaybeSerializeLastLogsForCrashReporting(); \
    __debugbreak();                                              \
    __assume(0);                                                 \
  } while (0)
#else
#define PERFETTO_IMMEDIATE_CRASH()                               \
  do {                                                           \
    ::perfetto::base::MaybeSerializeLastLogsForCrashReporting(); \
    __builtin_trap();                                            \
    __builtin_unreachable();                                     \
  } while (0)
#endif

#if PERFETTO_BUILDFLAG(PERFETTO_VERBOSE_LOGS)
#define PERFETTO_LOG(fmt, ...) \
  PERFETTO_XLOG(::perfetto::base::kLogInfo, fmt, ##__VA_ARGS__)
#else  // PERFETTO_BUILDFLAG(PERFETTO_VERBOSE_LOGS)
#define PERFETTO_LOG(...) ::perfetto::base::ignore_result(__VA_ARGS__)
#endif  // PERFETTO_BUILDFLAG(PERFETTO_VERBOSE_LOGS)

#define PERFETTO_ILOG(fmt, ...) \
  PERFETTO_XLOG(::perfetto::base::kLogImportant, fmt, ##__VA_ARGS__)
#define PERFETTO_ELOG(fmt, ...) \
  PERFETTO_XLOG(::perfetto::base::kLogError, fmt, ##__VA_ARGS__)
#define PERFETTO_FATAL(fmt, ...)       \
  do {                                 \
    PERFETTO_PLOG(fmt, ##__VA_ARGS__); \
    PERFETTO_IMMEDIATE_CRASH();        \
  } while (0)

#if defined(__GNUC__) || defined(__clang__)
#define PERFETTO_PLOG(x, ...) \
  PERFETTO_ELOG(x " (errno: %d, %s)"##__VA_ARGS__, errno, strerror(errno))
#else
// MSVC expands __VA_ARGS__ in a different order. Give up, not worth it.
#define PERFETTO_PLOG PERFETTO_ELOG
#endif

#define PERFETTO_CHECK(x)                            \
  do {                                               \
    if (PERFETTO_UNLIKELY(!(x))) {                   \
      PERFETTO_PLOG("%s""PERFETTO_CHECK(" #x ")"); \
      PERFETTO_IMMEDIATE_CRASH();                    \
    }                                                \
  } while (0)

#if PERFETTO_DLOG_IS_ON()

#define PERFETTO_DLOG(fmt, ...) \
  PERFETTO_XLOG(::perfetto::base::kLogDebug, fmt, ##__VA_ARGS__)

#if defined(__GNUC__) || defined(__clang__)
#define PERFETTO_DPLOG(x, ...) \
  PERFETTO_DLOG(x " (errno: %d, %s)"##__VA_ARGS__, errno, strerror(errno))
#else
// MSVC expands __VA_ARGS__ in a different order. Give up, not worth it.
#define PERFETTO_DPLOG PERFETTO_DLOG
#endif

#else  // PERFETTO_DLOG_IS_ON()

#define PERFETTO_DLOG(...) ::perfetto::base::ignore_result(__VA_ARGS__)
#define PERFETTO_DPLOG(...) ::perfetto::base::ignore_result(__VA_ARGS__)

#endif  // PERFETTO_DLOG_IS_ON()

#if PERFETTO_DCHECK_IS_ON()

#define PERFETTO_DCHECK(x) PERFETTO_CHECK(x)
#define PERFETTO_DFATAL(...) PERFETTO_FATAL(__VA_ARGS__)
#define PERFETTO_DFATAL_OR_ELOG(...) PERFETTO_DFATAL(__VA_ARGS__)

#else  // PERFETTO_DCHECK_IS_ON()

#define PERFETTO_DCHECK(x) \
  do {                     \
  } while (false && (x))

#define PERFETTO_DFATAL(...) ::perfetto::base::ignore_result(__VA_ARGS__)
#define PERFETTO_DFATAL_OR_ELOG(...) PERFETTO_ELOG(__VA_ARGS__)

#endif  // PERFETTO_DCHECK_IS_ON()

}  // namespace base
}  // namespace perfetto

#endif  // INCLUDE_PERFETTO_BASE_LOGGING_H_
/*
 * 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.
 */


#ifndef INCLUDE_PERFETTO_BASE_TIME_H_
#define INCLUDE_PERFETTO_BASE_TIME_H_

#include <stdint.h>
#include <time.h>

#include <chrono>
#include <optional>
#include <string>

// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
// gen_amalgamated expanded: #include "perfetto/base/logging.h"

#if PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
#include <mach/mach_init.h>
#include <mach/mach_port.h>
#include <mach/mach_time.h>
#include <mach/thread_act.h>
#endif

#if PERFETTO_BUILDFLAG(PERFETTO_OS_WASM)
#include <emscripten/emscripten.h>
#endif

#if PERFETTO_BUILDFLAG(PERFETTO_ARCH_CPU_X86_64)
#if PERFETTO_BUILDFLAG(PERFETTO_COMPILER_MSVC)
#include <intrin.h>
#endif
#endif

namespace perfetto {
namespace base {

using TimeSeconds = std::chrono::seconds;
using TimeMillis = std::chrono::milliseconds;
using TimeNanos = std::chrono::nanoseconds;

inline TimeNanos FromPosixTimespec(const struct timespec& ts) {
  return TimeNanos(ts.tv_sec * 1000000000LL + ts.tv_nsec);
}

void SleepMicroseconds(unsigned interval_us);
void InitializeTime();

#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)

TimeNanos GetWallTimeNs();
TimeNanos GetThreadCPUTimeNs();
inline TimeNanos GetWallTimeRawNs() {
  return GetWallTimeNs();
}

// TODO: Clock that counts time during suspend is not implemented on Windows.
inline TimeNanos GetBootTimeNs() {
  return GetWallTimeNs();
}

#elif PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)

inline TimeNanos GetWallTimeNs() {
  auto init_timebase_info = []() -> mach_timebase_info_data_t {
    mach_timebase_info_data_t timebase_info;
    mach_timebase_info(&timebase_info);
    return timebase_info;
  };

  static mach_timebase_info_data_t timebase_info = init_timebase_info();
  uint64_t mach_time = mach_absolute_time();

  // Take the fast path when the conversion is 1:1. The result will for sure fit
  // into an int_64 because we're going from nanoseconds to microseconds.
  if (timebase_info.numer == timebase_info.denom) {
    return TimeNanos(mach_time);
  }

  // Nanoseconds is mach_time * timebase.numer // timebase.denom. Divide first
  // to reduce the chance of overflow. Also stash the remainder right now,
  // a likely byproduct of the division.
  uint64_t nanoseconds = mach_time / timebase_info.denom;
  const uint64_t mach_time_remainder = mach_time % timebase_info.denom;

  // Now multiply, keeping an eye out for overflow.
  PERFETTO_CHECK(!__builtin_umulll_overflow(nanoseconds, timebase_info.numer,
                                            &nanoseconds));

  // By dividing first we lose precision. Regain it by adding back the
  // nanoseconds from the remainder, with an eye out for overflow.
  uint64_t least_significant_nanoseconds =
      (mach_time_remainder * timebase_info.numer) / timebase_info.denom;
  PERFETTO_CHECK(!__builtin_uaddll_overflow(
      nanoseconds, least_significant_nanoseconds, &nanoseconds));

  return TimeNanos(nanoseconds);
}

inline TimeNanos GetWallTimeRawNs() {
  return GetWallTimeNs();
}

// TODO: Clock that counts time during suspend is not implemented on Mac.
inline TimeNanos GetBootTimeNs() {
  return GetWallTimeNs();
}

// Before MacOS 10.12 clock_gettime() was not implemented.
#if __MAC_OS_X_VERSION_MIN_REQUIRED < 101200
inline TimeNanos GetThreadCPUTimeNs() {
  mach_port_t this_thread = mach_thread_self();
  mach_msg_type_number_t count = THREAD_BASIC_INFO_COUNT;
  thread_basic_info_data_t info{};
  kern_return_t kr =
      thread_info(this_thread, THREAD_BASIC_INFO,
                  reinterpret_cast<thread_info_t>(&info), &count);
  mach_port_deallocate(mach_task_self(), this_thread);

  if (kr != KERN_SUCCESS) {
    PERFETTO_DFATAL("Failed to get CPU time.");
    return TimeNanos(0);
  }
  return TimeNanos(info.user_time.seconds * 1000000000LL +
                   info.user_time.microseconds * 1000LL +
                   info.system_time.seconds * 1000000000LL +
                   info.system_time.microseconds * 1000LL);
}
#else
inline TimeNanos GetThreadCPUTimeNs() {
  struct timespec ts = {};
  PERFETTO_CHECK(clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts) == 0);
  return FromPosixTimespec(ts);
}
#endif

#elif PERFETTO_BUILDFLAG(PERFETTO_OS_WASM)

inline TimeNanos GetWallTimeNs() {
  return TimeNanos(static_cast<uint64_t>(emscripten_get_now()) * 1000000);
}

inline TimeNanos GetWallTimeRawNs() {
  return GetWallTimeNs();
}

inline TimeNanos GetThreadCPUTimeNs() {
  return TimeNanos(0);
}

// TODO: Clock that counts time during suspend is not implemented on WASM.
inline TimeNanos GetBootTimeNs() {
  return GetWallTimeNs();
}

#elif PERFETTO_BUILDFLAG(PERFETTO_OS_NACL)

// Tracing time doesn't need to work on NaCl since its going away shortly. We
// just need to compile on it. The only function NaCl could support is
// GetWallTimeNs(), but to prevent false hope we leave it unimplemented.

inline TimeNanos GetWallTimeNs() {
  return TimeNanos(0);
}

inline TimeNanos GetWallTimeRawNs() {
  return TimeNanos(0);
}

inline TimeNanos GetThreadCPUTimeNs() {
  return TimeNanos(0);
}

inline TimeNanos GetBootTimeNs() {
  return TimeNanos(0);
}

#elif PERFETTO_BUILDFLAG(PERFETTO_OS_QNX)

constexpr clockid_t kWallTimeClockSource = CLOCK_MONOTONIC;

inline TimeNanos GetTimeInternalNs(clockid_t clk_id) {
  struct timespec ts = {};
  PERFETTO_CHECK(clock_gettime(clk_id, &ts) == 0);
  return FromPosixTimespec(ts);
}

inline TimeNanos GetWallTimeNs() {
  return GetTimeInternalNs(kWallTimeClockSource);
}

inline TimeNanos GetWallTimeRawNs() {
  return GetTimeInternalNs(CLOCK_MONOTONIC);
}

inline TimeNanos GetThreadCPUTimeNs() {
  return GetTimeInternalNs(CLOCK_THREAD_CPUTIME_ID);
}

// TODO: Clock that counts time during suspend is not implemented on QNX.
inline TimeNanos GetBootTimeNs() {
  return GetWallTimeNs();
}

#else  // posix

constexpr clockid_t kWallTimeClockSource = CLOCK_MONOTONIC;

inline TimeNanos GetTimeInternalNs(clockid_t clk_id) {
  struct timespec ts = {};
  PERFETTO_CHECK(clock_gettime(clk_id, &ts) == 0);
  return FromPosixTimespec(ts);
}

// Return ns from boot. Conversely to GetWallTimeNs, this clock counts also time
// during suspend (when supported).
inline TimeNanos GetBootTimeNs() {
  // Determine if CLOCK_BOOTTIME is available on the first call.
  static const clockid_t kBootTimeClockSource = [] {
    struct timespec ts = {};
    int res = clock_gettime(CLOCK_BOOTTIME, &ts);
    return res == 0 ? CLOCK_BOOTTIME : kWallTimeClockSource;
  }();
  return GetTimeInternalNs(kBootTimeClockSource);
}

inline TimeNanos GetWallTimeNs() {
  return GetTimeInternalNs(kWallTimeClockSource);
}

inline TimeNanos GetWallTimeRawNs() {
  return GetTimeInternalNs(CLOCK_MONOTONIC_RAW);
}

inline TimeNanos GetThreadCPUTimeNs() {
  return GetTimeInternalNs(CLOCK_THREAD_CPUTIME_ID);
}
#endif

inline TimeSeconds GetBootTimeS() {
  return std::chrono::duration_cast<TimeSeconds>(GetBootTimeNs());
}

inline TimeMillis GetBootTimeMs() {
  return std::chrono::duration_cast<TimeMillis>(GetBootTimeNs());
}

inline TimeMillis GetWallTimeMs() {
  return std::chrono::duration_cast<TimeMillis>(GetWallTimeNs());
}

inline TimeSeconds GetWallTimeS() {
  return std::chrono::duration_cast<TimeSeconds>(GetWallTimeNs());
}

inline struct timespec ToPosixTimespec(TimeMillis time) {
  struct timespec ts {};
  const long time_s = static_cast<long>(time.count() / 1000);
  ts.tv_sec = time_s;
  ts.tv_nsec = (static_cast<long>(time.count()) - time_s * 1000L) * 1000000L;
  return ts;
}

std::string GetTimeFmt(const std::string& fmt);

inline int64_t TimeGm(struct tm* tms) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  return static_cast<int64_t>(_mkgmtime(tms));
#elif PERFETTO_BUILDFLAG(PERFETTO_OS_NACL)
  // NaCL has no timegm.
  if (tms)  // Kinda if (true), but avoids "mark as noreturn" errors.
    PERFETTO_FATAL("timegm not supported");
  return -1;
#else
  return static_cast<int64_t>(timegm(tms));
#endif
}

// Creates a time_t-compatible timestamp (seconds since epoch) from a tuple of
// y-m-d-h-m-s. It's a saner version of timegm(). Some remarks:
// The year is just the actual year (it's Y-1900 in timegm()).
// The month ranges 1-12 (it's 0-11 in timegm()).
inline int64_t MkTime(int year, int month, int day, int h, int m, int s) {
  PERFETTO_DCHECK(year >= 1900);
  PERFETTO_DCHECK(month > 0 && month <= 12);
  PERFETTO_DCHECK(day > 0 && day <= 31);
  struct tm tms {};
  tms.tm_year = year - 1900;
  tms.tm_mon = month - 1;
  tms.tm_mday = day;
  tms.tm_hour = h;
  tms.tm_min = m;
  tms.tm_sec = s;
  return TimeGm(&tms);
}

#if PERFETTO_BUILDFLAG(PERFETTO_ARCH_CPU_X86_64)
inline uint64_t Rdtsc() {
#if PERFETTO_BUILDFLAG(PERFETTO_COMPILER_MSVC)
  return static_cast<uint64_t>(__rdtsc());
#else
  // Use inline asm for clang and gcc: rust ffi bindgen crashes in using
  // intrinsics on ChromeOS.
  uint64_t low, high;
  __asm__ volatile("rdtsc" : "=a"(low), "=d"(high));
  return (high << 32) | low;
#endif
}
#endif

std::optional<int32_t> GetTimezoneOffsetMins();

}  // namespace base
}  // namespace perfetto

#endif  // INCLUDE_PERFETTO_BASE_TIME_H_
// gen_amalgamated begin header: include/perfetto/tracing/buffer_exhausted_policy.h
/*
 * Copyright (C) 2019 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.
 */


#ifndef INCLUDE_PERFETTO_TRACING_BUFFER_EXHAUSTED_POLICY_H_
#define INCLUDE_PERFETTO_TRACING_BUFFER_EXHAUSTED_POLICY_H_

namespace perfetto {

// Determines how SharedMemoryArbiterImpl::GetNewChunk() behaves when no free
// chunks are available.
enum class BufferExhaustedPolicy {
  // SharedMemoryArbiterImpl::GetNewChunk() will stall if no free SMB chunk is
  // available and wait for the tracing service to free one. Note that this
  // requires that messages the arbiter sends to the tracing service (from any
  // TraceWriter thread) will be received by it, even if all TraceWriter threads
  // are stalled.
  kStall,

  // SharedMemoryArbiterImpl::GetNewChunk() will return an invalid chunk if no
  // free SMB chunk is available. In this case, the TraceWriter will fall back
  // to a garbage chunk and drop written data until acquiring a future chunk
  // succeeds again.
  kDrop,

  // TODO(eseckler): Switch to kDrop by default and change the Android code to
  // explicitly request kStall instead.
  kDefault = kStall
};

}  // namespace perfetto

#endif  // INCLUDE_PERFETTO_TRACING_BUFFER_EXHAUSTED_POLICY_H_
// gen_amalgamated begin header: include/perfetto/tracing/console_interceptor.h
// gen_amalgamated begin header: include/perfetto/tracing/interceptor.h
// gen_amalgamated begin header: include/perfetto/protozero/field.h
// gen_amalgamated begin header: include/perfetto/protozero/contiguous_memory_range.h
/*
 * 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.
 */


#ifndef INCLUDE_PERFETTO_PROTOZERO_CONTIGUOUS_MEMORY_RANGE_H_
#define INCLUDE_PERFETTO_PROTOZERO_CONTIGUOUS_MEMORY_RANGE_H_

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

namespace protozero {

// Keep this struct trivially constructible (no ctors, no default initializers).
struct ContiguousMemoryRange {
  uint8_t* begin;
  uint8_t* end;  // STL style: one byte past the end of the buffer.

  inline bool is_valid() const { return begin != nullptr; }
  inline void reset() { begin = nullptr; }
  inline size_t size() const { return static_cast<size_t>(end - begin); }
};

}  // namespace protozero

#endif  // INCLUDE_PERFETTO_PROTOZERO_CONTIGUOUS_MEMORY_RANGE_H_
// gen_amalgamated begin header: include/perfetto/protozero/proto_utils.h
// gen_amalgamated begin header: include/perfetto/public/pb_utils.h
/*
 * Copyright (C) 2022 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.
 */


#ifndef INCLUDE_PERFETTO_PUBLIC_PB_UTILS_H_
#define INCLUDE_PERFETTO_PUBLIC_PB_UTILS_H_

#include <assert.h>
#include <stdint.h>
#include <string.h>

// gen_amalgamated expanded: #include "perfetto/public/compiler.h"

// Type of fields that can be found in a protobuf serialized message.
enum PerfettoPbWireType {
  PERFETTO_PB_WIRE_TYPE_VARINT = 0,
  PERFETTO_PB_WIRE_TYPE_FIXED64 = 1,
  PERFETTO_PB_WIRE_TYPE_DELIMITED = 2,
  PERFETTO_PB_WIRE_TYPE_FIXED32 = 5,
};

// Creates a field tag, which encodes the field type and the field id.
static inline uint32_t PerfettoPbMakeTag(int32_t field_id,
                                         enum PerfettoPbWireType wire_type) {
  return ((PERFETTO_STATIC_CAST(uint32_t, field_id)) << 3) |
         PERFETTO_STATIC_CAST(uint32_t, wire_type);
}

enum {
  // Maximum bytes size of a 64-bit integer encoded as a VarInt.
  PERFETTO_PB_VARINT_MAX_SIZE_64 = 10,
  // Maximum bytes size of a 32-bit integer encoded as a VarInt.
  PERFETTO_PB_VARINT_MAX_SIZE_32 = 5,
};

// Encodes `value` as a VarInt into `*dst`.
//
// `dst` must point into a buffer big enough to represent `value`:
// PERFETTO_PB_VARINT_MAX_SIZE_* can help.
static inline uint8_t* PerfettoPbWriteVarInt(uint64_t value, uint8_t* dst) {
  uint8_t byte;
  while (value >= 0x80) {
    byte = (value & 0x7f) | 0x80;
    *dst++ = byte;
    value >>= 7;
  }
  byte = value & 0x7f;
  *dst++ = byte;

  return dst;
}

// Encodes `value` as a fixed32 (little endian) into `*dst`.
//
// `dst` must point into a buffer with at least 4 bytes of space.
static inline uint8_t* PerfettoPbWriteFixed32(uint32_t value, uint8_t* buf) {
  buf[0] = PERFETTO_STATIC_CAST(uint8_t, value);
  buf[1] = PERFETTO_STATIC_CAST(uint8_t, value >> 8);
  buf[2] = PERFETTO_STATIC_CAST(uint8_t, value >> 16);
  buf[3] = PERFETTO_STATIC_CAST(uint8_t, value >> 24);
  return buf + 4;
}

// Encodes `value` as a fixed32 (little endian) into `*dst`.
//
// `dst` must point into a buffer with at least 8 bytes of space.
static inline uint8_t* PerfettoPbWriteFixed64(uint64_t value, uint8_t* buf) {
  buf[0] = PERFETTO_STATIC_CAST(uint8_t, value);
  buf[1] = PERFETTO_STATIC_CAST(uint8_t, value >> 8);
  buf[2] = PERFETTO_STATIC_CAST(uint8_t, value >> 16);
  buf[3] = PERFETTO_STATIC_CAST(uint8_t, value >> 24);
  buf[4] = PERFETTO_STATIC_CAST(uint8_t, value >> 32);
  buf[5] = PERFETTO_STATIC_CAST(uint8_t, value >> 40);
  buf[6] = PERFETTO_STATIC_CAST(uint8_t, value >> 48);
  buf[7] = PERFETTO_STATIC_CAST(uint8_t, value >> 56);
  return buf + 8;
}

// Parses a VarInt from the encoded buffer [start, end). |end| is STL-style and
// points one byte past the end of buffer.
// The parsed int value is stored in the output arg |value|. Returns a pointer
// to the next unconsumed byte (so start < retval <= end) or |start| if the
// VarInt could not be fully parsed because there was not enough space in the
// buffer.
static inline const uint8_t* PerfettoPbParseVarInt(const uint8_t* start,
                                                   const uint8_t* end,
                                                   uint64_t* out_value) {
  const uint8_t* pos = start;
  uint64_t value = 0;
  for (uint32_t shift = 0; pos < end && shift < 64u; shift += 7) {
    // Cache *pos into |cur_byte| to prevent that the compiler dereferences the
    // pointer twice (here and in the if() below) due to char* aliasing rules.
    uint8_t cur_byte = *pos++;
    value |= PERFETTO_STATIC_CAST(uint64_t, cur_byte & 0x7f) << shift;
    if ((cur_byte & 0x80) == 0) {
      // In valid cases we get here.
      *out_value = value;
      return pos;
    }
  }
  *out_value = 0;
  return start;
}

static inline uint32_t PerfettoPbZigZagEncode32(int32_t value) {
#if defined(__cplusplus) || \
    (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L)
  // Right-shift of negative values is implementation specific.
  // Assert the implementation does what we expect, which is that shifting an
  // positive int32_t by 31 gives an all 0 bitmap, and a negative int32_t gives
  // an all 1 bitmap.
  static_assert(
      PERFETTO_STATIC_CAST(uint32_t, INT32_C(-1) >> 31) == ~UINT32_C(0),
      "implementation does not support assumed rightshift");
  static_assert(PERFETTO_STATIC_CAST(uint32_t, INT32_C(1) >> 31) == UINT32_C(0),
                "implementation does not support assumed rightshift");
#endif

  return (PERFETTO_STATIC_CAST(uint32_t, value) << 1) ^
         PERFETTO_STATIC_CAST(uint32_t, value >> 31);
}

static inline uint64_t PerfettoPbZigZagEncode64(int64_t value) {
#if defined(__cplusplus) || \
    (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L)
  // Right-shift of negative values is implementation specific.
  // Assert the implementation does what we expect, which is that shifting an
  // positive int64_t by 63 gives an all 0 bitmap, and a negative int64_t gives
  // an all 1 bitmap.
  static_assert(
      PERFETTO_STATIC_CAST(uint64_t, INT64_C(-1) >> 63) == ~UINT64_C(0),
      "implementation does not support assumed rightshift");
  static_assert(PERFETTO_STATIC_CAST(uint64_t, INT64_C(1) >> 63) == UINT64_C(0),
                "implementation does not support assumed rightshift");
#endif

  return (PERFETTO_STATIC_CAST(uint64_t, value) << 1) ^
         PERFETTO_STATIC_CAST(uint64_t, value >> 63);
}

static inline int32_t PerfettoPbZigZagDecode32(uint32_t value) {
  uint32_t mask =
      PERFETTO_STATIC_CAST(uint32_t, -PERFETTO_STATIC_CAST(int32_t, value & 1));
  return PERFETTO_STATIC_CAST(int32_t, ((value >> 1) ^ mask));
}

static inline int64_t PerfettoPbZigZagDecode64(uint64_t value) {
  uint64_t mask =
      PERFETTO_STATIC_CAST(uint64_t, -PERFETTO_STATIC_CAST(int64_t, value & 1));
  return PERFETTO_STATIC_CAST(int64_t, ((value >> 1) ^ mask));
}

static inline uint64_t PerfettoPbDoubleToFixed64(double value) {
  uint64_t val;
  memcpy(&val, &value, sizeof val);
  return val;
}

static inline uint32_t PerfettoPbFloatToFixed32(float value) {
  uint32_t val;
  memcpy(&val, &value, sizeof val);
  return val;
}

#endif  // INCLUDE_PERFETTO_PUBLIC_PB_UTILS_H_
/*
 * 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.
 */


#ifndef INCLUDE_PERFETTO_PROTOZERO_PROTO_UTILS_H_
#define INCLUDE_PERFETTO_PROTOZERO_PROTO_UTILS_H_

#include <stddef.h>

#include <cinttypes>
#include <type_traits>

// gen_amalgamated expanded: #include "perfetto/base/logging.h"
// gen_amalgamated expanded: #include "perfetto/public/pb_utils.h"

// Helper macro for the constexpr functions containing
// the switch statement: if C++14 is supported, this macro
// resolves to `constexpr` and just `inline` otherwise.
#if __cpp_constexpr >= 201304
#define PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE constexpr
#else
#define PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE inline
#endif

namespace protozero {
namespace proto_utils {

// See https://developers.google.com/protocol-buffers/docs/encoding wire types.
// This is a type encoded into the proto that provides just enough info to
// find the length of the following value.
enum class ProtoWireType : uint32_t {
  kVarInt = 0,
  kFixed64 = 1,
  kLengthDelimited = 2,
  kFixed32 = 5,
};

// This is the type defined in the proto for each field. This information
// is used to decide the translation strategy when writing the trace.
enum class ProtoSchemaType {
  kUnknown = 0,
  kDouble,
  kFloat,
  kInt64,
  kUint64,
  kInt32,
  kFixed64,
  kFixed32,
  kBool,
  kString,
  kGroup,  // Deprecated (proto2 only)
  kMessage,
  kBytes,
  kUint32,
  kEnum,
  kSfixed32,
  kSfixed64,
  kSint32,
  kSint64,
};

inline const char* ProtoSchemaToString(ProtoSchemaType v) {
  switch (v) {
    case ProtoSchemaType::kUnknown:
      return "unknown";
    case ProtoSchemaType::kDouble:
      return "double";
    case ProtoSchemaType::kFloat:
      return "float";
    case ProtoSchemaType::kInt64:
      return "int64";
    case ProtoSchemaType::kUint64:
      return "uint64";
    case ProtoSchemaType::kInt32:
      return "int32";
    case ProtoSchemaType::kFixed64:
      return "fixed64";
    case ProtoSchemaType::kFixed32:
      return "fixed32";
    case ProtoSchemaType::kBool:
      return "bool";
    case ProtoSchemaType::kString:
      return "string";
    case ProtoSchemaType::kGroup:
      return "group";
    case ProtoSchemaType::kMessage:
      return "message";
    case ProtoSchemaType::kBytes:
      return "bytes";
    case ProtoSchemaType::kUint32:
      return "uint32";
    case ProtoSchemaType::kEnum:
      return "enum";
    case ProtoSchemaType::kSfixed32:
      return "sfixed32";
    case ProtoSchemaType::kSfixed64:
      return "sfixed64";
    case ProtoSchemaType::kSint32:
      return "sint32";
    case ProtoSchemaType::kSint64:
      return "sint64";
  }
  // For gcc:
  PERFETTO_DCHECK(false);
  return "";
}

// Maximum message size supported: 256 MiB (4 x 7-bit due to varint encoding).
constexpr size_t kMessageLengthFieldSize = 4;
constexpr size_t kMaxMessageLength = (1u << (kMessageLengthFieldSize * 7)) - 1;
constexpr size_t kMaxOneByteMessageLength = (1 << 7) - 1;

// Field tag is encoded as 32-bit varint (5 bytes at most).
// Largest value of simple (not length-delimited) field is 64-bit varint
// (10 bytes at most). 15 bytes buffer is enough to store a simple field.
constexpr size_t kMaxTagEncodedSize = 5;
constexpr size_t kMaxSimpleFieldEncodedSize = kMaxTagEncodedSize + 10;

// Proto types: (int|uint|sint)(32|64), bool, enum.
constexpr uint32_t MakeTagVarInt(uint32_t field_id) {
  return (field_id << 3) | static_cast<uint32_t>(ProtoWireType::kVarInt);
}

// Proto types: fixed64, sfixed64, fixed32, sfixed32, double, float.
template <typename T>
constexpr uint32_t MakeTagFixed(uint32_t field_id) {
  static_assert(sizeof(T) == 8 || sizeof(T) == 4, "Value must be 4 or 8 bytes");
  return (field_id << 3) |
         static_cast<uint32_t>((sizeof(T) == 8 ? ProtoWireType::kFixed64
                                               : ProtoWireType::kFixed32));
}

// Proto types: string, bytes, embedded messages.
constexpr uint32_t MakeTagLengthDelimited(uint32_t field_id) {
  return (field_id << 3) |
         static_cast<uint32_t>(ProtoWireType::kLengthDelimited);
}

// Proto types: sint64, sint32.
template <typename T>
inline typename std::make_unsigned<T>::type ZigZagEncode(T value) {
  using UnsignedType = typename std::make_unsigned<T>::type;

  // Right-shift of negative values is implementation specific.
  // Assert the implementation does what we expect, which is that shifting any
  // positive value by sizeof(T) * 8 - 1 gives an all 0 bitmap, and a negative
  // value gives an all 1 bitmap.
  constexpr uint64_t kUnsignedZero = 0u;
  constexpr int64_t kNegativeOne = -1;
  constexpr int64_t kPositiveOne = 1;
  static_assert(static_cast<uint64_t>(kNegativeOne >> 63) == ~kUnsignedZero,
                "implementation does not support assumed rightshift");
  static_assert(static_cast<uint64_t>(kPositiveOne >> 63) == kUnsignedZero,
                "implementation does not support assumed rightshift");

  return (static_cast<UnsignedType>(value) << 1) ^
         static_cast<UnsignedType>(value >> (sizeof(T) * 8 - 1));
}

// Proto types: sint64, sint32.
template <typename T>
inline typename std::make_signed<T>::type ZigZagDecode(T value) {
  using UnsignedType = typename std::make_unsigned<T>::type;
  using SignedType = typename std::make_signed<T>::type;
  auto u_value = static_cast<UnsignedType>(value);
  auto mask = static_cast<UnsignedType>(-static_cast<SignedType>(u_value & 1));
  return static_cast<SignedType>((u_value >> 1) ^ mask);
}

template <typename T>
auto ExtendValueForVarIntSerialization(T value) -> typename std::make_unsigned<
    typename std::conditional<std::is_unsigned<T>::value, T, int64_t>::type>::
    type {
  // If value is <= 0 we must first sign extend to int64_t (see [1]).
  // Finally we always cast to an unsigned value to to avoid arithmetic
  // (sign expanding) shifts in the while loop.
  // [1]: "If you use int32 or int64 as the type for a negative number, the
  // resulting varint is always ten bytes long".
  // - developers.google.com/protocol-buffers/docs/encoding
  // So for each input type we do the following casts:
  // uintX_t -> uintX_t -> uintX_t
  // int8_t  -> int64_t -> uint64_t
  // int16_t -> int64_t -> uint64_t
  // int32_t -> int64_t -> uint64_t
  // int64_t -> int64_t -> uint64_t
  using MaybeExtendedType =
      typename std::conditional<std::is_unsigned<T>::value, T, int64_t>::type;
  using UnsignedType = typename std::make_unsigned<MaybeExtendedType>::type;

  MaybeExtendedType extended_value = static_cast<MaybeExtendedType>(value);
  UnsignedType unsigned_value = static_cast<UnsignedType>(extended_value);

  return unsigned_value;
}

template <typename T>
inline uint8_t* WriteVarInt(T value, uint8_t* target) {
  auto unsigned_value = ExtendValueForVarIntSerialization(value);

  while (unsigned_value >= 0x80) {
    *target++ = static_cast<uint8_t>(unsigned_value) | 0x80;
    unsigned_value >>= 7;
  }
  *target = static_cast<uint8_t>(unsigned_value);
  return target + 1;
}

// Writes a fixed-size redundant encoding of the given |value|. This is
// used to backfill fixed-size reservations for the length field using a
// non-canonical varint encoding (e.g. \x81\x80\x80\x00 instead of \x01).
// See https://github.com/google/protobuf/issues/1530.
// This is used mainly in two cases:
// 1) At trace writing time, when starting a nested messages. The size of a
//    nested message is not known until all its field have been written.
//    |kMessageLengthFieldSize| bytes are reserved to encode the size field and
//    backfilled at the end.
// 2) When rewriting a message at trace filtering time, in protozero/filtering.
//    At that point we know only the upper bound of the length (a filtered
//    message is <= the original one) and we backfill after the message has been
//    filtered.
inline void WriteRedundantVarInt(uint32_t value,
                                 uint8_t* buf,
                                 size_t size = kMessageLengthFieldSize) {
  for (size_t i = 0; i < size; ++i) {
    const uint8_t msb = (i < size - 1) ? 0x80 : 0;
    buf[i] = static_cast<uint8_t>(value) | msb;
    value >>= 7;
  }
}

template <uint32_t field_id>
void StaticAssertSingleBytePreamble() {
  static_assert(field_id < 16,
                "Proto field id too big to fit in a single byte preamble");
}

// Parses a VarInt from the encoded buffer [start, end). |end| is STL-style and
// points one byte past the end of buffer.
// The parsed int value is stored in the output arg |value|. Returns a pointer
// to the next unconsumed byte (so start < retval <= end) or |start| if the
// VarInt could not be fully parsed because there was not enough space in the
// buffer.
inline const uint8_t* ParseVarInt(const uint8_t* start,
                                  const uint8_t* end,
                                  uint64_t* out_value) {
  return PerfettoPbParseVarInt(start, end, out_value);
}

enum class RepetitionType {
  kNotRepeated,
  kRepeatedPacked,
  kRepeatedNotPacked,
};

// Provide a common base struct for all templated FieldMetadata types to allow
// simple checks if a given type is a FieldMetadata or not.
struct FieldMetadataBase {
  constexpr FieldMetadataBase() = default;
};

template <uint32_t field_id,
          RepetitionType repetition_type,
          ProtoSchemaType proto_schema_type,
          typename CppFieldType,
          typename MessageType>
struct FieldMetadata : public FieldMetadataBase {
  constexpr FieldMetadata() = default;

  static constexpr int kFieldId = field_id;
  // Whether this field is repeated, packed (repeated [packed-true]) or not
  // (optional).
  static constexpr RepetitionType kRepetitionType = repetition_type;
  // Proto type of this field (e.g. int64, fixed32 or nested message).
  static constexpr ProtoSchemaType kProtoFieldType = proto_schema_type;
  // C++ type of this field (for nested messages - C++ protozero class).
  using cpp_field_type = CppFieldType;
  // Protozero message which this field belongs to.
  using message_type = MessageType;
};

}  // namespace proto_utils
}  // namespace protozero

#endif  // INCLUDE_PERFETTO_PROTOZERO_PROTO_UTILS_H_
/*
 * Copyright (C) 2019 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.
 */


#ifndef INCLUDE_PERFETTO_PROTOZERO_FIELD_H_
#define INCLUDE_PERFETTO_PROTOZERO_FIELD_H_

#include <stdint.h>

#include <string>
#include <string_view>
#include <vector>

// gen_amalgamated expanded: #include "perfetto/base/logging.h"
// gen_amalgamated expanded: #include "perfetto/protozero/contiguous_memory_range.h"
// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"

namespace protozero {

struct ConstBytes {
  std::string ToStdString() const {
    return std::string(reinterpret_cast<const char*>(data), size);
  }

  const uint8_t* data;
  size_t size;
};

struct ConstChars {
  // Allow implicit conversion to perfetto's base::StringView without depending
  // on perfetto/base or viceversa.
  static constexpr bool kConvertibleToStringView = true;
  static constexpr bool kHashable = true;
  std::string ToStdString() const { return {data, size}; }
  std::string_view ToStdStringView() const { return {data, size}; }

  const char* data;
  size_t size;
};

// A protobuf field decoded by the protozero proto decoders. It exposes
// convenience accessors with minimal debug checks.
// This class is used both by the iterator-based ProtoDecoder and by the
// one-shot TypedProtoDecoder.
// If the field is not valid the accessors consistently return zero-integers or
// null strings.
class Field {
 public:
  bool valid() const { return id_ != 0; }
  uint32_t id() const { return id_; }
  explicit operator bool() const { return valid(); }

  proto_utils::ProtoWireType type() const {
    auto res = static_cast<proto_utils::ProtoWireType>(type_);
    PERFETTO_DCHECK(res == proto_utils::ProtoWireType::kVarInt ||
                    res == proto_utils::ProtoWireType::kLengthDelimited ||
                    res == proto_utils::ProtoWireType::kFixed32 ||
                    res == proto_utils::ProtoWireType::kFixed64);
    return res;
  }

  bool as_bool() const {
    PERFETTO_DCHECK(!valid() || type() == proto_utils::ProtoWireType::kVarInt);
    return static_cast<bool>(int_value_);
  }

  uint32_t as_uint32() const {
    PERFETTO_DCHECK(!valid() || type() == proto_utils::ProtoWireType::kVarInt ||
                    type() == proto_utils::ProtoWireType::kFixed32);
    return static_cast<uint32_t>(int_value_);
  }

  int32_t as_int32() const {
    PERFETTO_DCHECK(!valid() || type() == proto_utils::ProtoWireType::kVarInt ||
                    type() == proto_utils::ProtoWireType::kFixed32);
    return static_cast<int32_t>(int_value_);
  }

  int32_t as_sint32() const {
    PERFETTO_DCHECK(!valid() || type() == proto_utils::ProtoWireType::kVarInt);
    return proto_utils::ZigZagDecode(static_cast<uint32_t>(int_value_));
  }

  uint64_t as_uint64() const {
    PERFETTO_DCHECK(!valid() || type() == proto_utils::ProtoWireType::kVarInt ||
                    type() == proto_utils::ProtoWireType::kFixed32 ||
                    type() == proto_utils::ProtoWireType::kFixed64);
    return int_value_;
  }

  int64_t as_int64() const {
    PERFETTO_DCHECK(!valid() || type() == proto_utils::ProtoWireType::kVarInt ||
                    type() == proto_utils::ProtoWireType::kFixed32 ||
                    type() == proto_utils::ProtoWireType::kFixed64);
    return static_cast<int64_t>(int_value_);
  }

  int64_t as_sint64() const {
    PERFETTO_DCHECK(!valid() || type() == proto_utils::ProtoWireType::kVarInt);
    return proto_utils::ZigZagDecode(static_cast<uint64_t>(int_value_));
  }

  float as_float() const {
    PERFETTO_DCHECK(!valid() || type() == proto_utils::ProtoWireType::kFixed32);
    float res;
    uint32_t value32 = static_cast<uint32_t>(int_value_);
    memcpy(&res, &value32, sizeof(res));
    return res;
  }

  double as_double() const {
    PERFETTO_DCHECK(!valid() || type() == proto_utils::ProtoWireType::kFixed64);
    double res;
    memcpy(&res, &int_value_, sizeof(res));
    return res;
  }

  ConstChars as_string() const {
    PERFETTO_DCHECK(!valid() ||
                    type() == proto_utils::ProtoWireType::kLengthDelimited);
    return ConstChars{reinterpret_cast<const char*>(data()), size_};
  }

  std::string as_std_string() const { return as_string().ToStdString(); }

  ConstBytes as_bytes() const {
    PERFETTO_DCHECK(!valid() ||
                    type() == proto_utils::ProtoWireType::kLengthDelimited);
    return ConstBytes{data(), size_};
  }

  const uint8_t* data() const {
    PERFETTO_DCHECK(!valid() ||
                    type() == proto_utils::ProtoWireType::kLengthDelimited);
    return reinterpret_cast<const uint8_t*>(int_value_);
  }

  size_t size() const {
    PERFETTO_DCHECK(!valid() ||
                    type() == proto_utils::ProtoWireType::kLengthDelimited);
    return size_;
  }

  uint64_t raw_int_value() const { return int_value_; }

  void initialize(uint32_t id,
                  uint8_t type,
                  uint64_t int_value,
                  uint32_t size) {
    id_ = id & kMaxId;
    type_ = type;
    int_value_ = int_value;
    size_ = size;
  }

  // For use with templates. This is used by RepeatedFieldIterator::operator*().
  void get(bool* val) const { *val = as_bool(); }
  void get(uint32_t* val) const { *val = as_uint32(); }
  void get(int32_t* val) const { *val = as_int32(); }
  void get(uint64_t* val) const { *val = as_uint64(); }
  void get(int64_t* val) const { *val = as_int64(); }
  void get(float* val) const { *val = as_float(); }
  void get(double* val) const { *val = as_double(); }
  void get(std::string* val) const { *val = as_std_string(); }
  void get(ConstChars* val) const { *val = as_string(); }
  void get(ConstBytes* val) const { *val = as_bytes(); }
  void get_signed(int32_t* val) const { *val = as_sint32(); }
  void get_signed(int64_t* val) const { *val = as_sint64(); }

  // For enum types.
  template <typename T,
            typename = typename std::enable_if<std::is_enum<T>::value, T>::type>
  void get(T* val) const {
    *val = static_cast<T>(as_int32());
  }

  // Serializes the field back into a proto-encoded byte stream and appends it
  // to |dst|. |dst| is resized accordingly.
  void SerializeAndAppendTo(std::string* dst) const;

  // Serializes the field back into a proto-encoded byte stream and appends it
  // to |dst|. |dst| is resized accordingly.
  void SerializeAndAppendTo(std::vector<uint8_t>* dst) const;

  static constexpr uint32_t kMaxId = (1 << 24) - 1;  // See id_ : 24 below.
 private:
  template <typename Container>
  void SerializeAndAppendToInternal(Container* dst) const;

  // Fields are deliberately not initialized to keep the class trivially
  // constructible. It makes a large perf difference for ProtoDecoder.
  uint64_t int_value_;  // In kLengthDelimited this contains the data() addr.
  uint32_t size_;       // Only valid when when type == kLengthDelimited.

  // Note: MSVC and clang-cl require bit-fields to be of the same type, hence
  // the `: 8` below rather than uint8_t.
  uint32_t id_ : 24;   // Proto field ordinal.
  uint32_t type_ : 8;  // proto_utils::ProtoWireType.
};
// The Field struct is used in a lot of perf-sensitive contexts.
static_assert(sizeof(Field) == 16, "Field struct too big");

}  // namespace protozero

#endif  // INCLUDE_PERFETTO_PROTOZERO_FIELD_H_
// gen_amalgamated begin header: include/perfetto/tracing/core/forward_decls.h
/*
 * Copyright (C) 2019 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.
 */


#ifndef INCLUDE_PERFETTO_TRACING_CORE_FORWARD_DECLS_H_
#define INCLUDE_PERFETTO_TRACING_CORE_FORWARD_DECLS_H_

// Forward declares classes that are generated at build-time from protos.
// First of all, why are we forward declaring at all?
//  1. Chromium diverges from the Google style guide on this, because forward
//     declarations typically make build times faster, and that's a desirable
//     property for a large and complex codebase.
//  2. Adding #include to build-time-generated headers from headers typically
//     creates subtle build errors that are hard to spot in GN. This is because
//     once a standard header (say foo.h) has an #include "protos/foo.gen.h",
//     the build target that depends on foo.h needs to depend on the genrule
//     that generates foo.gen.h. This is achievable using public_deps in GN but
//     is not testable / enforceable, hence too easy to get wrong.

// Historically the classes below used to be generated from the corresponding
// .proto(s) at CL *check-in* time (!= build time) in the ::perfetto namespace.
// Nowadays we have code everywhere that assume the right class is
// ::perfetto::TraceConfig or the like. Back then other headers could just
// forward declared ::perfetto::TraceConfig. These days, the real class is
// ::perfetto::protos::gen::TraceConfig and core/trace_config.h aliases that as
// using ::perfetto::TraceConfig = ::perfetto::protos::gen::TraceConfig.
// In C++ one cannot forward declare a type alias (but only the aliased type).
// Hence this header, which should be used every time one wants to forward
// declare classes like TraceConfig.

// The overall plan is that, when one of the classes below is needed:
// The .h file includes this file.
// The .cc file includes perfetto/tracing/core/trace_config.h (or equiv). That
// header will pull the full declaration from trace_config.gen.h and will also
// setup the alias in the ::perfetto namespace.

namespace perfetto {
namespace protos {
namespace gen {

class ChromeConfig;
class CommitDataRequest;
class DataSourceConfig;
class DataSourceDescriptor;
class ObservableEvents;
class TraceConfig;
class TraceStats;
class TracingServiceCapabilities;
class TracingServiceState;
class SyncClockRequest;
class SyncClockResponse;

}  // namespace gen
}  // namespace protos

using ChromeConfig = ::perfetto::protos::gen::ChromeConfig;
using CommitDataRequest = ::perfetto::protos::gen::CommitDataRequest;
using DataSourceConfig = ::perfetto::protos::gen::DataSourceConfig;
using DataSourceDescriptor = ::perfetto::protos::gen::DataSourceDescriptor;
using ObservableEvents = ::perfetto::protos::gen::ObservableEvents;
using TraceConfig = ::perfetto::protos::gen::TraceConfig;
using TraceStats = ::perfetto::protos::gen::TraceStats;
using TracingServiceCapabilities =
    ::perfetto::protos::gen::TracingServiceCapabilities;
using TracingServiceState = ::perfetto::protos::gen::TracingServiceState;
using SyncClockRequest = ::perfetto::protos::gen::SyncClockRequest;
using SyncClockResponse = ::perfetto::protos::gen::SyncClockResponse;

}  // namespace perfetto

#endif  // INCLUDE_PERFETTO_TRACING_CORE_FORWARD_DECLS_H_
// gen_amalgamated begin header: include/perfetto/tracing/internal/basic_types.h
/*
 * Copyright (C) 2019 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.
 */


#ifndef INCLUDE_PERFETTO_TRACING_INTERNAL_BASIC_TYPES_H_
#define INCLUDE_PERFETTO_TRACING_INTERNAL_BASIC_TYPES_H_

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

namespace perfetto {
namespace internal {

// A static_assert in tracing_muxer_impl.cc guarantees that this stays in sync
// with the definition in tracing/core/basic_types.h
using BufferId = uint16_t;

// This is an id of a backend in the TracingMuxer::producer_backends_ list.
// Backends are only added and never removed.
using TracingBackendId = size_t;

// Max numbers of data sources that can be registered in a process.
constexpr size_t kMaxDataSources = 32;

// Max instances for each data source type. This typically matches the
// "max number of concurrent tracing sessions". However remember that a data
// source can be instantiated more than once within one tracing session by
// creating two entries for it in the trace config.
constexpr size_t kMaxDataSourceInstances = 8;

}  // namespace internal
}  // namespace perfetto

#endif  // INCLUDE_PERFETTO_TRACING_INTERNAL_BASIC_TYPES_H_
// gen_amalgamated begin header: include/perfetto/tracing/internal/data_source_internal.h
// gen_amalgamated begin header: include/perfetto/tracing/core/data_source_config.h
// gen_amalgamated begin header: gen/protos/perfetto/config/data_source_config.gen.h
// gen_amalgamated begin header: include/perfetto/protozero/cpp_message_obj.h
/*
 * Copyright (C) 2019 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.
 */


#ifndef INCLUDE_PERFETTO_PROTOZERO_CPP_MESSAGE_OBJ_H_
#define INCLUDE_PERFETTO_PROTOZERO_CPP_MESSAGE_OBJ_H_

#include <stdint.h>

#include <string>
#include <vector>

// gen_amalgamated expanded: #include "perfetto/base/export.h"

namespace protozero {

// Base class for generated .gen.h classes, which are full C++ objects that
// support both ser and deserialization (but are not zero-copy).
// This is only used by the "cpp" targets not the "pbzero" ones.
class PERFETTO_EXPORT_COMPONENT CppMessageObj {
 public:
  virtual ~CppMessageObj();
  virtual std::string SerializeAsString() const = 0;
  virtual std::vector<uint8_t> SerializeAsArray() const = 0;
  virtual bool ParseFromArray(const void*, size_t) = 0;

  bool ParseFromString(const std::string& str) {
    return ParseFromArray(str.data(), str.size());
  }
};

}  // namespace protozero

#endif  // INCLUDE_PERFETTO_PROTOZERO_CPP_MESSAGE_OBJ_H_
// gen_amalgamated begin header: include/perfetto/protozero/copyable_ptr.h
/*
 * Copyright (C) 2019 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.
 */


#ifndef INCLUDE_PERFETTO_PROTOZERO_COPYABLE_PTR_H_
#define INCLUDE_PERFETTO_PROTOZERO_COPYABLE_PTR_H_

#include <memory>
#include <utility>

namespace protozero {

// This class is essentially a std::vector<T> of fixed size = 1.
// It's a pointer wrapper with deep copying and deep equality comparison.
// At all effects this wrapper behaves like the underlying T, with the exception
// of the heap indirection.
// Conversely to a std::unique_ptr, the pointer will be always valid, never
// null. The problem it solves is the following: when generating C++ classes
// from proto files, we want to keep each header hermetic (i.e. not #include
// headers of dependent types). As such we can't directly instantiate T
// field members but we can instead rely on pointers, so only the .cc file needs
// to see the actual definition of T. If the generated classes were move-only we
// could just use a unique_ptr there. But they aren't, hence this wrapper.
// Converesely to unique_ptr, this wrapper:
// - Default constructs the T instance in its constructor.
// - Implements deep comparison in operator== instead of pointer comparison.
template <typename T>
class CopyablePtr {
 public:
  CopyablePtr() : ptr_(new T()) {}
  ~CopyablePtr() = default;

  // Copy operators.
  CopyablePtr(const CopyablePtr& other) : ptr_(new T(*other.ptr_)) {}
  CopyablePtr& operator=(const CopyablePtr& other) {
    *ptr_ = *other.ptr_;
    return *this;
  }

  // Move operators.
  CopyablePtr(CopyablePtr&& other) noexcept : ptr_(std::move(other.ptr_)) {
    other.ptr_.reset(new T());
  }

  CopyablePtr& operator=(CopyablePtr&& other) {
    ptr_ = std::move(other.ptr_);
    other.ptr_.reset(new T());
    return *this;
  }

  T* get() { return ptr_.get(); }
  const T* get() const { return ptr_.get(); }

  T* operator->() { return ptr_.get(); }
  const T* operator->() const { return ptr_.get(); }

  T& operator*() { return *ptr_; }
  const T& operator*() const { return *ptr_; }

  friend bool operator==(const CopyablePtr& lhs, const CopyablePtr& rhs) {
    return *lhs == *rhs;
  }

  friend bool operator!=(const CopyablePtr& lhs, const CopyablePtr& rhs) {
    // In theory the underlying type might have a special operator!=
    // implementation which is not just !(x == y). Respect that.
    return *lhs != *rhs;
  }

 private:
  std::unique_ptr<T> ptr_;
};

}  // namespace protozero

#endif  // INCLUDE_PERFETTO_PROTOZERO_COPYABLE_PTR_H_
// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_DATA_SOURCE_CONFIG_PROTO_CPP_H_
#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_DATA_SOURCE_CONFIG_PROTO_CPP_H_

#include <stdint.h>
#include <bitset>
#include <vector>
#include <string>
#include <type_traits>

// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
// gen_amalgamated expanded: #include "perfetto/base/export.h"

namespace perfetto {
namespace protos {
namespace gen {
class DataSourceConfig;
class TestConfig;
class TestConfig_DummyFields;
class InterceptorConfig;
class ConsoleConfig;
class ChromeConfig;
class SystemInfoConfig;
enum DataSourceConfig_SessionInitiator : int;
enum ConsoleConfig_Output : int;
enum ChromeConfig_ClientPriority : int;
}  // namespace perfetto
}  // namespace protos
}  // namespace gen

namespace protozero {
class Message;
}  // namespace protozero

namespace perfetto {
namespace protos {
namespace gen {
enum DataSourceConfig_SessionInitiator : int {
  DataSourceConfig_SessionInitiator_SESSION_INITIATOR_UNSPECIFIED = 0,
  DataSourceConfig_SessionInitiator_SESSION_INITIATOR_TRUSTED_SYSTEM = 1,
};

class PERFETTO_EXPORT_COMPONENT DataSourceConfig : public ::protozero::CppMessageObj {
 public:
  using SessionInitiator = DataSourceConfig_SessionInitiator;
  static constexpr auto SESSION_INITIATOR_UNSPECIFIED = DataSourceConfig_SessionInitiator_SESSION_INITIATOR_UNSPECIFIED;
  static constexpr auto SESSION_INITIATOR_TRUSTED_SYSTEM = DataSourceConfig_SessionInitiator_SESSION_INITIATOR_TRUSTED_SYSTEM;
  static constexpr auto SessionInitiator_MIN = DataSourceConfig_SessionInitiator_SESSION_INITIATOR_UNSPECIFIED;
  static constexpr auto SessionInitiator_MAX = DataSourceConfig_SessionInitiator_SESSION_INITIATOR_TRUSTED_SYSTEM;
  enum FieldNumbers {
    kNameFieldNumber = 1,
    kTargetBufferFieldNumber = 2,
    kTraceDurationMsFieldNumber = 3,
    kPreferSuspendClockForDurationFieldNumber = 122,
    kStopTimeoutMsFieldNumber = 7,
    kEnableExtraGuardrailsFieldNumber = 6,
    kSessionInitiatorFieldNumber = 8,
    kTracingSessionIdFieldNumber = 4,
    kFtraceConfigFieldNumber = 100,
    kInodeFileConfigFieldNumber = 102,
    kProcessStatsConfigFieldNumber = 103,
    kSysStatsConfigFieldNumber = 104,
    kHeapprofdConfigFieldNumber = 105,
    kJavaHprofConfigFieldNumber = 110,
    kAndroidPowerConfigFieldNumber = 106,
    kAndroidLogConfigFieldNumber = 107,
    kGpuCounterConfigFieldNumber = 108,
    kAndroidGameInterventionListConfigFieldNumber = 116,
    kPackagesListConfigFieldNumber = 109,
    kPerfEventConfigFieldNumber = 111,
    kVulkanMemoryConfigFieldNumber = 112,
    kTrackEventConfigFieldNumber = 113,
    kAndroidPolledStateConfigFieldNumber = 114,
    kAndroidSystemPropertyConfigFieldNumber = 118,
    kStatsdTracingConfigFieldNumber = 117,
    kSystemInfoConfigFieldNumber = 119,
    kChromeConfigFieldNumber = 101,
    kV8ConfigFieldNumber = 127,
    kInterceptorConfigFieldNumber = 115,
    kNetworkPacketTraceConfigFieldNumber = 120,
    kSurfaceflingerLayersConfigFieldNumber = 121,
    kSurfaceflingerTransactionsConfigFieldNumber = 123,
    kAndroidSdkSyspropGuardConfigFieldNumber = 124,
    kEtwConfigFieldNumber = 125,
    kProtologConfigFieldNumber = 126,
    kAndroidInputEventConfigFieldNumber = 128,
    kPixelModemConfigFieldNumber = 129,
    kWindowmanagerConfigFieldNumber = 130,
    kChromiumSystemMetricsFieldNumber = 131,
    kLegacyConfigFieldNumber = 1000,
    kForTestingFieldNumber = 1001,
  };

  DataSourceConfig();
  ~DataSourceConfig() override;
  DataSourceConfig(DataSourceConfig&&) noexcept;
  DataSourceConfig& operator=(DataSourceConfig&&);
  DataSourceConfig(const DataSourceConfig&);
  DataSourceConfig& operator=(const DataSourceConfig&);
  bool operator==(const DataSourceConfig&) const;
  bool operator!=(const DataSourceConfig& other) const { return !(*this == other); }

  bool ParseFromArray(const void*, size_t) override;
  std::string SerializeAsString() const override;
  std::vector<uint8_t> SerializeAsArray() const override;
  void Serialize(::protozero::Message*) const;

  bool has_name() const { return _has_field_[1]; }
  const std::string& name() const { return name_; }
  void set_name(const std::string& value) { name_ = value; _has_field_.set(1); }

  bool has_target_buffer() const { return _has_field_[2]; }
  uint32_t target_buffer() const { return target_buffer_; }
  void set_target_buffer(uint32_t value) { target_buffer_ = value; _has_field_.set(2); }

  bool has_trace_duration_ms() const { return _has_field_[3]; }
  uint32_t trace_duration_ms() const { return trace_duration_ms_; }
  void set_trace_duration_ms(uint32_t value) { trace_duration_ms_ = value; _has_field_.set(3); }

  bool has_prefer_suspend_clock_for_duration() const { return _has_field_[122]; }
  bool prefer_suspend_clock_for_duration() const { return prefer_suspend_clock_for_duration_; }
  void set_prefer_suspend_clock_for_duration(bool value) { prefer_suspend_clock_for_duration_ = value; _has_field_.set(122); }

  bool has_stop_timeout_ms() const { return _has_field_[7]; }
  uint32_t stop_timeout_ms() const { return stop_timeout_ms_; }
  void set_stop_timeout_ms(uint32_t value) { stop_timeout_ms_ = value; _has_field_.set(7); }

  bool has_enable_extra_guardrails() const { return _has_field_[6]; }
  bool enable_extra_guardrails() const { return enable_extra_guardrails_; }
  void set_enable_extra_guardrails(bool value) { enable_extra_guardrails_ = value; _has_field_.set(6); }

  bool has_session_initiator() const { return _has_field_[8]; }
  DataSourceConfig_SessionInitiator session_initiator() const { return session_initiator_; }
  void set_session_initiator(DataSourceConfig_SessionInitiator value) { session_initiator_ = value; _has_field_.set(8); }

  bool has_tracing_session_id() const { return _has_field_[4]; }
  uint64_t tracing_session_id() const { return tracing_session_id_; }
  void set_tracing_session_id(uint64_t value) { tracing_session_id_ = value; _has_field_.set(4); }

  const std::string& ftrace_config_raw() const { return ftrace_config_; }
  void set_ftrace_config_raw(const std::string& raw) { ftrace_config_ = raw; _has_field_.set(100); }

  const std::string& inode_file_config_raw() const { return inode_file_config_; }
  void set_inode_file_config_raw(const std::string& raw) { inode_file_config_ = raw; _has_field_.set(102); }

  const std::string& process_stats_config_raw() const { return process_stats_config_; }
  void set_process_stats_config_raw(const std::string& raw) { process_stats_config_ = raw; _has_field_.set(103); }

  const std::string& sys_stats_config_raw() const { return sys_stats_config_; }
  void set_sys_stats_config_raw(const std::string& raw) { sys_stats_config_ = raw; _has_field_.set(104); }

  const std::string& heapprofd_config_raw() const { return heapprofd_config_; }
  void set_heapprofd_config_raw(const std::string& raw) { heapprofd_config_ = raw; _has_field_.set(105); }

  const std::string& java_hprof_config_raw() const { return java_hprof_config_; }
  void set_java_hprof_config_raw(const std::string& raw) { java_hprof_config_ = raw; _has_field_.set(110); }

  const std::string& android_power_config_raw() const { return android_power_config_; }
  void set_android_power_config_raw(const std::string& raw) { android_power_config_ = raw; _has_field_.set(106); }

  const std::string& android_log_config_raw() const { return android_log_config_; }
  void set_android_log_config_raw(const std::string& raw) { android_log_config_ = raw; _has_field_.set(107); }

  const std::string& gpu_counter_config_raw() const { return gpu_counter_config_; }
  void set_gpu_counter_config_raw(const std::string& raw) { gpu_counter_config_ = raw; _has_field_.set(108); }

  const std::string& android_game_intervention_list_config_raw() const { return android_game_intervention_list_config_; }
  void set_android_game_intervention_list_config_raw(const std::string& raw) { android_game_intervention_list_config_ = raw; _has_field_.set(116); }

  const std::string& packages_list_config_raw() const { return packages_list_config_; }
  void set_packages_list_config_raw(const std::string& raw) { packages_list_config_ = raw; _has_field_.set(109); }

  const std::string& perf_event_config_raw() const { return perf_event_config_; }
  void set_perf_event_config_raw(const std::string& raw) { perf_event_config_ = raw; _has_field_.set(111); }

  const std::string& vulkan_memory_config_raw() const { return vulkan_memory_config_; }
  void set_vulkan_memory_config_raw(const std::string& raw) { vulkan_memory_config_ = raw; _has_field_.set(112); }

  const std::string& track_event_config_raw() const { return track_event_config_; }
  void set_track_event_config_raw(const std::string& raw) { track_event_config_ = raw; _has_field_.set(113); }

  const std::string& android_polled_state_config_raw() const { return android_polled_state_config_; }
  void set_android_polled_state_config_raw(const std::string& raw) { android_polled_state_config_ = raw; _has_field_.set(114); }

  const std::string& android_system_property_config_raw() const { return android_system_property_config_; }
  void set_android_system_property_config_raw(const std::string& raw) { android_system_property_config_ = raw; _has_field_.set(118); }

  const std::string& statsd_tracing_config_raw() const { return statsd_tracing_config_; }
  void set_statsd_tracing_config_raw(const std::string& raw) { statsd_tracing_config_ = raw; _has_field_.set(117); }

  bool has_system_info_config() const { return _has_field_[119]; }
  const SystemInfoConfig& system_info_config() const { return *system_info_config_; }
  SystemInfoConfig* mutable_system_info_config() { _has_field_.set(119); return system_info_config_.get(); }

  bool has_chrome_config() const { return _has_field_[101]; }
  const ChromeConfig& chrome_config() const { return *chrome_config_; }
  ChromeConfig* mutable_chrome_config() { _has_field_.set(101); return chrome_config_.get(); }

  const std::string& v8_config_raw() const { return v8_config_; }
  void set_v8_config_raw(const std::string& raw) { v8_config_ = raw; _has_field_.set(127); }

  bool has_interceptor_config() const { return _has_field_[115]; }
  const InterceptorConfig& interceptor_config() const { return *interceptor_config_; }
  InterceptorConfig* mutable_interceptor_config() { _has_field_.set(115); return interceptor_config_.get(); }

  const std::string& network_packet_trace_config_raw() const { return network_packet_trace_config_; }
  void set_network_packet_trace_config_raw(const std::string& raw) { network_packet_trace_config_ = raw; _has_field_.set(120); }

  const std::string& surfaceflinger_layers_config_raw() const { return surfaceflinger_layers_config_; }
  void set_surfaceflinger_layers_config_raw(const std::string& raw) { surfaceflinger_layers_config_ = raw; _has_field_.set(121); }

  const std::string& surfaceflinger_transactions_config_raw() const { return surfaceflinger_transactions_config_; }
  void set_surfaceflinger_transactions_config_raw(const std::string& raw) { surfaceflinger_transactions_config_ = raw; _has_field_.set(123); }

  const std::string& android_sdk_sysprop_guard_config_raw() const { return android_sdk_sysprop_guard_config_; }
  void set_android_sdk_sysprop_guard_config_raw(const std::string& raw) { android_sdk_sysprop_guard_config_ = raw; _has_field_.set(124); }

  const std::string& etw_config_raw() const { return etw_config_; }
  void set_etw_config_raw(const std::string& raw) { etw_config_ = raw; _has_field_.set(125); }

  const std::string& protolog_config_raw() const { return protolog_config_; }
  void set_protolog_config_raw(const std::string& raw) { protolog_config_ = raw; _has_field_.set(126); }

  const std::string& android_input_event_config_raw() const { return android_input_event_config_; }
  void set_android_input_event_config_raw(const std::string& raw) { android_input_event_config_ = raw; _has_field_.set(128); }

  const std::string& pixel_modem_config_raw() const { return pixel_modem_config_; }
  void set_pixel_modem_config_raw(const std::string& raw) { pixel_modem_config_ = raw; _has_field_.set(129); }

  const std::string& windowmanager_config_raw() const { return windowmanager_config_; }
  void set_windowmanager_config_raw(const std::string& raw) { windowmanager_config_ = raw; _has_field_.set(130); }

  const std::string& chromium_system_metrics_raw() const { return chromium_system_metrics_; }
  void set_chromium_system_metrics_raw(const std::string& raw) { chromium_system_metrics_ = raw; _has_field_.set(131); }

  bool has_legacy_config() const { return _has_field_[1000]; }
  const std::string& legacy_config() const { return legacy_config_; }
  void set_legacy_config(const std::string& value) { legacy_config_ = value; _has_field_.set(1000); }

  bool has_for_testing() const { return _has_field_[1001]; }
  const TestConfig& for_testing() const { return *for_testing_; }
  TestConfig* mutable_for_testing() { _has_field_.set(1001); return for_testing_.get(); }

 private:
  std::string name_{};
  uint32_t target_buffer_{};
  uint32_t trace_duration_ms_{};
  bool prefer_suspend_clock_for_duration_{};
  uint32_t stop_timeout_ms_{};
  bool enable_extra_guardrails_{};
  DataSourceConfig_SessionInitiator session_initiator_{};
  uint64_t tracing_session_id_{};
  std::string ftrace_config_;  // [lazy=true]
  std::string inode_file_config_;  // [lazy=true]
  std::string process_stats_config_;  // [lazy=true]
  std::string sys_stats_config_;  // [lazy=true]
  std::string heapprofd_config_;  // [lazy=true]
  std::string java_hprof_config_;  // [lazy=true]
  std::string android_power_config_;  // [lazy=true]
  std::string android_log_config_;  // [lazy=true]
  std::string gpu_counter_config_;  // [lazy=true]
  std::string android_game_intervention_list_config_;  // [lazy=true]
  std::string packages_list_config_;  // [lazy=true]
  std::string perf_event_config_;  // [lazy=true]
  std::string vulkan_memory_config_;  // [lazy=true]
  std::string track_event_config_;  // [lazy=true]
  std::string android_polled_state_config_;  // [lazy=true]
  std::string android_system_property_config_;  // [lazy=true]
  std::string statsd_tracing_config_;  // [lazy=true]
  ::protozero::CopyablePtr<SystemInfoConfig> system_info_config_;
  ::protozero::CopyablePtr<ChromeConfig> chrome_config_;
  std::string v8_config_;  // [lazy=true]
  ::protozero::CopyablePtr<InterceptorConfig> interceptor_config_;
  std::string network_packet_trace_config_;  // [lazy=true]
  std::string surfaceflinger_layers_config_;  // [lazy=true]
  std::string surfaceflinger_transactions_config_;  // [lazy=true]
  std::string android_sdk_sysprop_guard_config_;  // [lazy=true]
  std::string etw_config_;  // [lazy=true]
  std::string protolog_config_;  // [lazy=true]
  std::string android_input_event_config_;  // [lazy=true]
  std::string pixel_modem_config_;  // [lazy=true]
  std::string windowmanager_config_;  // [lazy=true]
  std::string chromium_system_metrics_;  // [lazy=true]
  std::string legacy_config_{};
  ::protozero::CopyablePtr<TestConfig> for_testing_;

  // Allows to preserve unknown protobuf fields for compatibility
  // with future versions of .proto files.
  std::string unknown_fields_;

  std::bitset<1002> _has_field_{};
};

}  // namespace perfetto
}  // namespace protos
}  // namespace gen

#endif  // PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_DATA_SOURCE_CONFIG_PROTO_CPP_H_
/*
 * 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.
 */


#ifndef INCLUDE_PERFETTO_TRACING_CORE_DATA_SOURCE_CONFIG_H_
#define INCLUDE_PERFETTO_TRACING_CORE_DATA_SOURCE_CONFIG_H_

// Creates the aliases in the ::perfetto namespace, doing things like:
// using ::perfetto::Foo = ::perfetto::protos::gen::Foo.
// See comments in forward_decls.h for the historical reasons of this
// indirection layer.
// gen_amalgamated expanded: #include "perfetto/tracing/core/forward_decls.h"

// gen_amalgamated expanded: #include "protos/perfetto/config/data_source_config.gen.h"

#endif  // INCLUDE_PERFETTO_TRACING_CORE_DATA_SOURCE_CONFIG_H_
// gen_amalgamated begin header: include/perfetto/tracing/trace_writer_base.h
// gen_amalgamated begin header: include/perfetto/protozero/message_handle.h
// gen_amalgamated begin header: include/perfetto/protozero/message.h
// gen_amalgamated begin header: include/perfetto/protozero/scattered_stream_writer.h
/*
 * 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.
 */


#ifndef INCLUDE_PERFETTO_PROTOZERO_SCATTERED_STREAM_WRITER_H_
#define INCLUDE_PERFETTO_PROTOZERO_SCATTERED_STREAM_WRITER_H_

#include <assert.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>

#include <algorithm>

// gen_amalgamated expanded: #include "perfetto/base/compiler.h"
// gen_amalgamated expanded: #include "perfetto/base/export.h"
// gen_amalgamated expanded: #include "perfetto/base/logging.h"
// gen_amalgamated expanded: #include "perfetto/protozero/contiguous_memory_range.h"

namespace protozero {

// This class deals with the following problem: append-only proto messages want
// to write a stream of bytes, without caring about the implementation of the
// underlying buffer (which concretely will be either the trace ring buffer
// or a heap-allocated buffer). The main deal is: proto messages don't know in
// advance what their size will be.
// Due to the tracing buffer being split into fixed-size chunks, on some
// occasions, these writes need to be spread over two (or more) non-contiguous
// chunks of memory. Similarly, when the buffer is backed by the heap, we want
// to avoid realloc() calls, as they might cause a full copy of the contents
// of the buffer.
// The purpose of this class is to abstract away the non-contiguous write logic.
// This class knows how to deal with writes as long as they fall in the same
// ContiguousMemoryRange and defers the chunk-chaining logic to the Delegate.
class PERFETTO_EXPORT_COMPONENT ScatteredStreamWriter {
 public:
  class PERFETTO_EXPORT_COMPONENT Delegate {
   public:
    static constexpr size_t kPatchSize = 4;
    virtual ~Delegate();

    // Returns a new chunk for writing.
    virtual ContiguousMemoryRange GetNewBuffer() = 0;

    // Signals the delegate that the location pointed by `to_patch` (which must
    // be in the last chunk returned by GetNewBuffer()), kPatchSize long, needs
    // to be updated later (after potentially multiple GetNewBuffer calls).
    //
    // The caller must write to the returned location later. If the returned
    // pointer is nullptr, the caller should not write anything.
    //
    // The implementation considers the patch ready to apply when the caller
    // writes the first byte a value that's different than 0 (the
    // implementation periodically checks for this).
    virtual uint8_t* AnnotatePatch(uint8_t* patch_addr);
  };

  explicit ScatteredStreamWriter(Delegate* delegate);
  ~ScatteredStreamWriter();

  inline void WriteByte(uint8_t value) {
    if (write_ptr_ >= cur_range_.end)
      Extend();
    *write_ptr_++ = value;
  }

  // Assumes that the caller checked that there is enough headroom.
  // TODO(primiano): perf optimization, this is a tracing hot path. The
  // compiler can make strong optimization on std::copy if the size arg is a
  // constexpr. Make a templated variant of this for fixed-size writes.
  // TODO(primiano): restrict / noalias might also help.
  inline void WriteBytesUnsafe(const uint8_t* src, size_t size) {
    uint8_t* const end = write_ptr_ + size;
    assert(end <= cur_range_.end);
    std::copy(src, src + size, write_ptr_);
    write_ptr_ = end;
  }

  inline void WriteBytes(const uint8_t* src,
                         size_t size) PERFETTO_NO_SANITIZE_UNDEFINED {
    // If the stream writer hasn't been initialized, constructing the end
    // pointer below invokes undefined behavior because `write_ptr_` is null.
    // Since this function is on the hot path, we suppress the warning instead
    // of adding a conditional branch.
    uint8_t* const end = write_ptr_ + size;
    if (PERFETTO_LIKELY(end <= cur_range_.end))
      return WriteBytesUnsafe(src, size);
    WriteBytesSlowPath(src, size);
  }

  void WriteBytesSlowPath(const uint8_t* src, size_t size);

  // Reserves a fixed amount of bytes to be backfilled later. The reserved range
  // is guaranteed to be contiguous and not span across chunks. |size| has to be
  // <= than the size of a new buffer returned by the Delegate::GetNewBuffer().
  uint8_t* ReserveBytes(size_t size);

  // Fast (but unsafe) version of the above. The caller must have previously
  // checked that there are at least |size| contiguous bytes available.
  // Returns only the start pointer of the reservation.
  uint8_t* ReserveBytesUnsafe(size_t size) {
    uint8_t* begin = write_ptr_;
    write_ptr_ += size;
    assert(write_ptr_ <= cur_range_.end);
    return begin;
  }

  // Shifts the previously written `size` bytes backwards in memory by `offset`
  // bytes, moving the write pointer back accordingly. The shifted result must
  // still be fully contained by the current range.
  void Rewind(size_t size, size_t offset) {
    uint8_t* src = write_ptr_ - size;
    uint8_t* dst = src - offset;
    PERFETTO_DCHECK(src >= cur_range_.begin);
    PERFETTO_DCHECK(src + size <= cur_range_.end);
    PERFETTO_DCHECK(dst >= cur_range_.begin);
    PERFETTO_DCHECK(dst + size <= cur_range_.end);
    memmove(dst, src, size);
    write_ptr_ -= offset;
  }

  // Resets the buffer boundaries and the write pointer to the given |range|.
  // Subsequent WriteByte(s) will write into |range|.
  void Reset(ContiguousMemoryRange range);

  // Commits the current chunk and gets a new chunk from the delegate.
  void Extend();

  // Number of contiguous free bytes in |cur_range_| that can be written without
  // requesting a new buffer.
  size_t bytes_available() const {
    return static_cast<size_t>(cur_range_.end - write_ptr_);
  }

  ContiguousMemoryRange cur_range() const { return cur_range_; }

  uint8_t* write_ptr() const { return write_ptr_; }

  void set_write_ptr(uint8_t* write_ptr) {
    assert(cur_range_.begin <= write_ptr && write_ptr <= cur_range_.end);
    write_ptr_ = write_ptr;
  }

  uint64_t written() const {
    return written_previously_ +
           static_cast<uint64_t>(write_ptr_ - cur_range_.begin);
  }

  uint64_t written_previously() const { return written_previously_; }

  uint8_t* AnnotatePatch(uint8_t* patch_addr) {
    return delegate_->AnnotatePatch(patch_addr);
  }

 private:
  ScatteredStreamWriter(const ScatteredStreamWriter&) = delete;
  ScatteredStreamWriter& operator=(const ScatteredStreamWriter&) = delete;

  Delegate* const delegate_;
  ContiguousMemoryRange cur_range_;
  uint8_t* write_ptr_;
  uint64_t written_previously_ = 0;
};

}  // namespace protozero

#endif  // INCLUDE_PERFETTO_PROTOZERO_SCATTERED_STREAM_WRITER_H_
/*
 * 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.
 */


#ifndef INCLUDE_PERFETTO_PROTOZERO_MESSAGE_H_
#define INCLUDE_PERFETTO_PROTOZERO_MESSAGE_H_

#include <assert.h>
#include <stdint.h>
#include <string.h>

#include <string>
#include <type_traits>

// gen_amalgamated expanded: #include "perfetto/base/export.h"
// gen_amalgamated expanded: #include "perfetto/base/logging.h"
// gen_amalgamated expanded: #include "perfetto/protozero/contiguous_memory_range.h"
// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
// gen_amalgamated expanded: #include "perfetto/protozero/scattered_stream_writer.h"

namespace perfetto {
namespace shm_fuzz {
class FakeProducer;
}  // namespace shm_fuzz
}  // namespace perfetto

namespace protozero {

class MessageArena;
class MessageHandleBase;

// Base class extended by the proto C++ stubs generated by the ProtoZero
// compiler. This class provides the minimal runtime required to support
// append-only operations and is designed for performance. None of the methods
// require any dynamic memory allocation, unless more than 16 nested messages
// are created via BeginNestedMessage() calls.
class PERFETTO_EXPORT_COMPONENT Message {
 public:
  friend class MessageHandleBase;

  // The ctor is deliberately a no-op to avoid forwarding args from all
  // subclasses. The real initialization is performed by Reset().
  // Nested messages are allocated via placement new by MessageArena and
  // implictly destroyed when the RootMessage's arena goes away. This is
  // fine as long as all the fields are PODs, which is checked by the
  // static_assert()s in the Reset() method.
  Message() = default;

  // Clears up the state, allowing the message to be reused as a fresh one.
  void Reset(ScatteredStreamWriter*, MessageArena*);

  // Commits all the changes to the buffer (backfills the size field of this and
  // all nested messages) and seals the message. Returns the size of the message
  // (and all nested sub-messages), without taking into account any chunking.
  // Finalize is idempotent and can be called several times w/o side effects.
  // Short messages may be compacted in memory into the size field, since their
  // size can be represented with fewer than
  // proto_utils::kMessageLengthFieldSize bytes.
  uint32_t Finalize();

  // Optional. If is_valid() == true, the corresponding memory region (its
  // length == proto_utils::kMessageLengthFieldSize) is backfilled with the size
  // of this message. This is the mechanism used by messages to backfill their
  // corresponding size field in the parent message. In most cases this is only
  // used for nested messages and the ScatteredStreamWriter::Delegate (e.g.
  // TraceWriterImpl), takes case of the outer message.
  uint8_t* size_field() const { return size_field_; }
  void set_size_field(uint8_t* size_field) { size_field_ = size_field; }

  Message* nested_message() { return nested_message_; }

  bool is_finalized() const {
    return message_state_ != MessageState::kNotFinalized;
  }

#if PERFETTO_DCHECK_IS_ON()
  void set_handle(MessageHandleBase* handle) { handle_ = handle; }
#endif

  // Proto types: uint64, uint32, int64, int32, bool, enum.
  template <typename T>
  void AppendVarInt(uint32_t field_id, T value) {
    if (nested_message_)
      EndNestedMessage();

    uint8_t buffer[proto_utils::kMaxSimpleFieldEncodedSize];
    uint8_t* pos = buffer;

    pos = proto_utils::WriteVarInt(proto_utils::MakeTagVarInt(field_id), pos);
    // WriteVarInt encodes signed values in two's complement form.
    pos = proto_utils::WriteVarInt(value, pos);
    WriteToStream(buffer, pos);
  }

  // Proto types: sint64, sint32.
  template <typename T>
  void AppendSignedVarInt(uint32_t field_id, T value) {
    AppendVarInt(field_id, proto_utils::ZigZagEncode(value));
  }

  // Proto types: bool, enum (small).
  // Faster version of AppendVarInt for tiny numbers.
  void AppendTinyVarInt(uint32_t field_id, int32_t value) {
    PERFETTO_DCHECK(0 <= value && value < 0x80);
    if (nested_message_)
      EndNestedMessage();

    uint8_t buffer[proto_utils::kMaxSimpleFieldEncodedSize];
    uint8_t* pos = buffer;
    // MakeTagVarInt gets super optimized here for constexpr.
    pos = proto_utils::WriteVarInt(proto_utils::MakeTagVarInt(field_id), pos);
    *pos++ = static_cast<uint8_t>(value);
    WriteToStream(buffer, pos);
  }

  // Proto types: fixed64, sfixed64, fixed32, sfixed32, double, float.
  template <typename T>
  void AppendFixed(uint32_t field_id, T value) {
    if (nested_message_)
      EndNestedMessage();

    uint8_t buffer[proto_utils::kMaxSimpleFieldEncodedSize];
    uint8_t* pos = buffer;

    pos = proto_utils::WriteVarInt(proto_utils::MakeTagFixed<T>(field_id), pos);
    memcpy(pos, &value, sizeof(T));
    pos += sizeof(T);
    // TODO: Optimize memcpy performance, see http://crbug.com/624311 .
    WriteToStream(buffer, pos);
  }

  void AppendString(uint32_t field_id, const char* str);

  void AppendString(uint32_t field_id, const std::string& str) {
    AppendBytes(field_id, str.data(), str.size());
  }

  void AppendBytes(uint32_t field_id, const void* value, size_t size);

  // Append raw bytes for a field, using the supplied |ranges| to
  // copy from |num_ranges| individual buffers.
  size_t AppendScatteredBytes(uint32_t field_id,
                              ContiguousMemoryRange* ranges,
                              size_t num_ranges);

  // Begins a nested message. The returned object is owned by the MessageArena
  // of the root message. The nested message ends either when Finalize() is
  // called or when any other Append* method is called in the parent class.
  // The template argument T is supposed to be a stub class auto generated from
  // a .proto, hence a subclass of Message.
  template <class T>
  T* BeginNestedMessage(uint32_t field_id) {
    // This is to prevent subclasses (which should be autogenerated, though), to
    // introduce extra state fields (which wouldn't be initialized by Reset()).
    static_assert(std::is_base_of<Message, T>::value,
                  "T must be a subclass of Message");
    static_assert(sizeof(T) == sizeof(Message),
                  "Message subclasses cannot introduce extra state.");
    return static_cast<T*>(BeginNestedMessageInternal(field_id));
  }

  // Gives read-only access to the underlying stream_writer. This is used only
  // by few internals to query the state of the underlying buffer. It is almost
  // always a bad idea to poke at the stream_writer() internals.
  const ScatteredStreamWriter* stream_writer() const { return stream_writer_; }

  // Appends some raw bytes to the message. The use-case for this is preserving
  // unknown fields in the decode -> re-encode path of xxx.gen.cc classes
  // generated by the cppgen_plugin.cc.
  // The caller needs to guarantee that the appended data is properly
  // proto-encoded and each field has a proto preamble.
  void AppendRawProtoBytes(const void* data, size_t size) {
    if (nested_message_)
      EndNestedMessage();
    const uint8_t* src = reinterpret_cast<const uint8_t*>(data);
    WriteToStream(src, src + size);
  }

 private:
  Message(const Message&) = delete;
  Message& operator=(const Message&) = delete;

  Message* BeginNestedMessageInternal(uint32_t field_id);

  // Called by Finalize and Append* methods.
  void EndNestedMessage();

  void WriteToStream(const uint8_t* src_begin, const uint8_t* src_end) {
    PERFETTO_DCHECK(!is_finalized());
    PERFETTO_DCHECK(src_begin <= src_end);
    const uint32_t size = static_cast<uint32_t>(src_end - src_begin);
    stream_writer_->WriteBytes(src_begin, size);
    size_ += size;
  }

  // Only POD fields are allowed. This class's dtor is never called.
  // See the comment on the static_assert in the corresponding .cc file.

  // The stream writer interface used for the serialization.
  ScatteredStreamWriter* stream_writer_;

  // The storage used to allocate nested Message objects.
  // This is owned by RootMessage<T>.
  MessageArena* arena_;

  // Pointer to the last child message created through BeginNestedMessage(), if
  // any, nullptr otherwise. There is no need to keep track of more than one
  // message per nesting level as the proto-zero API contract mandates that
  // nested fields can be filled only in a stacked fashion. In other words,
  // nested messages are finalized and sealed when any other field is set in the
  // parent message (or the parent message itself is finalized) and cannot be
  // accessed anymore afterwards.
  Message* nested_message_;

  // [optional] Pointer to a non-aligned pre-reserved var-int slot of
  // kMessageLengthFieldSize bytes. When set, the Finalize() method will write
  // the size of proto-encoded message in the pointed memory region.
  uint8_t* size_field_;

  // Keeps track of the size of the current message.
  uint32_t size_;

  enum class MessageState : uint8_t {
    // Message is still being written to.
    kNotFinalized,
    // Finalized, no more changes to the message are allowed. This is to DCHECK
    // attempts of writing to a message which has been Finalize()-d.
    kFinalized,
    // Finalized, and additionally the message data has been partially or fully
    // compacted into the last 3 bytes of `size_field_`. See the comment in
    // Finalize().
    kFinalizedWithCompaction,
  };

  MessageState message_state_;

#if PERFETTO_DCHECK_IS_ON()
  // Current generation of message. Incremented on Reset.
  // Used to detect stale handles.
  uint32_t generation_;

  MessageHandleBase* handle_;
#endif
};

}  // namespace protozero

#endif  // INCLUDE_PERFETTO_PROTOZERO_MESSAGE_H_
/*
 * 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.
 */


#ifndef INCLUDE_PERFETTO_PROTOZERO_MESSAGE_HANDLE_H_
#define INCLUDE_PERFETTO_PROTOZERO_MESSAGE_HANDLE_H_

#include <functional>

// gen_amalgamated expanded: #include "perfetto/base/export.h"
// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
// gen_amalgamated expanded: #include "perfetto/protozero/scattered_stream_writer.h"

namespace protozero {

class Message;

class PERFETTO_EXPORT_COMPONENT MessageFinalizationListener {
 public:
  virtual ~MessageFinalizationListener();
  virtual void OnMessageFinalized(Message* message) = 0;
};

// MessageHandle allows to decouple the lifetime of a proto message
// from the underlying storage. It gives the following guarantees:
// - The underlying message is finalized (if still alive) if the handle goes
//   out of scope.
// - In Debug / DCHECK_ALWAYS_ON builds, the handle becomes null once the
//   message is finalized. This is to enforce the append-only API. For instance
//   when adding two repeated messages, the addition of the 2nd one forces
//   the finalization of the first.
// Think about this as a WeakPtr<Message> which calls
// Message::Finalize() when going out of scope.

class PERFETTO_EXPORT_COMPONENT MessageHandleBase {
 public:
  ~MessageHandleBase() {
    if (message_) {
#if PERFETTO_DCHECK_IS_ON()
      PERFETTO_DCHECK(generation_ == message_->generation_);
#endif
      FinalizeMessage();
    }
  }

  // Move-only type.
  MessageHandleBase(MessageHandleBase&& other) noexcept {
    Move(std::move(other));
  }

  MessageHandleBase& operator=(MessageHandleBase&& other) noexcept {
    // If the current handle was pointing to a message and is being reset to a
    // new one, finalize the old message. However, if the other message is the
    // same as the one we point to, don't finalize.
    if (message_ && message_ != other.message_)
      FinalizeMessage();
    Move(std::move(other));
    return *this;
  }

  explicit operator bool() const {
#if PERFETTO_DCHECK_IS_ON()
    PERFETTO_DCHECK(!message_ || generation_ == message_->generation_);
#endif
    return !!message_;
  }

  void set_finalization_listener(MessageFinalizationListener* listener) {
    listener_ = listener;
  }

  // Returns a (non-owned, it should not be deleted) pointer to the
  // ScatteredStreamWriter used to write the message data. The Message becomes
  // unusable after this point.
  //
  // The caller can now write directly, without using protozero::Message.
  ScatteredStreamWriter* TakeStreamWriter() {
    ScatteredStreamWriter* stream_writer = message_->stream_writer_;
#if PERFETTO_DCHECK_IS_ON()
    message_->set_handle(nullptr);
#endif
    message_ = nullptr;
    listener_ = nullptr;
    return stream_writer;
  }

 protected:
  explicit MessageHandleBase(Message* message = nullptr) : message_(message) {
#if PERFETTO_DCHECK_IS_ON()
    generation_ = message_ ? message->generation_ : 0;
    if (message_)
      message_->set_handle(this);
#endif
  }

  Message* operator->() const {
#if PERFETTO_DCHECK_IS_ON()
    PERFETTO_DCHECK(!message_ || generation_ == message_->generation_);
#endif
    return message_;
  }
  Message& operator*() const { return *(operator->()); }

 private:
  friend class Message;
  MessageHandleBase(const MessageHandleBase&) = delete;
  MessageHandleBase& operator=(const MessageHandleBase&) = delete;

  void reset_message() {
    // This is called by Message::Finalize().
    PERFETTO_DCHECK(message_->is_finalized());
    message_ = nullptr;
    listener_ = nullptr;
  }

  void Move(MessageHandleBase&& other) {
    message_ = other.message_;
    other.message_ = nullptr;
    listener_ = other.listener_;
    other.listener_ = nullptr;
#if PERFETTO_DCHECK_IS_ON()
    if (message_) {
      generation_ = message_->generation_;
      message_->set_handle(this);
    }
#endif
  }

  void FinalizeMessage() {
    // |message_| and |listener_| may be cleared by reset_message() during
    // Message::Finalize().
    auto* listener = listener_;
    auto* message = message_;
    message->Finalize();
    if (listener)
      listener->OnMessageFinalized(message);
  }

  Message* message_;
  MessageFinalizationListener* listener_ = nullptr;
#if PERFETTO_DCHECK_IS_ON()
  uint32_t generation_;
#endif
};

template <typename T>
class MessageHandle : public MessageHandleBase {
 public:
  MessageHandle() : MessageHandle(nullptr) {}
  explicit MessageHandle(T* message) : MessageHandleBase(message) {}

  explicit operator bool() const { return MessageHandleBase::operator bool(); }

  T& operator*() const {
    return static_cast<T&>(MessageHandleBase::operator*());
  }

  T* operator->() const {
    return static_cast<T*>(MessageHandleBase::operator->());
  }

  T* get() const { return static_cast<T*>(MessageHandleBase::operator->()); }
};

}  // namespace protozero

#endif  // INCLUDE_PERFETTO_PROTOZERO_MESSAGE_HANDLE_H_
/*
 * Copyright (C) 2019 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.
 */


#ifndef INCLUDE_PERFETTO_TRACING_TRACE_WRITER_BASE_H_
#define INCLUDE_PERFETTO_TRACING_TRACE_WRITER_BASE_H_

// gen_amalgamated expanded: #include "perfetto/base/export.h"
// gen_amalgamated expanded: #include "perfetto/protozero/message_handle.h"

namespace perfetto {

namespace protos {
namespace pbzero {
class TracePacket;
}  // namespace pbzero
}  // namespace protos

// This is a single-thread write interface that allows to write protobufs
// directly into the tracing shared buffer without making any copies.
// The idea is that each data source creates one (or more) TraceWriter for each
// thread it wants to write from. Each TraceWriter will get its own dedicated
// chunk and will write into the shared buffer without any locking most of the
// time.

class PERFETTO_EXPORT_COMPONENT TraceWriterBase {
 public:
  virtual ~TraceWriterBase();

  // Creates a new trace packet and returns a handle to a protozero Message that
  // will write to it. The message will be finalized either by calling directly
  // handle.Finalize() or by letting the handle go out of scope (the message
  // should be finalized before a new call to NewTracePacket is made). The
  // returned handle can be std::move()'d but cannot be used after either: (i)
  // the TraceWriter instance is destroyed, (ii) a subsequence NewTracePacket()
  // call is made on the same TraceWriter instance.
  //
  // The caller can use protozero::MessageHandle::TakeStreamWriter() to write.
  //
  // The caller must call ->Finalize() on the returned trace packet (the handle
  // destructor will take care of that) or explicitly call FinishTracePacket (if
  // using TakeStreamWriter) before calling any method on the same TraceWriter
  // instance.
  //
  // The returned packet handle is always valid, but note that, when using
  // BufferExhaustedPolicy::kDrop and the SMB is exhausted, it may be assigned
  // a garbage chunk and any trace data written into it will be lost. For more
  // details on buffer size choices: https://perfetto.dev/docs/concepts/buffers.
  virtual protozero::MessageHandle<protos::pbzero::TracePacket>
  NewTracePacket() = 0;

  // Tells the TraceWriterBase that the previous packet started with
  // NewTracePacket() is finished.
  //
  // Calling this is optional: the TraceWriterBase can realize that the previous
  // packet is finished when the next NewTracePacket() is called. It is still
  // useful, because the next NewTracePacket may not happen for a while.
  virtual void FinishTracePacket() = 0;

  // Commits the data pending for the current chunk. This can be called
  // only if the handle returned by NewTracePacket() has been destroyed (i.e. we
  // cannot Flush() while writing a TracePacket).
  //
  // Note: Flush() also happens implicitly when destroying the TraceWriter.
  //
  // |callback| is an optional callback. When non-null it will request the
  // service to ACK the flush and will be invoked after the service has
  // acknowledged it. The callback might be NEVER INVOKED if the service crashes
  // or the IPC connection is dropped. The callback should be used only by tests
  // and best-effort features (logging).
  virtual void Flush(std::function<void()> callback = {}) = 0;

  // Bytes written since creation. Not reset when new chunks are acquired.
  virtual uint64_t written() const = 0;
};

}  // namespace perfetto

#endif  // INCLUDE_PERFETTO_TRACING_TRACE_WRITER_BASE_H_
/*
 * Copyright (C) 2019 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.
 */


#ifndef INCLUDE_PERFETTO_TRACING_INTERNAL_DATA_SOURCE_INTERNAL_H_
#define INCLUDE_PERFETTO_TRACING_INTERNAL_DATA_SOURCE_INTERNAL_H_

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

#include <array>
#include <atomic>
#include <functional>
#include <memory>
#include <mutex>

// No perfetto headers (other than tracing/api and protozero) should be here.
// gen_amalgamated expanded: #include "perfetto/tracing/buffer_exhausted_policy.h"
// gen_amalgamated expanded: #include "perfetto/tracing/core/data_source_config.h"
// gen_amalgamated expanded: #include "perfetto/tracing/internal/basic_types.h"
// gen_amalgamated expanded: #include "perfetto/tracing/trace_writer_base.h"

namespace perfetto {

class DataSourceBase;
class InterceptorBase;
class TraceWriterBase;

namespace internal {

class TracingTLS;

// This maintains the internal state of a data source instance that is used only
// to implement the tracing mechanics and is not exposed to the API client.
// There is one of these object per DataSource instance (up to
// kMaxDataSourceInstances).
struct DataSourceState {
  // This boolean flag determines whether the DataSource::Trace() method should
  // do something or be a no-op. This flag doesn't give the full guarantee
  // that tracing data will be visible in the trace, it just makes it so that
  // the client attemps writing trace data and interacting with the service.
  // For instance, when a tracing session ends the service will reject data
  // commits that arrive too late even if the producer hasn't received the stop
  // IPC message.
  // This flag is set right before calling OnStart() and cleared right before
  // calling OnStop(), unless using HandleStopAsynchronously() (see comments
  // in data_source.h).
  // Keep this flag as the first field. This allows the compiler to directly
  // dereference the DataSourceState* pointer in the trace fast-path without
  // doing extra pointr arithmetic.
  std::atomic<bool> trace_lambda_enabled{false};

  // The overall TracingMuxerImpl instance id, which gets incremented by
  // ResetForTesting.
  uint32_t muxer_id_for_testing = 0;

  // The central buffer id that all TraceWriter(s) created by this data source
  // must target.
  BufferId buffer_id = 0;

  // The index within TracingMuxerImpl.backends_. Practically it allows to
  // lookup the Producer object, and hence the IPC channel, for this data
  // source.
  TracingBackendId backend_id = 0;

  // Each backend may connect to the tracing service multiple times if a
  // disconnection occurs. This counter is used to uniquely identify each
  // connection so that trace writers don't get reused across connections.
  uint32_t backend_connection_id = 0;

  // The instance id as assigned by the tracing service. Note that because a
  // process can be connected to >1 services, this ID is not globally unique but
  // is only unique within the scope of its backend.
  // Only the tuple (backend_id, data_source_instance_id) is globally unique.
  uint64_t data_source_instance_id = 0;

  // Set to a non-0 target buffer reservation ID iff startup tracing is
  // currently enabled for this data source.
  std::atomic<uint16_t> startup_target_buffer_reservation{0};

  // If the data source was originally started for startup tracing, this is set
  // to the startup session's ID.
  uint64_t startup_session_id = 0;

  // The trace config used by this instance. This is used to de-duplicate
  // instances for data sources with identical names (e.g., track event).
  // We store it as a pointer to be able to free memory after the datasource
  // is stopped.
  std::unique_ptr<DataSourceConfig> config;

  // If this data source is being intercepted (see Interceptor), this field
  // contains the non-zero id of a registered interceptor which should receive
  // trace packets for this session. Note: interceptor id 1 refers to the first
  // element of TracingMuxerImpl::interceptors_ with successive numbers using
  // the following slots.
  uint32_t interceptor_id = 0;

  // This is set to true when the datasource is in the process of async stop.
  // The flag is checked by the tracing muxer to avoid calling OnStop for the
  // second time.
  bool async_stop_in_progress = false;

  // Whether this data source instance should call NotifyDataSourceStopped()
  // when it's stopped.
  bool will_notify_on_stop = false;

  // Incremented whenever incremental state should be reset for this instance of
  // this data source.
  std::atomic<uint32_t> incremental_state_generation{0};

  // This lock is not held to implement Trace() and it's used only if the trace
  // code wants to access its own data source state.
  // This is to prevent that accessing the data source on an arbitrary embedder
  // thread races with the internal IPC thread destroying the data source
  // because of a end-of-tracing notification from the service.
  // This lock is also used to protect access to a possible interceptor for this
  // data source session.
  std::recursive_mutex lock;
  std::unique_ptr<DataSourceBase> data_source;
  std::unique_ptr<InterceptorBase> interceptor;
};

// This is to allow lazy-initialization and avoid static initializers and
// at-exit destructors. All the entries are initialized via placement-new when
// DataSource::Register() is called, see TracingMuxerImpl::RegisterDataSource().
struct DataSourceStateStorage {
  alignas(DataSourceState) char storage[sizeof(DataSourceState)]{};
};

// Per-DataSource-type global state.
struct DataSourceStaticState {
  // System-wide unique id of the data source.
  uint64_t id = 0;

  // Unique index of the data source, assigned at registration time.
  uint32_t index = kMaxDataSources;

  // A bitmap that tells about the validity of each |instances| entry. When the
  // i-th bit of the bitmap it's set, instances[i] is valid.
  std::atomic<uint32_t> valid_instances{};
  std::array<DataSourceStateStorage, kMaxDataSourceInstances> instances{};

  // The caller must be sure that `n` was a valid instance at some point (either
  // through a previous read of `valid_instances` or because the instance lock
  // is held).
  DataSourceState* GetUnsafe(size_t n) {
    return reinterpret_cast<DataSourceState*>(&instances[n]);
  }

  // Can be used with a cached |valid_instances| bitmap.
  DataSourceState* TryGetCached(uint32_t cached_bitmap, size_t n) {
    return cached_bitmap & (1 << n) ? GetUnsafe(n) : nullptr;
  }

  DataSourceState* TryGet(size_t n) {
    return TryGetCached(valid_instances.load(std::memory_order_acquire), n);
  }

  void CompilerAsserts() {
    static_assert(sizeof(valid_instances.load()) * 8 >= kMaxDataSourceInstances,
                  "kMaxDataSourceInstances too high");
  }

  void ResetForTesting() {
    id = 0;
    index = kMaxDataSources;
    valid_instances.store(0, std::memory_order_release);
    instances = {};
  }
};

// Per-DataSource-instance thread-local state.
struct DataSourceInstanceThreadLocalState {
  void Reset() { *this = DataSourceInstanceThreadLocalState{}; }

  std::unique_ptr<TraceWriterBase> trace_writer;
  using ObjectWithDeleter = std::unique_ptr<voidvoid (*)(void*)>;
  ObjectWithDeleter incremental_state = {nullptr, [](void*) {}};
  ObjectWithDeleter data_source_custom_tls = {nullptr, [](void*) {}};
  uint32_t incremental_state_generation = 0;
  uint32_t muxer_id_for_testing = 0;
  TracingBackendId backend_id = 0;
  uint32_t backend_connection_id = 0;
  BufferId buffer_id = 0;
  uint64_t data_source_instance_id = 0;
  bool is_intercepted = false;
  uint64_t last_empty_packet_position = 0;
  uint16_t startup_target_buffer_reservation = 0;
};

// Per-DataSource-type thread-local state.
struct DataSourceThreadLocalState {
  DataSourceStaticState* static_state = nullptr;

  // Pointer to the parent tls object that holds us. Used to retrieve the
  // generation, which is per-global-TLS and not per data-source.
  TracingTLS* root_tls = nullptr;

  // One entry per each data source instance.
  std::array<DataSourceInstanceThreadLocalState, kMaxDataSourceInstances>
      per_instance{};
};

}  // namespace internal
}  // namespace perfetto

#endif  // INCLUDE_PERFETTO_TRACING_INTERNAL_DATA_SOURCE_INTERNAL_H_
// gen_amalgamated begin header: include/perfetto/tracing/locked_handle.h
/*
 * Copyright (C) 2019 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.
 */


#ifndef INCLUDE_PERFETTO_TRACING_LOCKED_HANDLE_H_
#define INCLUDE_PERFETTO_TRACING_LOCKED_HANDLE_H_

#include <mutex>

namespace perfetto {

// This is used for GetDataSourceLocked(), in the (rare) case where the
// tracing code wants to access the state of its data source from the Trace()
// method.
template <typename T>
class LockedHandle {
 public:
  LockedHandle(std::unique_lock<std::recursive_mutex> lock, T* obj)
      : lock_(std::move(lock)), obj_(obj) {}
  LockedHandle() = default;  // For the invalid case.
  LockedHandle(LockedHandle&&) = default;
  LockedHandle& operator=(LockedHandle&&) = default;

  bool valid() const { return obj_; }
  explicit operator bool() const { return valid(); }

  T* operator->() {
    assert(valid());
    return obj_;
  }

  T& operator*() { return *(this->operator->()); }

 private:
  std::unique_lock<std::recursive_mutex> lock_;
  T* obj_ = nullptr;
};

}  // namespace perfetto

#endif  // INCLUDE_PERFETTO_TRACING_LOCKED_HANDLE_H_
/*
 * Copyright (C) 2020 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.
 */


#ifndef INCLUDE_PERFETTO_TRACING_INTERCEPTOR_H_
#define INCLUDE_PERFETTO_TRACING_INTERCEPTOR_H_

// An interceptor is used to redirect trace packets written by a data source
// into a custom backend instead of the normal Perfetto tracing service. For
// example, the console interceptor prints all trace packets to the console as
// they are generated. Another potential use is exporting trace data to another
// tracing service such as Android ATrace or Windows ETW.
//
// An interceptor is defined by subclassing the perfetto::Interceptor template:
//
// class MyInterceptor : public perfetto::Interceptor<MyInterceptor> {
//  public:
//   ~MyInterceptor() override = default;
//
//   // This function is called for each intercepted trace packet. |context|
//   // contains information about the trace packet as well as other state
//   // tracked by the interceptor (e.g., see ThreadLocalState).
//   //
//   // Intercepted trace data is provided in the form of serialized protobuf
//   // bytes, accessed through the |context.packet_data| field.
//   //
//   // Warning: this function can be called on any thread at any time. See
//   // below for how to safely access shared interceptor data from here.
//   static void OnTracePacket(InterceptorContext context) {
//     perfetto::protos::pbzero::TracePacket::Decoder packet(
//         context.packet_data.data, context.packet_data.size);
//     // ... Write |packet| to the desired destination ...
//   }
// };
//
// An interceptor should be registered before any tracing sessions are started.
// Note that the interceptor also needs to be activated through the trace config
// as shown below.
//
//   perfetto::InterceptorDescriptor desc;
//   desc.set_name("my_interceptor");
//   MyInterceptor::Register(desc);
//
// Finally, an interceptor is enabled through the trace config like this:
//
//   perfetto::TraceConfig cfg;
//   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
//   ds_cfg->set_name("data_source_to_intercept");   // e.g. "track_event"
//   ds_cfg->mutable_interceptor_config()->set_name("my_interceptor");
//
// Once an interceptor is enabled, all data from the affected data sources is
// sent to the interceptor instead of the main tracing buffer.
//
// Interceptor state
// =================
//
// Besides the serialized trace packet data, the |OnTracePacket| interceptor
// function can access three other types of state:
//
// 1. Global state: this is no different from a normal static function, but care
//    must be taken because |OnTracePacket| can be called concurrently on any
//    thread at any time.
//
// 2. Per-data source instance state: since the interceptor class is
//    automatically instantiated for each intercepted data source, its fields
//    can be used to store per-instance data such as the trace config. This data
//    can be maintained through the OnSetup/OnStart/OnStop callbacks:
//
//    class MyInterceptor : public perfetto::Interceptor<MyInterceptor> {
//     public:
//      void OnSetup(const SetupArgs& args) override {
//        enable_foo_ = args.config.interceptor_config().enable_foo();
//      }
//
//      bool enable_foo_{};
//    };
//
//    In the interceptor function this data must be accessed through a scoped
//    lock for safety:
//
//    class MyInterceptor : public perfetto::Interceptor<MyInterceptor> {
//      ...
//      static void OnTracePacket(InterceptorContext context) {
//        auto my_interceptor = context.GetInterceptorLocked();
//        if (my_interceptor) {
//           // Access fields of MyInterceptor here.
//           if (my_interceptor->enable_foo_) { ... }
//        }
//        ...
//      }
//    };
//
//    Since accessing this data involves holding a lock, it should be done
//    sparingly.
//
// 3. Per-thread/TraceWriter state: many data sources use interning to avoid
//    repeating common data in the trace. Since the interning dictionaries are
//    typically kept individually for each TraceWriter sequence (i.e., per
//    thread), an interceptor can declare a data structure with lifetime
//    matching the TraceWriter:
//
//    class MyInterceptor : public perfetto::Interceptor<MyInterceptor> {
//     public:
//      struct ThreadLocalState
//          : public perfetto::InterceptorBase::ThreadLocalState {
//        ThreadLocalState(ThreadLocalStateArgs&) override = default;
//        ~ThreadLocalState() override = default;
//
//        std::map<size_t, std::string> event_names;
//      };
//    };
//
//    This per-thread state can then be accessed and maintained in
//    |OnTracePacket| like this:
//
//    class MyInterceptor : public perfetto::Interceptor<MyInterceptor> {
//      ...
//      static void OnTracePacket(InterceptorContext context) {
//        // Updating interned data.
//        auto& tls = context.GetThreadLocalState();
//        if (parsed_packet.sequence_flags() & perfetto::protos::pbzero::
//                TracePacket::SEQ_INCREMENTAL_STATE_CLEARED) {
//          tls.event_names.clear();
//        }
//        for (const auto& entry : parsed_packet.interned_data().event_names())
//          tls.event_names[entry.iid()] = entry.name();
//
//        // Looking up interned data.
//        if (parsed_packet.has_track_event()) {
//          size_t name_iid = parsed_packet.track_event().name_iid();
//          const std::string& event_name = tls.event_names[name_iid];
//        }
//        ...
//      }
//    };
//

#include <functional>

// gen_amalgamated expanded: #include "perfetto/protozero/field.h"
// gen_amalgamated expanded: #include "perfetto/tracing/core/forward_decls.h"
// gen_amalgamated expanded: #include "perfetto/tracing/internal/basic_types.h"
// gen_amalgamated expanded: #include "perfetto/tracing/internal/data_source_internal.h"
// gen_amalgamated expanded: #include "perfetto/tracing/locked_handle.h"

namespace {
class MockTracingMuxer;
}

namespace perfetto {
namespace protos {
namespace gen {
class DataSourceConfig;
class InterceptorDescriptor;
}  // namespace gen
}  // namespace protos

using protos::gen::InterceptorDescriptor;

namespace internal {
class InterceptorTraceWriter;
class InterceptorTraceWriterTest;
class TracingMuxer;
class TracingMuxerFake;
class TracingMuxerImpl;
}  // namespace internal

// A virtual base class for interceptors. Users should derive from the templated
// subclass below instead of this one.
class PERFETTO_EXPORT_COMPONENT InterceptorBase {
 public:
  virtual ~InterceptorBase();

  // A virtual base class for thread-local state needed by the interceptor.
  // To define your own state, subclass this with the same name in the
  // interceptor class. A reference to the state can then be looked up through
  // context.GetThreadLocalState() in the trace packet interceptor function.
  class PERFETTO_EXPORT_COMPONENT ThreadLocalState {
   public:
    virtual ~ThreadLocalState();
  };

  struct SetupArgs {
    const DataSourceConfig& config;
  };
  struct StartArgs {};
  struct StopArgs {};

  // Called when an intercepted data source is set up. Both the interceptor's
  // and the data source's configuration is available in
  // |SetupArgs|. Called on an internal Perfetto service thread, but not
  // concurrently.
  virtual void OnSetup(const SetupArgs&) {}

  // Called when an intercepted data source starts. Called on an internal
  // Perfetto service thread, but not concurrently.
  virtual void OnStart(const StartArgs&) {}

  // Called when an intercepted data source stops. Called on an internal
  // Perfetto service thread, but not concurrently.
  virtual void OnStop(const StopArgs&) {}

 private:
  friend class internal::InterceptorTraceWriter;
  friend class internal::InterceptorTraceWriterTest;
  friend class internal::TracingMuxer;
  friend class internal::TracingMuxerFake;
  friend class internal::TracingMuxerImpl;
  friend MockTracingMuxer;
  template <class T>
  friend class Interceptor;

  // Data passed from DataSource::Trace() into the interceptor.
  struct TracePacketCallbackArgs {
    internal::DataSourceStaticState* static_state;
    uint32_t instance_index;
    protozero::ConstBytes packet_data;
    ThreadLocalState* tls;
  };

  // These callback functions are defined as stateless to avoid accidentally
  // introducing cross-thread data races.
  using TLSFactory = std::unique_ptr<ThreadLocalState> (*)(
      internal::DataSourceStaticState*,
      uint32_t data_source_instance_index);
  using TracePacketCallback = void (*)(TracePacketCallbackArgs);

  static void RegisterImpl(
      const InterceptorDescriptor& descriptor,
      std::function<std::unique_ptr<InterceptorBase>()> factory,
      InterceptorBase::TLSFactory tls_factory,
      InterceptorBase::TracePacketCallback on_trace_packet);
};

// Templated interceptor instantiation. See above for usage.
template <class InterceptorType>
class PERFETTO_EXPORT_COMPONENT Interceptor : public InterceptorBase {
 public:
  // A context object provided to the ThreadLocalState constructor. Provides
  // access to the per-instance interceptor object.
  class ThreadLocalStateArgs {
   public:
    ~ThreadLocalStateArgs() = default;

    ThreadLocalStateArgs(const ThreadLocalStateArgs&) = delete;
    ThreadLocalStateArgs& operator=(const ThreadLocalStateArgs&) = delete;

    ThreadLocalStateArgs(ThreadLocalStateArgs&&) noexcept = default;
    ThreadLocalStateArgs& operator=(ThreadLocalStateArgs&&) noexcept = default;

    // Return a locked reference to the interceptor session. The session object
    // will remain valid as long as the returned handle is in scope.
    LockedHandle<InterceptorType> GetInterceptorLocked() {
      auto* internal_state = static_state_->TryGet(data_source_instance_index_);
      if (!internal_state)
        return LockedHandle<InterceptorType>();
      std::unique_lock<std::recursive_mutex> lock(internal_state->lock);
      return LockedHandle<InterceptorType>(
          std::move(lock),
          static_cast<InterceptorType*>(internal_state->interceptor.get()));
    }

   private:
    friend class Interceptor<InterceptorType>;
    friend class InterceptorContext;
    friend class TracingMuxerImpl;

    ThreadLocalStateArgs(internal::DataSourceStaticState* static_state,
                         uint32_t data_source_instance_index)
        : static_state_(static_state),
          data_source_instance_index_(data_source_instance_index) {}

    internal::DataSourceStaticState* const static_state_;
    const uint32_t data_source_instance_index_;
  };

  // A context object provided to each call into |OnTracePacket|. Contains the
  // intercepted serialized trace packet data.
  class InterceptorContext {
   public:
    InterceptorContext(InterceptorContext&&) noexcept = default;
    ~InterceptorContext() = default;

    // Return a locked reference to the interceptor session. The session object
    // will remain valid as long as the returned handle is in scope.
    LockedHandle<InterceptorType> GetInterceptorLocked() {
      return tls_args_.GetInterceptorLocked();
    }

    // Return the thread-local state for this interceptor. See
    // InterceptorBase::ThreadLocalState.
    typename InterceptorType::ThreadLocalState& GetThreadLocalState() {
      return static_cast<typename InterceptorType::ThreadLocalState&>(*tls_);
    }

    // A buffer containing the serialized TracePacket protocol buffer message.
    // This memory is only valid during the call to OnTracePacket.
    protozero::ConstBytes packet_data;

   private:
    friend class Interceptor<InterceptorType>;
    InterceptorContext(TracePacketCallbackArgs args)
        : packet_data(args.packet_data),
          tls_args_(args.static_state, args.instance_index),
          tls_(args.tls) {}
    InterceptorContext(const InterceptorContext&) = delete;
    InterceptorContext& operator=(const InterceptorContext&) = delete;

    ThreadLocalStateArgs tls_args_;
    InterceptorBase::ThreadLocalState* const tls_;
  };

  // Register the interceptor for use in tracing sessions.
  // The optional |constructor_args| will be passed to the interceptor when it
  // is constructed.
  template <class... Args>
  static void Register(const InterceptorDescriptor& descriptor,
                       const Args&... constructor_args) {
    auto factory = [constructor_args...]() {
      return std::unique_ptr<InterceptorBase>(
          new InterceptorType(constructor_args...));
    };
    auto tls_factory = [](internal::DataSourceStaticState* static_state,
                          uint32_t data_source_instance_index) {
      // Don't bother allocating TLS state unless the interceptor is actually
      // using it.
      if (std::is_same<typename InterceptorType::ThreadLocalState,
                       InterceptorBase::ThreadLocalState>::value) {
        return std::unique_ptr<InterceptorBase::ThreadLocalState>(nullptr);
      }
      ThreadLocalStateArgs args(static_state, data_source_instance_index);
      return std::unique_ptr<InterceptorBase::ThreadLocalState>(
          new typename InterceptorType::ThreadLocalState(args));
    };
    auto on_trace_packet = [](TracePacketCallbackArgs args) {
      InterceptorType::OnTracePacket(InterceptorContext(std::move(args)));
    };
    RegisterImpl(descriptor, std::move(factory), std::move(tls_factory),
                 std::move(on_trace_packet));
  }
};

}  // namespace perfetto

#endif  // INCLUDE_PERFETTO_TRACING_INTERCEPTOR_H_
// gen_amalgamated begin header: include/perfetto/tracing/track_event_state_tracker.h
// gen_amalgamated begin header: gen/protos/perfetto/trace/track_event/track_event.pbzero.h
// gen_amalgamated begin header: include/perfetto/protozero/field_writer.h
/*
 * 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.
 */


// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"

#ifndef INCLUDE_PERFETTO_PROTOZERO_FIELD_WRITER_H_
#define INCLUDE_PERFETTO_PROTOZERO_FIELD_WRITER_H_

namespace protozero {
namespace internal {

template <proto_utils::ProtoSchemaType proto_schema_type>
struct FieldWriter {
  static_assert(proto_schema_type != proto_utils::ProtoSchemaType::kMessage,
                "FieldWriter can't be used with nested messages");
};

template <>
struct FieldWriter<proto_utils::ProtoSchemaType::kDouble> {
  inline static void Append(Message& message, uint32_t field_id, double value) {
    message.AppendFixed(field_id, value);
  }
};

template <>
struct FieldWriter<proto_utils::ProtoSchemaType::kFloat> {
  inline static void Append(Message& message, uint32_t field_id, float value) {
    message.AppendFixed(field_id, value);
  }
};

template <>
struct FieldWriter<proto_utils::ProtoSchemaType::kBool> {
  inline static void Append(Message& message, uint32_t field_id, bool value) {
    message.AppendTinyVarInt(field_id, value);
  }
};

template <>
struct FieldWriter<proto_utils::ProtoSchemaType::kInt32> {
  inline static void Append(Message& message,
                            uint32_t field_id,
                            int32_t value) {
    message.AppendVarInt(field_id, value);
  }
};

template <>
struct FieldWriter<proto_utils::ProtoSchemaType::kInt64> {
  inline static void Append(Message& message,
                            uint32_t field_id,
                            int64_t value) {
    message.AppendVarInt(field_id, value);
  }
};

template <>
struct FieldWriter<proto_utils::ProtoSchemaType::kUint32> {
  inline static void Append(Message& message,
                            uint32_t field_id,
                            uint32_t value) {
    message.AppendVarInt(field_id, value);
  }
};

template <>
struct FieldWriter<proto_utils::ProtoSchemaType::kUint64> {
  inline static void Append(Message& message,
                            uint32_t field_id,
                            uint64_t value) {
    message.AppendVarInt(field_id, value);
  }
};

template <>
struct FieldWriter<proto_utils::ProtoSchemaType::kSint32> {
  inline static void Append(Message& message,
                            uint32_t field_id,
                            int32_t value) {
    message.AppendSignedVarInt(field_id, value);
  }
};

template <>
struct FieldWriter<proto_utils::ProtoSchemaType::kSint64> {
  inline static void Append(Message& message,
                            uint32_t field_id,
                            int64_t value) {
    message.AppendSignedVarInt(field_id, value);
  }
};

template <>
struct FieldWriter<proto_utils::ProtoSchemaType::kFixed32> {
  inline static void Append(Message& message,
                            uint32_t field_id,
                            uint32_t value) {
    message.AppendFixed(field_id, value);
  }
};

template <>
struct FieldWriter<proto_utils::ProtoSchemaType::kFixed64> {
  inline static void Append(Message& message,
                            uint32_t field_id,
                            uint64_t value) {
    message.AppendFixed(field_id, value);
  }
};

template <>
struct FieldWriter<proto_utils::ProtoSchemaType::kSfixed32> {
  inline static void Append(Message& message,
                            uint32_t field_id,
                            int32_t value) {
    message.AppendFixed(field_id, value);
  }
};

template <>
struct FieldWriter<proto_utils::ProtoSchemaType::kSfixed64> {
  inline static void Append(Message& message,
                            uint32_t field_id,
                            int64_t value) {
    message.AppendFixed(field_id, value);
  }
};

template <>
struct FieldWriter<proto_utils::ProtoSchemaType::kEnum> {
  template <typename EnumType>
  inline static void Append(Message& message,
                            uint32_t field_id,
                            EnumType value) {
    message.AppendVarInt(field_id, value);
  }
};

template <>
struct FieldWriter<proto_utils::ProtoSchemaType::kString> {
  inline static void Append(Message& message,
                            uint32_t field_id,
                            const char* data,
                            size_t size) {
    message.AppendBytes(field_id, data, size);
  }

  inline static void Append(Message& message,
                            uint32_t field_id,
                            const std::string& value) {
    message.AppendBytes(field_id, value.data(), value.size());
  }
};

template <>
struct FieldWriter<proto_utils::ProtoSchemaType::kBytes> {
  inline static void Append(Message& message,
                            uint32_t field_id,
                            const uint8_t* data,
                            size_t size) {
    message.AppendBytes(field_id, data, size);
  }

  inline static void Append(Message& message,
                            uint32_t field_id,
                            const std::string& value) {
    message.AppendBytes(field_id, value.data(), value.size());
  }
};

}  // namespace internal
}  // namespace protozero

#endif  // INCLUDE_PERFETTO_PROTOZERO_FIELD_WRITER_H_
// gen_amalgamated begin header: include/perfetto/protozero/packed_repeated_fields.h
/*
 * Copyright (C) 2019 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.
 */


#ifndef INCLUDE_PERFETTO_PROTOZERO_PACKED_REPEATED_FIELDS_H_
#define INCLUDE_PERFETTO_PROTOZERO_PACKED_REPEATED_FIELDS_H_

#include <stdint.h>

#include <array>
#include <memory>
#include <type_traits>

// gen_amalgamated expanded: #include "perfetto/base/logging.h"
// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"

namespace protozero {

// This file contains classes used when encoding packed repeated fields.
// To encode such a field, the caller is first expected to accumulate all of the
// values in one of the following types (depending on the wire type of the
// individual elements), defined below:
// * protozero::PackedVarInt
// * protozero::PackedFixedSizeInt</*element_type=*/ uint32_t>
// Then that buffer is passed to the protozero-generated setters as an argument.
// After calling the setter, the buffer can be destroyed.
//
// An example of encoding a packed field:
//   protozero::HeapBuffered<protozero::Message> msg;
//   protozero::PackedVarInt buf;
//   buf.Append(42);
//   buf.Append(-1);
//   msg->set_fieldname(buf);
//   msg.SerializeAsString();

class PackedBufferBase {
 public:
  PackedBufferBase() { Reset(); }

  // Copy or move is disabled due to pointers to stack addresses.
  PackedBufferBase(const PackedBufferBase&) = delete;
  PackedBufferBase(PackedBufferBase&&) = delete;
  PackedBufferBase& operator=(const PackedBufferBase&) = delete;
  PackedBufferBase& operator=(PackedBufferBase&&) = delete;

  void Reset();

  const uint8_t* data() const { return storage_begin_; }

  size_t size() const {
    return static_cast<size_t>(write_ptr_ - storage_begin_);
  }

 protected:
  void GrowIfNeeded() {
    PERFETTO_DCHECK(write_ptr_ >= storage_begin_ && write_ptr_ <= storage_end_);
    if (PERFETTO_UNLIKELY(write_ptr_ + kMaxElementSize > storage_end_)) {
      GrowSlowpath();
    }
  }

  void GrowSlowpath();

  // max(uint64_t varint encoding, biggest fixed type (uint64)).
  static constexpr size_t kMaxElementSize = 10;

  // So sizeof(this) == 8k.
  static constexpr size_t kOnStackStorageSize = 8192 - 32;

  uint8_t* storage_begin_;
  uint8_t* storage_end_;
  uint8_t* write_ptr_;
  std::unique_ptr<uint8_t[]> heap_buf_;
  alignas(uint64_t) uint8_t stack_buf_[kOnStackStorageSize];
};

class PackedVarInt : public PackedBufferBase {
 public:
  template <typename T>
  void Append(T value) {
    GrowIfNeeded();
    write_ptr_ = proto_utils::WriteVarInt(value, write_ptr_);
  }
};

template <typename T /* e.g. uint32_t for Fixed32 */>
class PackedFixedSizeInt : public PackedBufferBase {
 public:
  void Append(T value) {
    static_assert(sizeof(T) == 4 || sizeof(T) == 8,
                  "PackedFixedSizeInt should be used only with 32/64-bit ints");
    static_assert(sizeof(T) <= kMaxElementSize,
                  "kMaxElementSize needs to be updated");
    GrowIfNeeded();
    PERFETTO_DCHECK(reinterpret_cast<size_t>(write_ptr_) % alignof(T) == 0);
    memcpy(reinterpret_cast<T*>(write_ptr_), &value, sizeof(T));
    write_ptr_ += sizeof(T);
  }
};

}  // namespace protozero

#endif  // INCLUDE_PERFETTO_PROTOZERO_PACKED_REPEATED_FIELDS_H_
// gen_amalgamated begin header: include/perfetto/protozero/proto_decoder.h
/*
 * 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.
 */


#ifndef INCLUDE_PERFETTO_PROTOZERO_PROTO_DECODER_H_
#define INCLUDE_PERFETTO_PROTOZERO_PROTO_DECODER_H_

#include <stdint.h>
#include <array>
#include <memory>
#include <vector>

// gen_amalgamated expanded: #include "perfetto/base/compiler.h"
// gen_amalgamated expanded: #include "perfetto/base/logging.h"
// gen_amalgamated expanded: #include "perfetto/protozero/field.h"
// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"

namespace protozero {

// A generic protobuf decoder. Doesn't require any knowledge about the proto
// schema. It tokenizes fields, retrieves their ID and type and exposes
// accessors to retrieve its values.
// It does NOT recurse in nested submessages, instead it just computes their
// boundaries, recursion is left to the caller.
// This class is designed to be used in perf-sensitive contexts. It does not
// allocate and does not perform any proto semantic checks (e.g. repeated /
// required / optional). It's supposedly safe wrt out-of-bounds memory accesses
// (see proto_decoder_fuzzer.cc).
// This class serves also as a building block for TypedProtoDecoder, used when
// the schema is known at compile time.
class PERFETTO_EXPORT_COMPONENT ProtoDecoder {
 public:
  // Creates a ProtoDecoder using the given |buffer| with size |length| bytes.
  ProtoDecoder(const void* buffer, size_t length)
      : begin_(reinterpret_cast<const uint8_t*>(buffer)),
        end_(begin_ + length),
        read_ptr_(begin_) {}
  ProtoDecoder(const std::string& str) : ProtoDecoder(str.data(), str.size()) {}
  ProtoDecoder(const ConstBytes& cb) : ProtoDecoder(cb.data, cb.size) {}

  // Reads the next field from the buffer and advances the read cursor. If a
  // full field cannot be read, the returned Field will be invalid (i.e.
  // field.valid() == false).
  Field ReadField();

  // Finds the first field with the given id. Doesn't affect the read cursor.
  Field FindField(uint32_t field_id);

  // Resets the read cursor to the start of the buffer.
  void Reset() { read_ptr_ = begin_; }

  // Resets the read cursor to the given position (must be within the buffer).
  void Reset(const uint8_t* pos) {
    PERFETTO_DCHECK(pos >= begin_ && pos < end_);
    read_ptr_ = pos;
  }

  // Returns the position of read cursor, relative to the start of the buffer.
  size_t read_offset() const { return static_cast<size_t>(read_ptr_ - begin_); }

  size_t bytes_left() const {
    PERFETTO_DCHECK(read_ptr_ <= end_);
    return static_cast<size_t>(end_ - read_ptr_);
  }

  const uint8_t* begin() const { return begin_; }
  const uint8_t* end() const { return end_; }

 protected:
  const uint8_t* const begin_;
  const uint8_t* const end_;
  const uint8_t* read_ptr_ = nullptr;
};

// An iterator-like class used to iterate through repeated fields. Used by
// TypedProtoDecoder. The iteration sequence is a bit counter-intuitive due to
// the fact that fields_[field_id] holds the *last* value of the field, not the
// first, but the remaining storage holds repeated fields in FIFO order.
// Assume that we push the 10,11,12 into a repeated field with ID=1.
//
// Decoder memory layout:  [  fields storage  ] [ repeated fields storage ]
// 1st iteration:           10
// 2nd iteration:           11                   10
// 3rd iteration:           12                   10 11
//
// We start the iteration @ fields_[num_fields], which is the start of the
// repeated fields storage, proceed until the end and lastly jump @ fields_[id].
template <typename T>
class RepeatedFieldIterator {
 public:
  RepeatedFieldIterator(uint32_t field_id,
                        const Field* begin,
                        const Field* end,
                        const Field* last)
      : field_id_(field_id), iter_(begin), end_(end), last_(last) {
    FindNextMatchingId();
  }

  // Constructs an invalid iterator.
  RepeatedFieldIterator()
      : field_id_(0u), iter_(nullptr), end_(nullptr), last_(nullptr) {}

  explicit operator bool() const { return iter_ != end_; }
  const Field& field() const { return *iter_; }

  T operator*() const {
    T val{};
    iter_->get(&val);
    return val;
  }
  const Field* operator->() const { return iter_; }

  RepeatedFieldIterator& operator++() {
    PERFETTO_DCHECK(iter_ != end_);
    if (iter_ == last_) {
      iter_ = end_;
      return *this;
    }
    ++iter_;
    FindNextMatchingId();
    return *this;
  }

  RepeatedFieldIterator operator++(int) {
    PERFETTO_DCHECK(iter_ != end_);
    RepeatedFieldIterator it(*this);
    ++(*this);
    return it;
  }

 private:
  void FindNextMatchingId() {
    PERFETTO_DCHECK(iter_ != last_);
    for (; iter_ != end_; ++iter_) {
      if (iter_->id() == field_id_)
        return;
    }
    iter_ = last_->valid() ? last_ : end_;
  }

  uint32_t field_id_;

  // Initially points to the beginning of the repeated field storage, then is
  // incremented as we call operator++().
  const Field* iter_;

  // Always points to fields_[size_], i.e. past the end of the storage.
  const Field* end_;

  // Always points to fields_[field_id].
  const Field* last_;
};

// As RepeatedFieldIterator, but allows iterating over a packed repeated field
// (which will be initially stored as a single length-delimited field).
// See |GetPackedRepeatedField| for details.
//
// Assumes little endianness, and that the input buffers are well formed -
// containing an exact multiple of encoded elements.
template <proto_utils::ProtoWireType wire_type, typename CppType>
class PackedRepeatedFieldIterator {
 public:
  PackedRepeatedFieldIterator(const uint8_t* data_begin,
                              size_t size,
                              bool* parse_error_ptr)
      : data_end_(data_begin ? data_begin + size : nullptr),
        read_ptr_(data_begin),
        parse_error_(parse_error_ptr) {
    using proto_utils::ProtoWireType;
    static_assert(wire_type == ProtoWireType::kVarInt ||
                      wire_type == ProtoWireType::kFixed32 ||
                      wire_type == ProtoWireType::kFixed64,
                  "invalid type");

    PERFETTO_DCHECK(parse_error_ptr);

    // Either the field is unset (and there are no data pointer), or the field
    // is set with a zero length payload. Mark the iterator as invalid in both
    // cases.
    if (size == 0) {
      curr_value_valid_ = false;
      return;
    }

    if ((wire_type == ProtoWireType::kFixed32 && (size % 4) != 0) ||
        (wire_type == ProtoWireType::kFixed64 && (size % 8) != 0)) {
      *parse_error_ = true;
      curr_value_valid_ = false;
      return;
    }

    ++(*this);
  }

  const CppType operator*() const { return curr_value_; }
  explicit operator bool() const { return curr_value_valid_; }

  PackedRepeatedFieldIterator& operator++() {
    using proto_utils::ProtoWireType;

    if (PERFETTO_UNLIKELY(!curr_value_valid_))
      return *this;

    if (PERFETTO_UNLIKELY(read_ptr_ == data_end_)) {
      curr_value_valid_ = false;
      return *this;
    }

    if (wire_type == ProtoWireType::kVarInt) {
      uint64_t new_value = 0;
      const uint8_t* new_pos =
          proto_utils::ParseVarInt(read_ptr_, data_end_, &new_value);

      if (PERFETTO_UNLIKELY(new_pos == read_ptr_)) {
        // Failed to decode the varint (probably incomplete buffer).
        *parse_error_ = true;
        curr_value_valid_ = false;
      } else {
        read_ptr_ = new_pos;
        curr_value_ = static_cast<CppType>(new_value);
      }
    } else {  // kFixed32 or kFixed64
      constexpr size_t kStep = wire_type == ProtoWireType::kFixed32 ? 4 : 8;

      // NB: the raw buffer is not guaranteed to be aligned, so neither are
      // these copies.
      memcpy(&curr_value_, read_ptr_, sizeof(CppType));
      read_ptr_ += kStep;
    }

    return *this;
  }

  PackedRepeatedFieldIterator operator++(int) {
    PackedRepeatedFieldIterator it(*this);
    ++(*this);
    return it;
  }

 private:
  // Might be null if the backing proto field isn't set.
  const uint8_t* const data_end_;

  // The iterator looks ahead by an element, so |curr_value| holds the value
  // to be returned when the caller dereferences the iterator, and |read_ptr_|
  // points at the start of the next element to be decoded.
  // |read_ptr_| might be null if the backing proto field isn't set.
  const uint8_t* read_ptr_;
  CppType curr_value_ = {};

  // Set to false once we've exhausted the iterator, or encountered an error.
  bool curr_value_valid_ = true;

  // Where to set parsing errors, supplied by the caller.
  boolconst parse_error_;
};

// This decoder loads all fields upfront, without recursing in nested messages.
// It is used as a base class for typed decoders generated by the pbzero plugin.
// The split between TypedProtoDecoderBase and TypedProtoDecoder<> is to have
// unique definition of functions like ParseAllFields() and ExpandHeapStorage().
// The storage (either on-stack or on-heap) for this class is organized as
// follows:
// |-------------------------- fields_ ----------------------|
// [ field 0 (invalid) ] [ fields 1 .. N ] [ repeated fields ]
//                                        ^                  ^
//                                        num_fields_        size_
// Note that if a message has high field numbers, upon creation |size_| can be
// < |num_fields_| (until a heap expansion is hit while inserting).
class PERFETTO_EXPORT_COMPONENT TypedProtoDecoderBase : public ProtoDecoder {
 public:
  // If the field |id| is known at compile time, prefer the templated
  // specialization at<kFieldNumber>().
  const Field& Get(uint32_t id) const {
    if (PERFETTO_LIKELY(id < num_fields_ && id < size_))
      return fields_[id];
    // If id >= num_fields_, the field id is invalid (was not known in the
    // .proto) and we return the 0th field, which is always !valid().
    // If id >= size_ and <= num_fields, the id is valid but the field has not
    // been seen while decoding (hence the stack storage has not been expanded)
    // so we return the 0th invalid field.
    return fields_[0];
  }

  // Returns an object that allows to iterate over all instances of a repeated
  // field given its id. Example usage:
  //   for (auto it = decoder.GetRepeated<int32_t>(N); it; ++it) { ... }
  template <typename T>
  RepeatedFieldIterator<T> GetRepeated(uint32_t field_id) const {
    const Field* repeated_begin;
    // The storage for repeated fields starts after the slot for the highest
    // field id (refer to the diagram in the class-level comment). However, if
    // a message has more than INITIAL_STACK_CAPACITY field there will be no
    // slots available for the repeated fields (if ExpandHeapStorage() was not
    // called). Imagine a message that has highest field id = 102 and that is
    // still using the stack:
    // [ F0 ] [ F1 ] ... [ F100 ] [ F101 ] [ F1012] [ repeated fields ]
    //                                            ^ num_fields_
    //                          ^ size (== capacity)
    if (PERFETTO_LIKELY(num_fields_ < size_)) {
      repeated_begin = &fields_[num_fields_];
    } else {
      // This is the case of not having any storage space for repeated fields.
      // This makes it so begin == end, so the iterator will just skip @ last.
      repeated_begin = &fields_[size_];
    }
    const Field* repeated_end = &fields_[size_];
    const Field* last = &Get(field_id);
    return RepeatedFieldIterator<T>(field_id, repeated_begin, repeated_end,
                                    last);
  }

  // Returns an objects that allows to iterate over all entries of a packed
  // repeated field given its id and type. The |wire_type| is necessary for
  // decoding the packed field, the |cpp_type| is for convenience & stronger
  // typing.
  //
  // The caller must also supply a pointer to a bool that is set to true if the
  // packed buffer is found to be malformed while iterating (so you need to
  // exhaust the iterator if you want to check the full extent of the buffer).
  //
  // Note that unlike standard protobuf parsers, protozero does not allow
  // treating of packed repeated fields as non-packed and vice-versa (therefore
  // not making the packed option forwards and backwards compatible). So
  // the caller needs to use the right accessor for correct results.
  template <proto_utils::ProtoWireType wire_type, typename cpp_type>
  PackedRepeatedFieldIterator<wire_type, cpp_type> GetPackedRepeated(
      uint32_t field_id,
      bool* parse_error_location) const {
    const Field& field = Get(field_id);
    if (field.valid() &&
        field.type() == proto_utils::ProtoWireType::kLengthDelimited) {
      return PackedRepeatedFieldIterator<wire_type, cpp_type>(
          field.data(), field.size(), parse_error_location);
    }
    return PackedRepeatedFieldIterator<wire_type, cpp_type>(
        nullptr, 0, parse_error_location);
  }

 protected:
  TypedProtoDecoderBase(Field* storage,
                        uint32_t num_fields,
                        uint32_t capacity,
                        const uint8_t* buffer,
                        size_t length)
      : ProtoDecoder(buffer, length),
        fields_(storage),
        num_fields_(num_fields),
        // The reason for "capacity -1" is to avoid hitting the expansion path
        // in TypedProtoDecoderBase::ParseAllFields() when we are just setting
        // fields < INITIAL_STACK_CAPACITY (which is the most common case).
        size_(std::min(num_fields, capacity - 1)),
        capacity_(capacity) {
    // The reason why Field needs to be trivially de/constructible is to avoid
    // implicit initializers on all the ~1000 entries. We need it to initialize
    // only on the first |max_field_id| fields, the remaining capacity doesn't
    // require initialization.
    static_assert(std::is_trivially_constructible<Field>::value &&
                      std::is_trivially_destructible<Field>::value &&
                      std::is_trivial<Field>::value,
                  "Field must be a trivial aggregate type");
    memset(fields_, 0, sizeof(Field) * capacity_);
    PERFETTO_DCHECK(capacity > 0);
  }

  void ParseAllFields();

  // Called when the default on-stack storage is exhausted and new repeated
  // fields need to be pushed.
  void ExpandHeapStorage();

  // Used only in presence of a large number of repeated fields, when the
  // default on-stack storage is exhausted.
  std::unique_ptr<Field[]> heap_storage_;

  // Points to the storage, either on-stack (default, provided by the template
  // specialization) or |heap_storage_| after ExpandHeapStorage() is called, in
  // case of a large number of repeated fields.
  Field* fields_;

  // Number of known fields, without accounting repeated storage. This is equal
  // to MAX_FIELD_ID + 1 (to account for the invalid 0th field). It never
  // changes after construction.
  // This is unrelated with |size_| and |capacity_|. If the highest field id of
  // a proto message is 131, |num_fields_| will be = 132 but, on initialization,
  // |size_| = |capacity_| = 100 (INITIAL_STACK_CAPACITY).
  // One cannot generally assume that |fields_| has enough storage to
  // dereference every field. That is only true:
  // - For field ids < INITIAL_STACK_CAPACITY.
  // - After the first call to ExpandHeapStorage().
  uint32_t num_fields_;

  // Number of active |fields_| entries. This is initially equal to
  // min(num_fields_, INITIAL_STACK_CAPACITY - 1) and after ExpandHeapStorage()
  // becomes == |num_fields_|. If the message has non-packed repeated fields, it
  // can grow further, up to |capacity_|.
  // |size_| is always <= |capacity_|. But |num_fields_| can be > |size_|.
  uint32_t size_;

  // Initially equal to kFieldsCapacity of the TypedProtoDecoder
  // specialization. Can grow when falling back on heap-based storage, in which
  // case it represents the size (#fields with each entry of a repeated field
  // counted individually) of the |heap_storage_| array.
  uint32_t capacity_;
};

// This constant is a tradeoff between having a larger stack frame and being
// able to decode field IDs up to N (or N - num_fields repeated fields) without
// falling back on the heap.
#define PROTOZERO_DECODER_INITIAL_STACK_CAPACITY 100

// Template class instantiated by the auto-generated decoder classes declared in
// xxx.pbzero.h files.
template <int MAX_FIELD_ID, bool HAS_NONPACKED_REPEATED_FIELDS>
class TypedProtoDecoder : public TypedProtoDecoderBase {
 public:
  TypedProtoDecoder(const uint8_t* buffer, size_t length)
      : TypedProtoDecoderBase(on_stack_storage_,
                              /*num_fields=*/MAX_FIELD_ID + 1,
                              PROTOZERO_DECODER_INITIAL_STACK_CAPACITY,
                              buffer,
                              length) {
    TypedProtoDecoderBase::ParseAllFields();
  }

  template <uint32_t FIELD_ID>
  const Field& at() const {
    static_assert(FIELD_ID <= MAX_FIELD_ID, "FIELD_ID > MAX_FIELD_ID");
    // If the field id is < the on-stack capacity, it's safe to always
    // dereference |fields_|, whether it's still using the stack or it fell
    // back on the heap. Because both terms of the if () are known at compile
    // time, the compiler elides the branch for ids < INITIAL_STACK_CAPACITY.
    if (FIELD_ID < PROTOZERO_DECODER_INITIAL_STACK_CAPACITY) {
      return fields_[FIELD_ID];
    } else {
      // Otherwise use the slowpath Get() which will do a runtime check.
      return Get(FIELD_ID);
    }
  }

  TypedProtoDecoder(TypedProtoDecoder&& other) noexcept
      : TypedProtoDecoderBase(std::move(other)) {
    // If the moved-from decoder was using on-stack storage, we need to update
    // our pointer to point to this decoder's on-stack storage.
    if (fields_ == other.on_stack_storage_) {
      fields_ = on_stack_storage_;
      memcpy(on_stack_storage_, other.on_stack_storage_,
             sizeof(on_stack_storage_));
    }
  }

 private:
  Field on_stack_storage_[PROTOZERO_DECODER_INITIAL_STACK_CAPACITY];
};

}  // namespace protozero

#endif  // INCLUDE_PERFETTO_PROTOZERO_PROTO_DECODER_H_
// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.

#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_TRACK_EVENT_PROTO_H_
#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_TRACK_EVENT_PROTO_H_

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

// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"

namespace perfetto {
namespace protos {
namespace pbzero {
class ChromeActiveProcesses;
class ChromeApplicationStateInfo;
class ChromeCompositorSchedulerState;
class ChromeContentSettingsEventInfo;
class ChromeFrameReporter;
class ChromeHistogramSample;
class ChromeKeyedService;
class ChromeLatencyInfo;
class ChromeLegacyIpc;
class ChromeMessagePump;
class ChromeMojoEventInfo;
class ChromeRendererSchedulerState;
class ChromeUserEvent;
class ChromeWindowHandleEventInfo;
class DebugAnnotation;
class LogMessage;
class Screenshot;
class SourceLocation;
class TaskExecution;
class TrackEvent_LegacyEvent;
namespace perfetto_pbzero_enum_TrackEvent_LegacyEvent {
enum FlowDirection : int32_t;
}  // namespace perfetto_pbzero_enum_TrackEvent_LegacyEvent
using TrackEvent_LegacyEvent_FlowDirection = perfetto_pbzero_enum_TrackEvent_LegacyEvent::FlowDirection;
namespace perfetto_pbzero_enum_TrackEvent_LegacyEvent {
enum InstantEventScope : int32_t;
}  // namespace perfetto_pbzero_enum_TrackEvent_LegacyEvent
using TrackEvent_LegacyEvent_InstantEventScope = perfetto_pbzero_enum_TrackEvent_LegacyEvent::InstantEventScope;
namespace perfetto_pbzero_enum_TrackEvent {
enum Type : int32_t;
}  // namespace perfetto_pbzero_enum_TrackEvent
using TrackEvent_Type = perfetto_pbzero_enum_TrackEvent::Type;
// Namespace pbzero.
// Namespace protos.
// Namespace perfetto.

namespace perfetto {
namespace protos {
namespace pbzero {

namespace perfetto_pbzero_enum_TrackEvent {
enum Type : int32_t {
  TYPE_UNSPECIFIED = 0,
  TYPE_SLICE_BEGIN = 1,
  TYPE_SLICE_END = 2,
  TYPE_INSTANT = 3,
  TYPE_COUNTER = 4,
};
// namespace perfetto_pbzero_enum_TrackEvent
using TrackEvent_Type = perfetto_pbzero_enum_TrackEvent::Type;


constexpr TrackEvent_Type TrackEvent_Type_MIN = TrackEvent_Type::TYPE_UNSPECIFIED;
constexpr TrackEvent_Type TrackEvent_Type_MAX = TrackEvent_Type::TYPE_COUNTER;


PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
const char* TrackEvent_Type_Name(::perfetto::protos::pbzero::TrackEvent_Type value) {
  switch (value) {
  case ::perfetto::protos::pbzero::TrackEvent_Type::TYPE_UNSPECIFIED:
    return "TYPE_UNSPECIFIED";

  case ::perfetto::protos::pbzero::TrackEvent_Type::TYPE_SLICE_BEGIN:
    return "TYPE_SLICE_BEGIN";

  case ::perfetto::protos::pbzero::TrackEvent_Type::TYPE_SLICE_END:
    return "TYPE_SLICE_END";

  case ::perfetto::protos::pbzero::TrackEvent_Type::TYPE_INSTANT:
    return "TYPE_INSTANT";

  case ::perfetto::protos::pbzero::TrackEvent_Type::TYPE_COUNTER:
    return "TYPE_COUNTER";
  }
  return "PBZERO_UNKNOWN_ENUM_VALUE";
}

namespace perfetto_pbzero_enum_TrackEvent_LegacyEvent {
enum FlowDirection : int32_t {
  FLOW_UNSPECIFIED = 0,
  FLOW_IN = 1,
  FLOW_OUT = 2,
  FLOW_INOUT = 3,
};
// namespace perfetto_pbzero_enum_TrackEvent_LegacyEvent
using TrackEvent_LegacyEvent_FlowDirection = perfetto_pbzero_enum_TrackEvent_LegacyEvent::FlowDirection;


constexpr TrackEvent_LegacyEvent_FlowDirection TrackEvent_LegacyEvent_FlowDirection_MIN = TrackEvent_LegacyEvent_FlowDirection::FLOW_UNSPECIFIED;
constexpr TrackEvent_LegacyEvent_FlowDirection TrackEvent_LegacyEvent_FlowDirection_MAX = TrackEvent_LegacyEvent_FlowDirection::FLOW_INOUT;


PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
const char* TrackEvent_LegacyEvent_FlowDirection_Name(::perfetto::protos::pbzero::TrackEvent_LegacyEvent_FlowDirection value) {
  switch (value) {
  case ::perfetto::protos::pbzero::TrackEvent_LegacyEvent_FlowDirection::FLOW_UNSPECIFIED:
    return "FLOW_UNSPECIFIED";

  case ::perfetto::protos::pbzero::TrackEvent_LegacyEvent_FlowDirection::FLOW_IN:
    return "FLOW_IN";

  case ::perfetto::protos::pbzero::TrackEvent_LegacyEvent_FlowDirection::FLOW_OUT:
    return "FLOW_OUT";

  case ::perfetto::protos::pbzero::TrackEvent_LegacyEvent_FlowDirection::FLOW_INOUT:
    return "FLOW_INOUT";
  }
  return "PBZERO_UNKNOWN_ENUM_VALUE";
}

namespace perfetto_pbzero_enum_TrackEvent_LegacyEvent {
enum InstantEventScope : int32_t {
  SCOPE_UNSPECIFIED = 0,
  SCOPE_GLOBAL = 1,
  SCOPE_PROCESS = 2,
  SCOPE_THREAD = 3,
};
// namespace perfetto_pbzero_enum_TrackEvent_LegacyEvent
using TrackEvent_LegacyEvent_InstantEventScope = perfetto_pbzero_enum_TrackEvent_LegacyEvent::InstantEventScope;


constexpr TrackEvent_LegacyEvent_InstantEventScope TrackEvent_LegacyEvent_InstantEventScope_MIN = TrackEvent_LegacyEvent_InstantEventScope::SCOPE_UNSPECIFIED;
constexpr TrackEvent_LegacyEvent_InstantEventScope TrackEvent_LegacyEvent_InstantEventScope_MAX = TrackEvent_LegacyEvent_InstantEventScope::SCOPE_THREAD;


PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
const char* TrackEvent_LegacyEvent_InstantEventScope_Name(::perfetto::protos::pbzero::TrackEvent_LegacyEvent_InstantEventScope value) {
  switch (value) {
  case ::perfetto::protos::pbzero::TrackEvent_LegacyEvent_InstantEventScope::SCOPE_UNSPECIFIED:
    return "SCOPE_UNSPECIFIED";

  case ::perfetto::protos::pbzero::TrackEvent_LegacyEvent_InstantEventScope::SCOPE_GLOBAL:
    return "SCOPE_GLOBAL";

  case ::perfetto::protos::pbzero::TrackEvent_LegacyEvent_InstantEventScope::SCOPE_PROCESS:
    return "SCOPE_PROCESS";

  case ::perfetto::protos::pbzero::TrackEvent_LegacyEvent_InstantEventScope::SCOPE_THREAD:
    return "SCOPE_THREAD";
  }
  return "PBZERO_UNKNOWN_ENUM_VALUE";
}

class EventName_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
 public:
  EventName_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
  explicit EventName_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
  explicit EventName_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
  bool has_iid() const { return at<1>().valid(); }
  uint64_t iid() const { return at<1>().as_uint64(); }
  bool has_name() const { return at<2>().valid(); }
  ::protozero::ConstChars name() const { return at<2>().as_string(); }
};

class EventName : public ::protozero::Message {
 public:
  using Decoder = EventName_Decoder;
  enum : int32_t {
    kIidFieldNumber = 1,
    kNameFieldNumber = 2,
  };
  static constexpr const char* GetName() { return ".perfetto.protos.EventName"; }


  using FieldMetadata_Iid =
    ::protozero::proto_utils::FieldMetadata<
      1,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kUint64,
      uint64_t,
      EventName>;

  static constexpr FieldMetadata_Iid kIid{};
  void set_iid(uint64_t value) {
    static constexpr uint32_t field_id = FieldMetadata_Iid::kFieldId;
    // Call the appropriate protozero::Message::Append(field_id, ...)
    // method based on the type of the field.
    ::protozero::internal::FieldWriter<
      ::protozero::proto_utils::ProtoSchemaType::kUint64>
        ::Append(*this, field_id, value);
  }

  using FieldMetadata_Name =
    ::protozero::proto_utils::FieldMetadata<
      2,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kString,
      std::string,
      EventName>;

  static constexpr FieldMetadata_Name kName{};
  void set_name(const char* data, size_t size) {
    AppendBytes(FieldMetadata_Name::kFieldId, data, size);
  }
  void set_name(::protozero::ConstChars chars) {
    AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
  }
  void set_name(std::string value) {
    static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
    // Call the appropriate protozero::Message::Append(field_id, ...)
    // method based on the type of the field.
    ::protozero::internal::FieldWriter<
      ::protozero::proto_utils::ProtoSchemaType::kString>
        ::Append(*this, field_id, value);
  }
};

class EventCategory_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
 public:
  EventCategory_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
  explicit EventCategory_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
  explicit EventCategory_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
  bool has_iid() const { return at<1>().valid(); }
  uint64_t iid() const { return at<1>().as_uint64(); }
  bool has_name() const { return at<2>().valid(); }
  ::protozero::ConstChars name() const { return at<2>().as_string(); }
};

class EventCategory : public ::protozero::Message {
 public:
  using Decoder = EventCategory_Decoder;
  enum : int32_t {
    kIidFieldNumber = 1,
    kNameFieldNumber = 2,
  };
  static constexpr const char* GetName() { return ".perfetto.protos.EventCategory"; }


  using FieldMetadata_Iid =
    ::protozero::proto_utils::FieldMetadata<
      1,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kUint64,
      uint64_t,
      EventCategory>;

  static constexpr FieldMetadata_Iid kIid{};
  void set_iid(uint64_t value) {
    static constexpr uint32_t field_id = FieldMetadata_Iid::kFieldId;
    // Call the appropriate protozero::Message::Append(field_id, ...)
    // method based on the type of the field.
    ::protozero::internal::FieldWriter<
      ::protozero::proto_utils::ProtoSchemaType::kUint64>
        ::Append(*this, field_id, value);
  }

  using FieldMetadata_Name =
    ::protozero::proto_utils::FieldMetadata<
      2,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kString,
      std::string,
      EventCategory>;

  static constexpr FieldMetadata_Name kName{};
  void set_name(const char* data, size_t size) {
    AppendBytes(FieldMetadata_Name::kFieldId, data, size);
  }
  void set_name(::protozero::ConstChars chars) {
    AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
  }
  void set_name(std::string value) {
    static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
    // Call the appropriate protozero::Message::Append(field_id, ...)
    // method based on the type of the field.
    ::protozero::internal::FieldWriter<
      ::protozero::proto_utils::ProtoSchemaType::kString>
        ::Append(*this, field_id, value);
  }
};

class TrackEventDefaults_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/45, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
 public:
  TrackEventDefaults_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
  explicit TrackEventDefaults_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
  explicit TrackEventDefaults_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
  bool has_track_uuid() const { return at<11>().valid(); }
  uint64_t track_uuid() const { return at<11>().as_uint64(); }
  bool has_extra_counter_track_uuids() const { return at<31>().valid(); }
  ::protozero::RepeatedFieldIterator<uint64_t> extra_counter_track_uuids() const { return GetRepeated<uint64_t>(31); }
  bool has_extra_double_counter_track_uuids() const { return at<45>().valid(); }
  ::protozero::RepeatedFieldIterator<uint64_t> extra_double_counter_track_uuids() const { return GetRepeated<uint64_t>(45); }
};

class TrackEventDefaults : public ::protozero::Message {
 public:
  using Decoder = TrackEventDefaults_Decoder;
  enum : int32_t {
    kTrackUuidFieldNumber = 11,
    kExtraCounterTrackUuidsFieldNumber = 31,
    kExtraDoubleCounterTrackUuidsFieldNumber = 45,
  };
  static constexpr const char* GetName() { return ".perfetto.protos.TrackEventDefaults"; }


  using FieldMetadata_TrackUuid =
    ::protozero::proto_utils::FieldMetadata<
      11,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kUint64,
      uint64_t,
      TrackEventDefaults>;

  static constexpr FieldMetadata_TrackUuid kTrackUuid{};
  void set_track_uuid(uint64_t value) {
    static constexpr uint32_t field_id = FieldMetadata_TrackUuid::kFieldId;
    // Call the appropriate protozero::Message::Append(field_id, ...)
    // method based on the type of the field.
    ::protozero::internal::FieldWriter<
      ::protozero::proto_utils::ProtoSchemaType::kUint64>
        ::Append(*this, field_id, value);
  }

  using FieldMetadata_ExtraCounterTrackUuids =
    ::protozero::proto_utils::FieldMetadata<
      31,
      ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
      ::protozero::proto_utils::ProtoSchemaType::kUint64,
      uint64_t,
      TrackEventDefaults>;

  static constexpr FieldMetadata_ExtraCounterTrackUuids kExtraCounterTrackUuids{};
  void add_extra_counter_track_uuids(uint64_t value) {
    static constexpr uint32_t field_id = FieldMetadata_ExtraCounterTrackUuids::kFieldId;
    // Call the appropriate protozero::Message::Append(field_id, ...)
    // method based on the type of the field.
    ::protozero::internal::FieldWriter<
      ::protozero::proto_utils::ProtoSchemaType::kUint64>
        ::Append(*this, field_id, value);
  }

  using FieldMetadata_ExtraDoubleCounterTrackUuids =
    ::protozero::proto_utils::FieldMetadata<
      45,
      ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
      ::protozero::proto_utils::ProtoSchemaType::kUint64,
      uint64_t,
      TrackEventDefaults>;

  static constexpr FieldMetadata_ExtraDoubleCounterTrackUuids kExtraDoubleCounterTrackUuids{};
  void add_extra_double_counter_track_uuids(uint64_t value) {
    static constexpr uint32_t field_id = FieldMetadata_ExtraDoubleCounterTrackUuids::kFieldId;
    // Call the appropriate protozero::Message::Append(field_id, ...)
    // method based on the type of the field.
    ::protozero::internal::FieldWriter<
      ::protozero::proto_utils::ProtoSchemaType::kUint64>
        ::Append(*this, field_id, value);
  }
};

class TrackEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/50, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
 public:
  TrackEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
  explicit TrackEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
  explicit TrackEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
  bool has_category_iids() const { return at<3>().valid(); }
  ::protozero::RepeatedFieldIterator<uint64_t> category_iids() const { return GetRepeated<uint64_t>(3); }
  bool has_categories() const { return at<22>().valid(); }
  ::protozero::RepeatedFieldIterator<::protozero::ConstChars> categories() const { return GetRepeated<::protozero::ConstChars>(22); }
  bool has_name_iid() const { return at<10>().valid(); }
  uint64_t name_iid() const { return at<10>().as_uint64(); }
  bool has_name() const { return at<23>().valid(); }
  ::protozero::ConstChars name() const { return at<23>().as_string(); }
  bool has_type() const { return at<9>().valid(); }
  int32_t type() const { return at<9>().as_int32(); }
  bool has_track_uuid() const { return at<11>().valid(); }
  uint64_t track_uuid() const { return at<11>().as_uint64(); }
  bool has_counter_value() const { return at<30>().valid(); }
  int64_t counter_value() const { return at<30>().as_int64(); }
  bool has_double_counter_value() const { return at<44>().valid(); }
  double double_counter_value() const { return at<44>().as_double(); }
  bool has_extra_counter_track_uuids() const { return at<31>().valid(); }
  ::protozero::RepeatedFieldIterator<uint64_t> extra_counter_track_uuids() const { return GetRepeated<uint64_t>(31); }
  bool has_extra_counter_values() const { return at<12>().valid(); }
  ::protozero::RepeatedFieldIterator<int64_t> extra_counter_values() const { return GetRepeated<int64_t>(12); }
  bool has_extra_double_counter_track_uuids() const { return at<45>().valid(); }
  ::protozero::RepeatedFieldIterator<uint64_t> extra_double_counter_track_uuids() const { return GetRepeated<uint64_t>(45); }
  bool has_extra_double_counter_values() const { return at<46>().valid(); }
  ::protozero::RepeatedFieldIterator<double> extra_double_counter_values() const { return GetRepeated<double>(46); }
  bool has_flow_ids_old() const { return at<36>().valid(); }
  ::protozero::RepeatedFieldIterator<uint64_t> flow_ids_old() const { return GetRepeated<uint64_t>(36); }
  bool has_flow_ids() const { return at<47>().valid(); }
  ::protozero::RepeatedFieldIterator<uint64_t> flow_ids() const { return GetRepeated<uint64_t>(47); }
  bool has_terminating_flow_ids_old() const { return at<42>().valid(); }
  ::protozero::RepeatedFieldIterator<uint64_t> terminating_flow_ids_old() const { return GetRepeated<uint64_t>(42); }
  bool has_terminating_flow_ids() const { return at<48>().valid(); }
  ::protozero::RepeatedFieldIterator<uint64_t> terminating_flow_ids() const { return GetRepeated<uint64_t>(48); }
  bool has_debug_annotations() const { return at<4>().valid(); }
  ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> debug_annotations() const { return GetRepeated<::protozero::ConstBytes>(4); }
  bool has_task_execution() const { return at<5>().valid(); }
  ::protozero::ConstBytes task_execution() const { return at<5>().as_bytes(); }
  bool has_log_message() const { return at<21>().valid(); }
  ::protozero::ConstBytes log_message() const { return at<21>().as_bytes(); }
  bool has_cc_scheduler_state() const { return at<24>().valid(); }
  ::protozero::ConstBytes cc_scheduler_state() const { return at<24>().as_bytes(); }
  bool has_chrome_user_event() const { return at<25>().valid(); }
  ::protozero::ConstBytes chrome_user_event() const { return at<25>().as_bytes(); }
  bool has_chrome_keyed_service() const { return at<26>().valid(); }
  ::protozero::ConstBytes chrome_keyed_service() const { return at<26>().as_bytes(); }
  bool has_chrome_legacy_ipc() const { return at<27>().valid(); }
  ::protozero::ConstBytes chrome_legacy_ipc() const { return at<27>().as_bytes(); }
  bool has_chrome_histogram_sample() const { return at<28>().valid(); }
  ::protozero::ConstBytes chrome_histogram_sample() const { return at<28>().as_bytes(); }
  bool has_chrome_latency_info() const { return at<29>().valid(); }
  ::protozero::ConstBytes chrome_latency_info() const { return at<29>().as_bytes(); }
  bool has_chrome_frame_reporter() const { return at<32>().valid(); }
  ::protozero::ConstBytes chrome_frame_reporter() const { return at<32>().as_bytes(); }
  bool has_chrome_application_state_info() const { return at<39>().valid(); }
  ::protozero::ConstBytes chrome_application_state_info() const { return at<39>().as_bytes(); }
  bool has_chrome_renderer_scheduler_state() const { return at<40>().valid(); }
  ::protozero::ConstBytes chrome_renderer_scheduler_state() const { return at<40>().as_bytes(); }
  bool has_chrome_window_handle_event_info() const { return at<41>().valid(); }
  ::protozero::ConstBytes chrome_window_handle_event_info() const { return at<41>().as_bytes(); }
  bool has_chrome_content_settings_event_info() const { return at<43>().valid(); }
  ::protozero::ConstBytes chrome_content_settings_event_info() const { return at<43>().as_bytes(); }
  bool has_chrome_active_processes() const { return at<49>().valid(); }
  ::protozero::ConstBytes chrome_active_processes() const { return at<49>().as_bytes(); }
  bool has_screenshot() const { return at<50>().valid(); }
  ::protozero::ConstBytes screenshot() const { return at<50>().as_bytes(); }
  bool has_source_location() const { return at<33>().valid(); }
  ::protozero::ConstBytes source_location() const { return at<33>().as_bytes(); }
  bool has_source_location_iid() const { return at<34>().valid(); }
  uint64_t source_location_iid() const { return at<34>().as_uint64(); }
  bool has_chrome_message_pump() const { return at<35>().valid(); }
  ::protozero::ConstBytes chrome_message_pump() const { return at<35>().as_bytes(); }
  bool has_chrome_mojo_event_info() const { return at<38>().valid(); }
  ::protozero::ConstBytes chrome_mojo_event_info() const { return at<38>().as_bytes(); }
  bool has_timestamp_delta_us() const { return at<1>().valid(); }
  int64_t timestamp_delta_us() const { return at<1>().as_int64(); }
  bool has_timestamp_absolute_us() const { return at<16>().valid(); }
  int64_t timestamp_absolute_us() const { return at<16>().as_int64(); }
  bool has_thread_time_delta_us() const { return at<2>().valid(); }
  int64_t thread_time_delta_us() const { return at<2>().as_int64(); }
  bool has_thread_time_absolute_us() const { return at<17>().valid(); }
  int64_t thread_time_absolute_us() const { return at<17>().as_int64(); }
  bool has_thread_instruction_count_delta() const { return at<8>().valid(); }
  int64_t thread_instruction_count_delta() const { return at<8>().as_int64(); }
  bool has_thread_instruction_count_absolute() const { return at<20>().valid(); }
  int64_t thread_instruction_count_absolute() const { return at<20>().as_int64(); }
  bool has_legacy_event() const { return at<6>().valid(); }
  ::protozero::ConstBytes legacy_event() const { return at<6>().as_bytes(); }
};

class TrackEvent : public ::protozero::Message {
 public:
  using Decoder = TrackEvent_Decoder;
  enum : int32_t {
    kCategoryIidsFieldNumber = 3,
    kCategoriesFieldNumber = 22,
    kNameIidFieldNumber = 10,
    kNameFieldNumber = 23,
    kTypeFieldNumber = 9,
    kTrackUuidFieldNumber = 11,
    kCounterValueFieldNumber = 30,
    kDoubleCounterValueFieldNumber = 44,
    kExtraCounterTrackUuidsFieldNumber = 31,
    kExtraCounterValuesFieldNumber = 12,
    kExtraDoubleCounterTrackUuidsFieldNumber = 45,
    kExtraDoubleCounterValuesFieldNumber = 46,
    kFlowIdsOldFieldNumber = 36,
    kFlowIdsFieldNumber = 47,
    kTerminatingFlowIdsOldFieldNumber = 42,
    kTerminatingFlowIdsFieldNumber = 48,
    kDebugAnnotationsFieldNumber = 4,
    kTaskExecutionFieldNumber = 5,
    kLogMessageFieldNumber = 21,
    kCcSchedulerStateFieldNumber = 24,
    kChromeUserEventFieldNumber = 25,
    kChromeKeyedServiceFieldNumber = 26,
    kChromeLegacyIpcFieldNumber = 27,
    kChromeHistogramSampleFieldNumber = 28,
    kChromeLatencyInfoFieldNumber = 29,
    kChromeFrameReporterFieldNumber = 32,
    kChromeApplicationStateInfoFieldNumber = 39,
    kChromeRendererSchedulerStateFieldNumber = 40,
    kChromeWindowHandleEventInfoFieldNumber = 41,
    kChromeContentSettingsEventInfoFieldNumber = 43,
    kChromeActiveProcessesFieldNumber = 49,
    kScreenshotFieldNumber = 50,
    kSourceLocationFieldNumber = 33,
    kSourceLocationIidFieldNumber = 34,
    kChromeMessagePumpFieldNumber = 35,
    kChromeMojoEventInfoFieldNumber = 38,
    kTimestampDeltaUsFieldNumber = 1,
    kTimestampAbsoluteUsFieldNumber = 16,
    kThreadTimeDeltaUsFieldNumber = 2,
    kThreadTimeAbsoluteUsFieldNumber = 17,
    kThreadInstructionCountDeltaFieldNumber = 8,
    kThreadInstructionCountAbsoluteFieldNumber = 20,
    kLegacyEventFieldNumber = 6,
  };
  static constexpr const char* GetName() { return ".perfetto.protos.TrackEvent"; }

  using LegacyEvent = ::perfetto::protos::pbzero::TrackEvent_LegacyEvent;

  using Type = ::perfetto::protos::pbzero::TrackEvent_Type;
  static inline const char* Type_Name(Type value) {
    return ::perfetto::protos::pbzero::TrackEvent_Type_Name(value);
  }
  static inline const Type TYPE_UNSPECIFIED = Type::TYPE_UNSPECIFIED;
  static inline const Type TYPE_SLICE_BEGIN = Type::TYPE_SLICE_BEGIN;
  static inline const Type TYPE_SLICE_END = Type::TYPE_SLICE_END;
  static inline const Type TYPE_INSTANT = Type::TYPE_INSTANT;
  static inline const Type TYPE_COUNTER = Type::TYPE_COUNTER;

  using FieldMetadata_CategoryIids =
    ::protozero::proto_utils::FieldMetadata<
      3,
      ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
      ::protozero::proto_utils::ProtoSchemaType::kUint64,
      uint64_t,
      TrackEvent>;

  static constexpr FieldMetadata_CategoryIids kCategoryIids{};
  void add_category_iids(uint64_t value) {
    static constexpr uint32_t field_id = FieldMetadata_CategoryIids::kFieldId;
    // Call the appropriate protozero::Message::Append(field_id, ...)
    // method based on the type of the field.
    ::protozero::internal::FieldWriter<
      ::protozero::proto_utils::ProtoSchemaType::kUint64>
        ::Append(*this, field_id, value);
  }

  using FieldMetadata_Categories =
    ::protozero::proto_utils::FieldMetadata<
      22,
      ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
      ::protozero::proto_utils::ProtoSchemaType::kString,
      std::string,
      TrackEvent>;

  static constexpr FieldMetadata_Categories kCategories{};
  void add_categories(const char* data, size_t size) {
    AppendBytes(FieldMetadata_Categories::kFieldId, data, size);
  }
  void add_categories(::protozero::ConstChars chars) {
    AppendBytes(FieldMetadata_Categories::kFieldId, chars.data, chars.size);
  }
  void add_categories(std::string value) {
    static constexpr uint32_t field_id = FieldMetadata_Categories::kFieldId;
    // Call the appropriate protozero::Message::Append(field_id, ...)
    // method based on the type of the field.
    ::protozero::internal::FieldWriter<
      ::protozero::proto_utils::ProtoSchemaType::kString>
        ::Append(*this, field_id, value);
  }

  using FieldMetadata_NameIid =
    ::protozero::proto_utils::FieldMetadata<
      10,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kUint64,
      uint64_t,
      TrackEvent>;

  static constexpr FieldMetadata_NameIid kNameIid{};
  void set_name_iid(uint64_t value) {
    static constexpr uint32_t field_id = FieldMetadata_NameIid::kFieldId;
    // Call the appropriate protozero::Message::Append(field_id, ...)
    // method based on the type of the field.
    ::protozero::internal::FieldWriter<
      ::protozero::proto_utils::ProtoSchemaType::kUint64>
        ::Append(*this, field_id, value);
  }

  using FieldMetadata_Name =
    ::protozero::proto_utils::FieldMetadata<
      23,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kString,
      std::string,
      TrackEvent>;

  static constexpr FieldMetadata_Name kName{};
  void set_name(const char* data, size_t size) {
    AppendBytes(FieldMetadata_Name::kFieldId, data, size);
  }
  void set_name(::protozero::ConstChars chars) {
    AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
  }
  void set_name(std::string value) {
    static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
    // Call the appropriate protozero::Message::Append(field_id, ...)
    // method based on the type of the field.
    ::protozero::internal::FieldWriter<
      ::protozero::proto_utils::ProtoSchemaType::kString>
        ::Append(*this, field_id, value);
  }

  using FieldMetadata_Type =
    ::protozero::proto_utils::FieldMetadata<
      9,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kEnum,
      TrackEvent_Type,
      TrackEvent>;

  static constexpr FieldMetadata_Type kType{};
  void set_type(TrackEvent_Type value) {
    static constexpr uint32_t field_id = FieldMetadata_Type::kFieldId;
    // Call the appropriate protozero::Message::Append(field_id, ...)
    // method based on the type of the field.
    ::protozero::internal::FieldWriter<
      ::protozero::proto_utils::ProtoSchemaType::kEnum>
        ::Append(*this, field_id, value);
  }

  using FieldMetadata_TrackUuid =
    ::protozero::proto_utils::FieldMetadata<
      11,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kUint64,
      uint64_t,
      TrackEvent>;

  static constexpr FieldMetadata_TrackUuid kTrackUuid{};
  void set_track_uuid(uint64_t value) {
    static constexpr uint32_t field_id = FieldMetadata_TrackUuid::kFieldId;
    // Call the appropriate protozero::Message::Append(field_id, ...)
    // method based on the type of the field.
    ::protozero::internal::FieldWriter<
      ::protozero::proto_utils::ProtoSchemaType::kUint64>
        ::Append(*this, field_id, value);
  }

  using FieldMetadata_CounterValue =
    ::protozero::proto_utils::FieldMetadata<
      30,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kInt64,
      int64_t,
      TrackEvent>;

  static constexpr FieldMetadata_CounterValue kCounterValue{};
  void set_counter_value(int64_t value) {
    static constexpr uint32_t field_id = FieldMetadata_CounterValue::kFieldId;
    // Call the appropriate protozero::Message::Append(field_id, ...)
    // method based on the type of the field.
    ::protozero::internal::FieldWriter<
      ::protozero::proto_utils::ProtoSchemaType::kInt64>
        ::Append(*this, field_id, value);
  }

  using FieldMetadata_DoubleCounterValue =
    ::protozero::proto_utils::FieldMetadata<
      44,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kDouble,
      double,
      TrackEvent>;

  static constexpr FieldMetadata_DoubleCounterValue kDoubleCounterValue{};
  void set_double_counter_value(double value) {
    static constexpr uint32_t field_id = FieldMetadata_DoubleCounterValue::kFieldId;
    // Call the appropriate protozero::Message::Append(field_id, ...)
    // method based on the type of the field.
    ::protozero::internal::FieldWriter<
      ::protozero::proto_utils::ProtoSchemaType::kDouble>
        ::Append(*this, field_id, value);
  }

  using FieldMetadata_ExtraCounterTrackUuids =
    ::protozero::proto_utils::FieldMetadata<
      31,
      ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
      ::protozero::proto_utils::ProtoSchemaType::kUint64,
      uint64_t,
      TrackEvent>;

  static constexpr FieldMetadata_ExtraCounterTrackUuids kExtraCounterTrackUuids{};
  void add_extra_counter_track_uuids(uint64_t value) {
    static constexpr uint32_t field_id = FieldMetadata_ExtraCounterTrackUuids::kFieldId;
    // Call the appropriate protozero::Message::Append(field_id, ...)
    // method based on the type of the field.
    ::protozero::internal::FieldWriter<
      ::protozero::proto_utils::ProtoSchemaType::kUint64>
        ::Append(*this, field_id, value);
  }

  using FieldMetadata_ExtraCounterValues =
    ::protozero::proto_utils::FieldMetadata<
      12,
      ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
      ::protozero::proto_utils::ProtoSchemaType::kInt64,
      int64_t,
      TrackEvent>;

  static constexpr FieldMetadata_ExtraCounterValues kExtraCounterValues{};
  void add_extra_counter_values(int64_t value) {
    static constexpr uint32_t field_id = FieldMetadata_ExtraCounterValues::kFieldId;
    // Call the appropriate protozero::Message::Append(field_id, ...)
    // method based on the type of the field.
    ::protozero::internal::FieldWriter<
      ::protozero::proto_utils::ProtoSchemaType::kInt64>
        ::Append(*this, field_id, value);
  }

  using FieldMetadata_ExtraDoubleCounterTrackUuids =
    ::protozero::proto_utils::FieldMetadata<
      45,
      ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
      ::protozero::proto_utils::ProtoSchemaType::kUint64,
      uint64_t,
      TrackEvent>;

  static constexpr FieldMetadata_ExtraDoubleCounterTrackUuids kExtraDoubleCounterTrackUuids{};
  void add_extra_double_counter_track_uuids(uint64_t value) {
    static constexpr uint32_t field_id = FieldMetadata_ExtraDoubleCounterTrackUuids::kFieldId;
    // Call the appropriate protozero::Message::Append(field_id, ...)
    // method based on the type of the field.
    ::protozero::internal::FieldWriter<
      ::protozero::proto_utils::ProtoSchemaType::kUint64>
        ::Append(*this, field_id, value);
  }

  using FieldMetadata_ExtraDoubleCounterValues =
    ::protozero::proto_utils::FieldMetadata<
      46,
      ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
      ::protozero::proto_utils::ProtoSchemaType::kDouble,
      double,
      TrackEvent>;

  static constexpr FieldMetadata_ExtraDoubleCounterValues kExtraDoubleCounterValues{};
  void add_extra_double_counter_values(double value) {
    static constexpr uint32_t field_id = FieldMetadata_ExtraDoubleCounterValues::kFieldId;
    // Call the appropriate protozero::Message::Append(field_id, ...)
    // method based on the type of the field.
    ::protozero::internal::FieldWriter<
      ::protozero::proto_utils::ProtoSchemaType::kDouble>
        ::Append(*this, field_id, value);
  }

  using FieldMetadata_FlowIdsOld =
    ::protozero::proto_utils::FieldMetadata<
      36,
      ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
      ::protozero::proto_utils::ProtoSchemaType::kUint64,
      uint64_t,
      TrackEvent>;

  static constexpr FieldMetadata_FlowIdsOld kFlowIdsOld{};
  void add_flow_ids_old(uint64_t value) {
    static constexpr uint32_t field_id = FieldMetadata_FlowIdsOld::kFieldId;
    // Call the appropriate protozero::Message::Append(field_id, ...)
    // method based on the type of the field.
    ::protozero::internal::FieldWriter<
      ::protozero::proto_utils::ProtoSchemaType::kUint64>
        ::Append(*this, field_id, value);
  }

  using FieldMetadata_FlowIds =
    ::protozero::proto_utils::FieldMetadata<
      47,
      ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
      ::protozero::proto_utils::ProtoSchemaType::kFixed64,
      uint64_t,
      TrackEvent>;

  static constexpr FieldMetadata_FlowIds kFlowIds{};
  void add_flow_ids(uint64_t value) {
    static constexpr uint32_t field_id = FieldMetadata_FlowIds::kFieldId;
    // Call the appropriate protozero::Message::Append(field_id, ...)
    // method based on the type of the field.
    ::protozero::internal::FieldWriter<
      ::protozero::proto_utils::ProtoSchemaType::kFixed64>
        ::Append(*this, field_id, value);
  }

  using FieldMetadata_TerminatingFlowIdsOld =
    ::protozero::proto_utils::FieldMetadata<
      42,
      ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
      ::protozero::proto_utils::ProtoSchemaType::kUint64,
      uint64_t,
      TrackEvent>;

  static constexpr FieldMetadata_TerminatingFlowIdsOld kTerminatingFlowIdsOld{};
  void add_terminating_flow_ids_old(uint64_t value) {
    static constexpr uint32_t field_id = FieldMetadata_TerminatingFlowIdsOld::kFieldId;
    // Call the appropriate protozero::Message::Append(field_id, ...)
    // method based on the type of the field.
    ::protozero::internal::FieldWriter<
      ::protozero::proto_utils::ProtoSchemaType::kUint64>
        ::Append(*this, field_id, value);
  }

  using FieldMetadata_TerminatingFlowIds =
    ::protozero::proto_utils::FieldMetadata<
      48,
      ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
      ::protozero::proto_utils::ProtoSchemaType::kFixed64,
      uint64_t,
      TrackEvent>;

  static constexpr FieldMetadata_TerminatingFlowIds kTerminatingFlowIds{};
  void add_terminating_flow_ids(uint64_t value) {
    static constexpr uint32_t field_id = FieldMetadata_TerminatingFlowIds::kFieldId;
    // Call the appropriate protozero::Message::Append(field_id, ...)
    // method based on the type of the field.
    ::protozero::internal::FieldWriter<
      ::protozero::proto_utils::ProtoSchemaType::kFixed64>
        ::Append(*this, field_id, value);
  }

  using FieldMetadata_DebugAnnotations =
    ::protozero::proto_utils::FieldMetadata<
      4,
      ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      DebugAnnotation,
      TrackEvent>;

  static constexpr FieldMetadata_DebugAnnotations kDebugAnnotations{};
  template <typename T = DebugAnnotation> T* add_debug_annotations() {
    return BeginNestedMessage<T>(4);
  }


  using FieldMetadata_TaskExecution =
    ::protozero::proto_utils::FieldMetadata<
      5,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      TaskExecution,
      TrackEvent>;

  static constexpr FieldMetadata_TaskExecution kTaskExecution{};
  template <typename T = TaskExecution> T* set_task_execution() {
    return BeginNestedMessage<T>(5);
  }


  using FieldMetadata_LogMessage =
    ::protozero::proto_utils::FieldMetadata<
      21,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      LogMessage,
      TrackEvent>;

  static constexpr FieldMetadata_LogMessage kLogMessage{};
  template <typename T = LogMessage> T* set_log_message() {
    return BeginNestedMessage<T>(21);
  }


  using FieldMetadata_CcSchedulerState =
    ::protozero::proto_utils::FieldMetadata<
      24,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      ChromeCompositorSchedulerState,
      TrackEvent>;

  static constexpr FieldMetadata_CcSchedulerState kCcSchedulerState{};
  template <typename T = ChromeCompositorSchedulerState> T* set_cc_scheduler_state() {
    return BeginNestedMessage<T>(24);
  }


  using FieldMetadata_ChromeUserEvent =
    ::protozero::proto_utils::FieldMetadata<
      25,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      ChromeUserEvent,
      TrackEvent>;

  static constexpr FieldMetadata_ChromeUserEvent kChromeUserEvent{};
  template <typename T = ChromeUserEvent> T* set_chrome_user_event() {
    return BeginNestedMessage<T>(25);
  }


  using FieldMetadata_ChromeKeyedService =
    ::protozero::proto_utils::FieldMetadata<
      26,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      ChromeKeyedService,
      TrackEvent>;

  static constexpr FieldMetadata_ChromeKeyedService kChromeKeyedService{};
  template <typename T = ChromeKeyedService> T* set_chrome_keyed_service() {
    return BeginNestedMessage<T>(26);
  }


  using FieldMetadata_ChromeLegacyIpc =
    ::protozero::proto_utils::FieldMetadata<
      27,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      ChromeLegacyIpc,
      TrackEvent>;

  static constexpr FieldMetadata_ChromeLegacyIpc kChromeLegacyIpc{};
  template <typename T = ChromeLegacyIpc> T* set_chrome_legacy_ipc() {
    return BeginNestedMessage<T>(27);
  }


  using FieldMetadata_ChromeHistogramSample =
    ::protozero::proto_utils::FieldMetadata<
      28,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      ChromeHistogramSample,
      TrackEvent>;

  static constexpr FieldMetadata_ChromeHistogramSample kChromeHistogramSample{};
  template <typename T = ChromeHistogramSample> T* set_chrome_histogram_sample() {
    return BeginNestedMessage<T>(28);
  }


  using FieldMetadata_ChromeLatencyInfo =
    ::protozero::proto_utils::FieldMetadata<
      29,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      ChromeLatencyInfo,
      TrackEvent>;

  static constexpr FieldMetadata_ChromeLatencyInfo kChromeLatencyInfo{};
  template <typename T = ChromeLatencyInfo> T* set_chrome_latency_info() {
    return BeginNestedMessage<T>(29);
  }


  using FieldMetadata_ChromeFrameReporter =
    ::protozero::proto_utils::FieldMetadata<
      32,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      ChromeFrameReporter,
      TrackEvent>;

  static constexpr FieldMetadata_ChromeFrameReporter kChromeFrameReporter{};
  template <typename T = ChromeFrameReporter> T* set_chrome_frame_reporter() {
    return BeginNestedMessage<T>(32);
  }


  using FieldMetadata_ChromeApplicationStateInfo =
    ::protozero::proto_utils::FieldMetadata<
      39,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      ChromeApplicationStateInfo,
      TrackEvent>;

  static constexpr FieldMetadata_ChromeApplicationStateInfo kChromeApplicationStateInfo{};
  template <typename T = ChromeApplicationStateInfo> T* set_chrome_application_state_info() {
    return BeginNestedMessage<T>(39);
  }


  using FieldMetadata_ChromeRendererSchedulerState =
    ::protozero::proto_utils::FieldMetadata<
      40,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      ChromeRendererSchedulerState,
      TrackEvent>;

  static constexpr FieldMetadata_ChromeRendererSchedulerState kChromeRendererSchedulerState{};
  template <typename T = ChromeRendererSchedulerState> T* set_chrome_renderer_scheduler_state() {
    return BeginNestedMessage<T>(40);
  }


  using FieldMetadata_ChromeWindowHandleEventInfo =
    ::protozero::proto_utils::FieldMetadata<
      41,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      ChromeWindowHandleEventInfo,
      TrackEvent>;

  static constexpr FieldMetadata_ChromeWindowHandleEventInfo kChromeWindowHandleEventInfo{};
  template <typename T = ChromeWindowHandleEventInfo> T* set_chrome_window_handle_event_info() {
    return BeginNestedMessage<T>(41);
  }


  using FieldMetadata_ChromeContentSettingsEventInfo =
    ::protozero::proto_utils::FieldMetadata<
      43,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      ChromeContentSettingsEventInfo,
      TrackEvent>;

  static constexpr FieldMetadata_ChromeContentSettingsEventInfo kChromeContentSettingsEventInfo{};
  template <typename T = ChromeContentSettingsEventInfo> T* set_chrome_content_settings_event_info() {
    return BeginNestedMessage<T>(43);
  }


  using FieldMetadata_ChromeActiveProcesses =
    ::protozero::proto_utils::FieldMetadata<
      49,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      ChromeActiveProcesses,
      TrackEvent>;

  static constexpr FieldMetadata_ChromeActiveProcesses kChromeActiveProcesses{};
  template <typename T = ChromeActiveProcesses> T* set_chrome_active_processes() {
    return BeginNestedMessage<T>(49);
  }


  using FieldMetadata_Screenshot =
    ::protozero::proto_utils::FieldMetadata<
      50,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      Screenshot,
      TrackEvent>;

  static constexpr FieldMetadata_Screenshot kScreenshot{};
  template <typename T = Screenshot> T* set_screenshot() {
    return BeginNestedMessage<T>(50);
  }


  using FieldMetadata_SourceLocation =
    ::protozero::proto_utils::FieldMetadata<
      33,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      SourceLocation,
      TrackEvent>;

  static constexpr FieldMetadata_SourceLocation kSourceLocation{};
  template <typename T = SourceLocation> T* set_source_location() {
    return BeginNestedMessage<T>(33);
  }


  using FieldMetadata_SourceLocationIid =
    ::protozero::proto_utils::FieldMetadata<
      34,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kUint64,
      uint64_t,
      TrackEvent>;

  static constexpr FieldMetadata_SourceLocationIid kSourceLocationIid{};
  void set_source_location_iid(uint64_t value) {
    static constexpr uint32_t field_id = FieldMetadata_SourceLocationIid::kFieldId;
    // Call the appropriate protozero::Message::Append(field_id, ...)
    // method based on the type of the field.
    ::protozero::internal::FieldWriter<
      ::protozero::proto_utils::ProtoSchemaType::kUint64>
        ::Append(*this, field_id, value);
  }

  using FieldMetadata_ChromeMessagePump =
    ::protozero::proto_utils::FieldMetadata<
      35,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      ChromeMessagePump,
      TrackEvent>;

  static constexpr FieldMetadata_ChromeMessagePump kChromeMessagePump{};
  template <typename T = ChromeMessagePump> T* set_chrome_message_pump() {
    return BeginNestedMessage<T>(35);
  }


  using FieldMetadata_ChromeMojoEventInfo =
    ::protozero::proto_utils::FieldMetadata<
      38,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      ChromeMojoEventInfo,
      TrackEvent>;

  static constexpr FieldMetadata_ChromeMojoEventInfo kChromeMojoEventInfo{};
  template <typename T = ChromeMojoEventInfo> T* set_chrome_mojo_event_info() {
    return BeginNestedMessage<T>(38);
  }


  using FieldMetadata_TimestampDeltaUs =
    ::protozero::proto_utils::FieldMetadata<
      1,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kInt64,
      int64_t,
      TrackEvent>;

  static constexpr FieldMetadata_TimestampDeltaUs kTimestampDeltaUs{};
  void set_timestamp_delta_us(int64_t value) {
    static constexpr uint32_t field_id = FieldMetadata_TimestampDeltaUs::kFieldId;
    // Call the appropriate protozero::Message::Append(field_id, ...)
    // method based on the type of the field.
    ::protozero::internal::FieldWriter<
      ::protozero::proto_utils::ProtoSchemaType::kInt64>
        ::Append(*this, field_id, value);
  }

  using FieldMetadata_TimestampAbsoluteUs =
    ::protozero::proto_utils::FieldMetadata<
      16,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kInt64,
      int64_t,
      TrackEvent>;

  static constexpr FieldMetadata_TimestampAbsoluteUs kTimestampAbsoluteUs{};
  void set_timestamp_absolute_us(int64_t value) {
    static constexpr uint32_t field_id = FieldMetadata_TimestampAbsoluteUs::kFieldId;
    // Call the appropriate protozero::Message::Append(field_id, ...)
    // method based on the type of the field.
    ::protozero::internal::FieldWriter<
      ::protozero::proto_utils::ProtoSchemaType::kInt64>
        ::Append(*this, field_id, value);
  }

  using FieldMetadata_ThreadTimeDeltaUs =
    ::protozero::proto_utils::FieldMetadata<
      2,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kInt64,
      int64_t,
      TrackEvent>;

  static constexpr FieldMetadata_ThreadTimeDeltaUs kThreadTimeDeltaUs{};
  void set_thread_time_delta_us(int64_t value) {
    static constexpr uint32_t field_id = FieldMetadata_ThreadTimeDeltaUs::kFieldId;
    // Call the appropriate protozero::Message::Append(field_id, ...)
    // method based on the type of the field.
    ::protozero::internal::FieldWriter<
      ::protozero::proto_utils::ProtoSchemaType::kInt64>
        ::Append(*this, field_id, value);
  }

  using FieldMetadata_ThreadTimeAbsoluteUs =
    ::protozero::proto_utils::FieldMetadata<
      17,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kInt64,
      int64_t,
      TrackEvent>;

  static constexpr FieldMetadata_ThreadTimeAbsoluteUs kThreadTimeAbsoluteUs{};
  void set_thread_time_absolute_us(int64_t value) {
    static constexpr uint32_t field_id = FieldMetadata_ThreadTimeAbsoluteUs::kFieldId;
    // Call the appropriate protozero::Message::Append(field_id, ...)
    // method based on the type of the field.
    ::protozero::internal::FieldWriter<
      ::protozero::proto_utils::ProtoSchemaType::kInt64>
        ::Append(*this, field_id, value);
  }

  using FieldMetadata_ThreadInstructionCountDelta =
    ::protozero::proto_utils::FieldMetadata<
      8,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kInt64,
      int64_t,
      TrackEvent>;

  static constexpr FieldMetadata_ThreadInstructionCountDelta kThreadInstructionCountDelta{};
  void set_thread_instruction_count_delta(int64_t value) {
    static constexpr uint32_t field_id = FieldMetadata_ThreadInstructionCountDelta::kFieldId;
    // Call the appropriate protozero::Message::Append(field_id, ...)
    // method based on the type of the field.
    ::protozero::internal::FieldWriter<
      ::protozero::proto_utils::ProtoSchemaType::kInt64>
        ::Append(*this, field_id, value);
  }

  using FieldMetadata_ThreadInstructionCountAbsolute =
    ::protozero::proto_utils::FieldMetadata<
      20,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kInt64,
      int64_t,
      TrackEvent>;

  static constexpr FieldMetadata_ThreadInstructionCountAbsolute kThreadInstructionCountAbsolute{};
  void set_thread_instruction_count_absolute(int64_t value) {
    static constexpr uint32_t field_id = FieldMetadata_ThreadInstructionCountAbsolute::kFieldId;
    // Call the appropriate protozero::Message::Append(field_id, ...)
    // method based on the type of the field.
    ::protozero::internal::FieldWriter<
      ::protozero::proto_utils::ProtoSchemaType::kInt64>
        ::Append(*this, field_id, value);
  }

  using FieldMetadata_LegacyEvent =
    ::protozero::proto_utils::FieldMetadata<
      6,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      TrackEvent_LegacyEvent,
      TrackEvent>;

  static constexpr FieldMetadata_LegacyEvent kLegacyEvent{};
  template <typename T = TrackEvent_LegacyEvent> T* set_legacy_event() {
    return BeginNestedMessage<T>(6);
  }

};

class TrackEvent_LegacyEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/19, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
 public:
  TrackEvent_LegacyEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
  explicit TrackEvent_LegacyEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
  explicit TrackEvent_LegacyEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
  bool has_name_iid() const { return at<1>().valid(); }
  uint64_t name_iid() const { return at<1>().as_uint64(); }
  bool has_phase() const { return at<2>().valid(); }
  int32_t phase() const { return at<2>().as_int32(); }
  bool has_duration_us() const { return at<3>().valid(); }
  int64_t duration_us() const { return at<3>().as_int64(); }
  bool has_thread_duration_us() const { return at<4>().valid(); }
  int64_t thread_duration_us() const { return at<4>().as_int64(); }
  bool has_thread_instruction_delta() const { return at<15>().valid(); }
  int64_t thread_instruction_delta() const { return at<15>().as_int64(); }
  bool has_unscoped_id() const { return at<6>().valid(); }
  uint64_t unscoped_id() const { return at<6>().as_uint64(); }
  bool has_local_id() const { return at<10>().valid(); }
  uint64_t local_id() const { return at<10>().as_uint64(); }
  bool has_global_id() const { return at<11>().valid(); }
  uint64_t global_id() const { return at<11>().as_uint64(); }
  bool has_id_scope() const { return at<7>().valid(); }
  ::protozero::ConstChars id_scope() const { return at<7>().as_string(); }
  bool has_use_async_tts() const { return at<9>().valid(); }
  bool use_async_tts() const { return at<9>().as_bool(); }
  bool has_bind_id() const { return at<8>().valid(); }
  uint64_t bind_id() const { return at<8>().as_uint64(); }
  bool has_bind_to_enclosing() const { return at<12>().valid(); }
  bool bind_to_enclosing() const { return at<12>().as_bool(); }
  bool has_flow_direction() const { return at<13>().valid(); }
  int32_t flow_direction() const { return at<13>().as_int32(); }
  bool has_instant_event_scope() const { return at<14>().valid(); }
  int32_t instant_event_scope() const { return at<14>().as_int32(); }
  bool has_pid_override() const { return at<18>().valid(); }
  int32_t pid_override() const { return at<18>().as_int32(); }
  bool has_tid_override() const { return at<19>().valid(); }
  int32_t tid_override() const { return at<19>().as_int32(); }
};

class TrackEvent_LegacyEvent : public ::protozero::Message {
 public:
  using Decoder = TrackEvent_LegacyEvent_Decoder;
  enum : int32_t {
    kNameIidFieldNumber = 1,
    kPhaseFieldNumber = 2,
    kDurationUsFieldNumber = 3,
    kThreadDurationUsFieldNumber = 4,
    kThreadInstructionDeltaFieldNumber = 15,
    kUnscopedIdFieldNumber = 6,
    kLocalIdFieldNumber = 10,
    kGlobalIdFieldNumber = 11,
    kIdScopeFieldNumber = 7,
    kUseAsyncTtsFieldNumber = 9,
    kBindIdFieldNumber = 8,
    kBindToEnclosingFieldNumber = 12,
    kFlowDirectionFieldNumber = 13,
    kInstantEventScopeFieldNumber = 14,
    kPidOverrideFieldNumber = 18,
    kTidOverrideFieldNumber = 19,
  };
  static constexpr const char* GetName() { return ".perfetto.protos.TrackEvent.LegacyEvent"; }


  using FlowDirection = ::perfetto::protos::pbzero::TrackEvent_LegacyEvent_FlowDirection;
  static inline const char* FlowDirection_Name(FlowDirection value) {
    return ::perfetto::protos::pbzero::TrackEvent_LegacyEvent_FlowDirection_Name(value);
  }

  using InstantEventScope = ::perfetto::protos::pbzero::TrackEvent_LegacyEvent_InstantEventScope;
  static inline const char* InstantEventScope_Name(InstantEventScope value) {
    return ::perfetto::protos::pbzero::TrackEvent_LegacyEvent_InstantEventScope_Name(value);
  }
  static inline const FlowDirection FLOW_UNSPECIFIED = FlowDirection::FLOW_UNSPECIFIED;
  static inline const FlowDirection FLOW_IN = FlowDirection::FLOW_IN;
  static inline const FlowDirection FLOW_OUT = FlowDirection::FLOW_OUT;
  static inline const FlowDirection FLOW_INOUT = FlowDirection::FLOW_INOUT;
  static inline const InstantEventScope SCOPE_UNSPECIFIED = InstantEventScope::SCOPE_UNSPECIFIED;
  static inline const InstantEventScope SCOPE_GLOBAL = InstantEventScope::SCOPE_GLOBAL;
  static inline const InstantEventScope SCOPE_PROCESS = InstantEventScope::SCOPE_PROCESS;
  static inline const InstantEventScope SCOPE_THREAD = InstantEventScope::SCOPE_THREAD;

  using FieldMetadata_NameIid =
    ::protozero::proto_utils::FieldMetadata<
      1,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kUint64,
      uint64_t,
      TrackEvent_LegacyEvent>;

  static constexpr FieldMetadata_NameIid kNameIid{};
  void set_name_iid(uint64_t value) {
    static constexpr uint32_t field_id = FieldMetadata_NameIid::kFieldId;
    // Call the appropriate protozero::Message::Append(field_id, ...)
    // method based on the type of the field.
    ::protozero::internal::FieldWriter<
      ::protozero::proto_utils::ProtoSchemaType::kUint64>
        ::Append(*this, field_id, value);
  }

  using FieldMetadata_Phase =
    ::protozero::proto_utils::FieldMetadata<
      2,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kInt32,
      int32_t,
      TrackEvent_LegacyEvent>;

  static constexpr FieldMetadata_Phase kPhase{};
  void set_phase(int32_t value) {
    static constexpr uint32_t field_id = FieldMetadata_Phase::kFieldId;
    // Call the appropriate protozero::Message::Append(field_id, ...)
    // method based on the type of the field.
    ::protozero::internal::FieldWriter<
      ::protozero::proto_utils::ProtoSchemaType::kInt32>
        ::Append(*this, field_id, value);
  }

  using FieldMetadata_DurationUs =
    ::protozero::proto_utils::FieldMetadata<
      3,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kInt64,
      int64_t,
      TrackEvent_LegacyEvent>;

  static constexpr FieldMetadata_DurationUs kDurationUs{};
  void set_duration_us(int64_t value) {
    static constexpr uint32_t field_id = FieldMetadata_DurationUs::kFieldId;
    // Call the appropriate protozero::Message::Append(field_id, ...)
    // method based on the type of the field.
    ::protozero::internal::FieldWriter<
      ::protozero::proto_utils::ProtoSchemaType::kInt64>
        ::Append(*this, field_id, value);
  }

  using FieldMetadata_ThreadDurationUs =
    ::protozero::proto_utils::FieldMetadata<
      4,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kInt64,
      int64_t,
      TrackEvent_LegacyEvent>;

  static constexpr FieldMetadata_ThreadDurationUs kThreadDurationUs{};
  void set_thread_duration_us(int64_t value) {
    static constexpr uint32_t field_id = FieldMetadata_ThreadDurationUs::kFieldId;
    // Call the appropriate protozero::Message::Append(field_id, ...)
    // method based on the type of the field.
    ::protozero::internal::FieldWriter<
      ::protozero::proto_utils::ProtoSchemaType::kInt64>
        ::Append(*this, field_id, value);
  }

  using FieldMetadata_ThreadInstructionDelta =
    ::protozero::proto_utils::FieldMetadata<
      15,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kInt64,
      int64_t,
      TrackEvent_LegacyEvent>;

  static constexpr FieldMetadata_ThreadInstructionDelta kThreadInstructionDelta{};
  void set_thread_instruction_delta(int64_t value) {
    static constexpr uint32_t field_id = FieldMetadata_ThreadInstructionDelta::kFieldId;
    // Call the appropriate protozero::Message::Append(field_id, ...)
    // method based on the type of the field.
    ::protozero::internal::FieldWriter<
      ::protozero::proto_utils::ProtoSchemaType::kInt64>
        ::Append(*this, field_id, value);
  }

  using FieldMetadata_UnscopedId =
    ::protozero::proto_utils::FieldMetadata<
      6,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kUint64,
      uint64_t,
      TrackEvent_LegacyEvent>;

  static constexpr FieldMetadata_UnscopedId kUnscopedId{};
  void set_unscoped_id(uint64_t value) {
    static constexpr uint32_t field_id = FieldMetadata_UnscopedId::kFieldId;
    // Call the appropriate protozero::Message::Append(field_id, ...)
    // method based on the type of the field.
    ::protozero::internal::FieldWriter<
      ::protozero::proto_utils::ProtoSchemaType::kUint64>
        ::Append(*this, field_id, value);
  }

  using FieldMetadata_LocalId =
    ::protozero::proto_utils::FieldMetadata<
      10,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kUint64,
      uint64_t,
      TrackEvent_LegacyEvent>;

  static constexpr FieldMetadata_LocalId kLocalId{};
  void set_local_id(uint64_t value) {
    static constexpr uint32_t field_id = FieldMetadata_LocalId::kFieldId;
    // Call the appropriate protozero::Message::Append(field_id, ...)
    // method based on the type of the field.
    ::protozero::internal::FieldWriter<
      ::protozero::proto_utils::ProtoSchemaType::kUint64>
        ::Append(*this, field_id, value);
  }

  using FieldMetadata_GlobalId =
    ::protozero::proto_utils::FieldMetadata<
      11,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kUint64,
      uint64_t,
      TrackEvent_LegacyEvent>;

  static constexpr FieldMetadata_GlobalId kGlobalId{};
  void set_global_id(uint64_t value) {
    static constexpr uint32_t field_id = FieldMetadata_GlobalId::kFieldId;
    // Call the appropriate protozero::Message::Append(field_id, ...)
    // method based on the type of the field.
    ::protozero::internal::FieldWriter<
      ::protozero::proto_utils::ProtoSchemaType::kUint64>
        ::Append(*this, field_id, value);
  }

  using FieldMetadata_IdScope =
    ::protozero::proto_utils::FieldMetadata<
      7,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kString,
      std::string,
      TrackEvent_LegacyEvent>;

  static constexpr FieldMetadata_IdScope kIdScope{};
  void set_id_scope(const char* data, size_t size) {
    AppendBytes(FieldMetadata_IdScope::kFieldId, data, size);
  }
  void set_id_scope(::protozero::ConstChars chars) {
    AppendBytes(FieldMetadata_IdScope::kFieldId, chars.data, chars.size);
  }
  void set_id_scope(std::string value) {
    static constexpr uint32_t field_id = FieldMetadata_IdScope::kFieldId;
    // Call the appropriate protozero::Message::Append(field_id, ...)
    // method based on the type of the field.
    ::protozero::internal::FieldWriter<
      ::protozero::proto_utils::ProtoSchemaType::kString>
        ::Append(*this, field_id, value);
  }

  using FieldMetadata_UseAsyncTts =
    ::protozero::proto_utils::FieldMetadata<
      9,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kBool,
      bool,
      TrackEvent_LegacyEvent>;

  static constexpr FieldMetadata_UseAsyncTts kUseAsyncTts{};
  void set_use_async_tts(bool value) {
    static constexpr uint32_t field_id = FieldMetadata_UseAsyncTts::kFieldId;
    // Call the appropriate protozero::Message::Append(field_id, ...)
    // method based on the type of the field.
    ::protozero::internal::FieldWriter<
      ::protozero::proto_utils::ProtoSchemaType::kBool>
        ::Append(*this, field_id, value);
  }

  using FieldMetadata_BindId =
    ::protozero::proto_utils::FieldMetadata<
      8,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kUint64,
      uint64_t,
      TrackEvent_LegacyEvent>;

  static constexpr FieldMetadata_BindId kBindId{};
  void set_bind_id(uint64_t value) {
    static constexpr uint32_t field_id = FieldMetadata_BindId::kFieldId;
    // Call the appropriate protozero::Message::Append(field_id, ...)
    // method based on the type of the field.
    ::protozero::internal::FieldWriter<
      ::protozero::proto_utils::ProtoSchemaType::kUint64>
        ::Append(*this, field_id, value);
  }

  using FieldMetadata_BindToEnclosing =
    ::protozero::proto_utils::FieldMetadata<
      12,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kBool,
      bool,
      TrackEvent_LegacyEvent>;

  static constexpr FieldMetadata_BindToEnclosing kBindToEnclosing{};
  void set_bind_to_enclosing(bool value) {
    static constexpr uint32_t field_id = FieldMetadata_BindToEnclosing::kFieldId;
    // Call the appropriate protozero::Message::Append(field_id, ...)
    // method based on the type of the field.
    ::protozero::internal::FieldWriter<
      ::protozero::proto_utils::ProtoSchemaType::kBool>
        ::Append(*this, field_id, value);
  }

  using FieldMetadata_FlowDirection =
    ::protozero::proto_utils::FieldMetadata<
      13,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kEnum,
      TrackEvent_LegacyEvent_FlowDirection,
      TrackEvent_LegacyEvent>;

  static constexpr FieldMetadata_FlowDirection kFlowDirection{};
  void set_flow_direction(TrackEvent_LegacyEvent_FlowDirection value) {
    static constexpr uint32_t field_id = FieldMetadata_FlowDirection::kFieldId;
    // Call the appropriate protozero::Message::Append(field_id, ...)
    // method based on the type of the field.
    ::protozero::internal::FieldWriter<
      ::protozero::proto_utils::ProtoSchemaType::kEnum>
        ::Append(*this, field_id, value);
  }

  using FieldMetadata_InstantEventScope =
    ::protozero::proto_utils::FieldMetadata<
      14,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kEnum,
      TrackEvent_LegacyEvent_InstantEventScope,
      TrackEvent_LegacyEvent>;

  static constexpr FieldMetadata_InstantEventScope kInstantEventScope{};
  void set_instant_event_scope(TrackEvent_LegacyEvent_InstantEventScope value) {
    static constexpr uint32_t field_id = FieldMetadata_InstantEventScope::kFieldId;
    // Call the appropriate protozero::Message::Append(field_id, ...)
    // method based on the type of the field.
    ::protozero::internal::FieldWriter<
      ::protozero::proto_utils::ProtoSchemaType::kEnum>
        ::Append(*this, field_id, value);
  }

  using FieldMetadata_PidOverride =
    ::protozero::proto_utils::FieldMetadata<
      18,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kInt32,
      int32_t,
      TrackEvent_LegacyEvent>;

  static constexpr FieldMetadata_PidOverride kPidOverride{};
  void set_pid_override(int32_t value) {
    static constexpr uint32_t field_id = FieldMetadata_PidOverride::kFieldId;
    // Call the appropriate protozero::Message::Append(field_id, ...)
    // method based on the type of the field.
    ::protozero::internal::FieldWriter<
      ::protozero::proto_utils::ProtoSchemaType::kInt32>
        ::Append(*this, field_id, value);
  }

  using FieldMetadata_TidOverride =
    ::protozero::proto_utils::FieldMetadata<
      19,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kInt32,
      int32_t,
      TrackEvent_LegacyEvent>;

  static constexpr FieldMetadata_TidOverride kTidOverride{};
  void set_tid_override(int32_t value) {
    static constexpr uint32_t field_id = FieldMetadata_TidOverride::kFieldId;
    // Call the appropriate protozero::Message::Append(field_id, ...)
    // method based on the type of the field.
    ::protozero::internal::FieldWriter<
      ::protozero::proto_utils::ProtoSchemaType::kInt32>
        ::Append(*this, field_id, value);
  }
};

// Namespace.
// Namespace.
// Namespace.
#endif  // Include guard.
/*
 * Copyright (C) 2020 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.
 */


#ifndef INCLUDE_PERFETTO_TRACING_TRACK_EVENT_STATE_TRACKER_H_
#define INCLUDE_PERFETTO_TRACING_TRACK_EVENT_STATE_TRACKER_H_

// gen_amalgamated expanded: #include "perfetto/base/export.h"

// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/track_event.pbzero.h"

#include <map>
#include <string>
#include <vector>

namespace perfetto {
namespace protos {
namespace pbzero {
class TracePacket_Decoder;
class TrackEvent;
class TrackEvent_Decoder;
}  // namespace pbzero
}  // namespace protos

// A helper for keeping track of incremental state when intercepting track
// events.
class PERFETTO_EXPORT_COMPONENT TrackEventStateTracker {
 public:
  ~TrackEventStateTracker();

  struct StackFrame {
    uint64_t timestamp{};

    // Only one of |name| and |name_iid| will be set.
    std::string name;
    uint64_t name_iid{};
    uint64_t name_hash{};

    // Only one of |category| and |category_iid| will be set.
    std::string category;
    uint64_t category_iid{};
  };

  struct Track {
    uint64_t uuid{};
    uint32_t index{};  // Ordinal number for the track in the tracing session.

    std::string name;
    int64_t pid{};
    int64_t tid{};

    // Opaque user data associated with the track.
    std::vector<uint8_t> user_data;

    // Stack of opened slices on this track.
    std::vector<StackFrame> stack;
  };

  // State for a single trace writer sequence (typically a single thread).
  struct SequenceState {
    // Trace packet sequence defaults.
    Track track;

    // Interned state.
#if PERFETTO_DCHECK_IS_ON()
    uint32_t sequence_id{};
#endif
    std::map<uint64_t /*iid*/, std::string> event_names;
    std::map<uint64_t /*iid*/, std::string> event_categories;
    std::map<uint64_t /*iid*/, std::string> debug_annotation_names;
    // Current absolute timestamp of the incremental clock.
    uint64_t most_recent_absolute_time_ns = 0;
    // default_clock_id == 0 means, no default clock_id is set.
    uint32_t default_clock_id = 0;
  };

  // State for the entire tracing session. Shared by all trace writer sequences
  // participating in the session.
  struct SessionState {
    // Non-thread-bound tracks.
    std::map<uint64_t /*uuid*/, Track> tracks;
  };

  // Represents a single decoded track event (without arguments).
  struct ParsedTrackEvent {
    explicit ParsedTrackEvent(
        const perfetto::protos::pbzero::TrackEvent::Decoder&);

    // Underlying event.
    const perfetto::protos::pbzero::TrackEvent::Decoder& track_event;

    // Event metadata.
    uint64_t timestamp_ns{};
    uint64_t duration_ns{};

    size_t stack_depth{};

    protozero::ConstChars category{};
    protozero::ConstChars name{};
    uint64_t name_hash{};
  };

  // Interface used by the tracker to access tracing session and sequence state
  // and to report parsed track events.
  class PERFETTO_EXPORT_COMPONENT Delegate {
   public:
    virtual ~Delegate();

    // Called to retrieve the session-global state shared by all sequences. The
    // returned pointer must remain valid (locked) throughout the call to
    // |ProcessTracePacket|.
    virtual SessionState* GetSessionState() = 0;

    // Called when the metadata (e.g., name) for a track changes. |Track| can be
    // modified by the callback to attach user data.
    virtual void OnTrackUpdated(Track&) = 0;

    // If the packet given to |ProcessTracePacket| contains a track event, this
    // method is called to report the properties of that event. Note that memory
    // pointers in |TrackEvent| will only be valid during this call.
    virtual void OnTrackEvent(const Track&, const ParsedTrackEvent&) = 0;
  };

  // Process a single trace packet, reporting any contained track event back via
  // the delegate interface. |SequenceState| must correspond to the sequence
  // that was used to write the packet.
  static void ProcessTracePacket(Delegate&,
                                 SequenceState&,
                                 const protos::pbzero::TracePacket_Decoder&);

 private:
  static void UpdateIncrementalState(
      Delegate&,
      SequenceState&,
      const protos::pbzero::TracePacket_Decoder&);
};

}  // namespace perfetto

#endif  // INCLUDE_PERFETTO_TRACING_TRACK_EVENT_STATE_TRACKER_H_
/*
 * Copyright (C) 2020 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.
 */


#ifndef INCLUDE_PERFETTO_TRACING_CONSOLE_INTERCEPTOR_H_
#define INCLUDE_PERFETTO_TRACING_CONSOLE_INTERCEPTOR_H_

// gen_amalgamated expanded: #include "perfetto/base/compiler.h"
// gen_amalgamated expanded: #include "perfetto/base/logging.h"
// gen_amalgamated expanded: #include "perfetto/tracing/interceptor.h"
// gen_amalgamated expanded: #include "perfetto/tracing/track_event_state_tracker.h"

#include <stdarg.h>

#include <functional>
#include <map>
#include <vector>

#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
#include <io.h>
#else
#include <unistd.h>
#endif

#if defined(__GNUC__) || defined(__clang__)
#define PERFETTO_PRINTF_ATTR \
  __attribute__((format(printf, /*format_index=*/2, /*first_to_check=*/3)))
#else
#define PERFETTO_PRINTF_ATTR
#endif

#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) && !defined(STDOUT_FILENO)
#define STDOUT_FILENO 1
#define STDERR_FILENO 2
#endif

namespace perfetto {
namespace protos {
namespace pbzero {
class DebugAnnotation_Decoder;
class TracePacket_Decoder;
class TrackEvent_Decoder;
}  // namespace pbzero
}  // namespace protos

struct ConsoleColor;

class PERFETTO_EXPORT_COMPONENT ConsoleInterceptor
    : public Interceptor<ConsoleInterceptor> {
 public:
  ~ConsoleInterceptor() override;

  static void Register();
  static void OnTracePacket(InterceptorContext context);

  static void SetOutputFdForTesting(int fd);

  void OnSetup(const SetupArgs&) override;
  void OnStart(const StartArgs&) override;
  void OnStop(const StopArgs&) override;

  struct ThreadLocalState : public InterceptorBase::ThreadLocalState {
    ThreadLocalState(ThreadLocalStateArgs&);
    ~ThreadLocalState() override;

    // Destination file. Assumed to stay valid until the program ends (i.e., is
    // stderr or stdout).
    int fd{};
    bool use_colors{};

    // Messages up to this length are buffered and written atomically. If a
    // message is longer, it will be printed with multiple writes.
    std::array<char, 1024> message_buffer{};
    size_t buffer_pos{};

    // We only support a single trace writer sequence per thread, so the
    // sequence state is stored in TLS.
    TrackEventStateTracker::SequenceState sequence_state;
    uint64_t start_time_ns{};
  };

 private:
  class Delegate;

  // Appends a formatted message to |message_buffer_| or directly to the output
  // file if the buffer is full.
  static void Printf(InterceptorContext& context,
                     const char* format,
                     ...) PERFETTO_PRINTF_ATTR;
  static void Flush(InterceptorContext& context);
  static void SetColor(InterceptorContext& context, const ConsoleColor&);
  static void SetColor(InterceptorContext& context, const char*);

  static void PrintDebugAnnotations(InterceptorContext&,
                                    const protos::pbzero::TrackEvent_Decoder&,
                                    const ConsoleColor& slice_color,
                                    const ConsoleColor& highlight_color);
  static void PrintDebugAnnotationName(
      InterceptorContext&,
      const perfetto::protos::pbzero::DebugAnnotation_Decoder& annotation);
  static void PrintDebugAnnotationValue(
      InterceptorContext&,
      const perfetto::protos::pbzero::DebugAnnotation_Decoder& annotation);

  int fd_ = STDOUT_FILENO;
  bool use_colors_ = true;

  TrackEventStateTracker::SessionState session_state_;
  uint64_t start_time_ns_{};
};

}  // namespace perfetto

#endif  // INCLUDE_PERFETTO_TRACING_CONSOLE_INTERCEPTOR_H_
// gen_amalgamated begin header: include/perfetto/tracing/core/data_source_descriptor.h
// gen_amalgamated begin header: gen/protos/perfetto/common/data_source_descriptor.gen.h
// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_DATA_SOURCE_DESCRIPTOR_PROTO_CPP_H_
#define PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_DATA_SOURCE_DESCRIPTOR_PROTO_CPP_H_

#include <stdint.h>
#include <bitset>
#include <vector>
#include <string>
#include <type_traits>

// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
// gen_amalgamated expanded: #include "perfetto/base/export.h"

namespace perfetto {
namespace protos {
namespace gen {
class DataSourceDescriptor;
}  // namespace perfetto
}  // namespace protos
}  // namespace gen

namespace protozero {
class Message;
}  // namespace protozero

namespace perfetto {
namespace protos {
namespace gen {

class PERFETTO_EXPORT_COMPONENT DataSourceDescriptor : public ::protozero::CppMessageObj {
 public:
  enum FieldNumbers {
    kNameFieldNumber = 1,
    kIdFieldNumber = 7,
    kWillNotifyOnStopFieldNumber = 2,
    kWillNotifyOnStartFieldNumber = 3,
    kHandlesIncrementalStateClearFieldNumber = 4,
    kNoFlushFieldNumber = 9,
    kGpuCounterDescriptorFieldNumber = 5,
    kTrackEventDescriptorFieldNumber = 6,
    kFtraceDescriptorFieldNumber = 8,
  };

  DataSourceDescriptor();
  ~DataSourceDescriptor() override;
  DataSourceDescriptor(DataSourceDescriptor&&) noexcept;
  DataSourceDescriptor& operator=(DataSourceDescriptor&&);
  DataSourceDescriptor(const DataSourceDescriptor&);
  DataSourceDescriptor& operator=(const DataSourceDescriptor&);
  bool operator==(const DataSourceDescriptor&) const;
  bool operator!=(const DataSourceDescriptor& other) const { return !(*this == other); }

  bool ParseFromArray(const void*, size_t) override;
  std::string SerializeAsString() const override;
  std::vector<uint8_t> SerializeAsArray() const override;
  void Serialize(::protozero::Message*) const;

  bool has_name() const { return _has_field_[1]; }
  const std::string& name() const { return name_; }
  void set_name(const std::string& value) { name_ = value; _has_field_.set(1); }

  bool has_id() const { return _has_field_[7]; }
  uint64_t id() const { return id_; }
  void set_id(uint64_t value) { id_ = value; _has_field_.set(7); }

  bool has_will_notify_on_stop() const { return _has_field_[2]; }
  bool will_notify_on_stop() const { return will_notify_on_stop_; }
  void set_will_notify_on_stop(bool value) { will_notify_on_stop_ = value; _has_field_.set(2); }

  bool has_will_notify_on_start() const { return _has_field_[3]; }
  bool will_notify_on_start() const { return will_notify_on_start_; }
  void set_will_notify_on_start(bool value) { will_notify_on_start_ = value; _has_field_.set(3); }

  bool has_handles_incremental_state_clear() const { return _has_field_[4]; }
  bool handles_incremental_state_clear() const { return handles_incremental_state_clear_; }
  void set_handles_incremental_state_clear(bool value) { handles_incremental_state_clear_ = value; _has_field_.set(4); }

  bool has_no_flush() const { return _has_field_[9]; }
  bool no_flush() const { return no_flush_; }
  void set_no_flush(bool value) { no_flush_ = value; _has_field_.set(9); }

  const std::string& gpu_counter_descriptor_raw() const { return gpu_counter_descriptor_; }
  void set_gpu_counter_descriptor_raw(const std::string& raw) { gpu_counter_descriptor_ = raw; _has_field_.set(5); }

  const std::string& track_event_descriptor_raw() const { return track_event_descriptor_; }
  void set_track_event_descriptor_raw(const std::string& raw) { track_event_descriptor_ = raw; _has_field_.set(6); }

  const std::string& ftrace_descriptor_raw() const { return ftrace_descriptor_; }
  void set_ftrace_descriptor_raw(const std::string& raw) { ftrace_descriptor_ = raw; _has_field_.set(8); }

 private:
  std::string name_{};
  uint64_t id_{};
  bool will_notify_on_stop_{};
  bool will_notify_on_start_{};
  bool handles_incremental_state_clear_{};
  bool no_flush_{};
  std::string gpu_counter_descriptor_;  // [lazy=true]
  std::string track_event_descriptor_;  // [lazy=true]
  std::string ftrace_descriptor_;  // [lazy=true]

  // Allows to preserve unknown protobuf fields for compatibility
  // with future versions of .proto files.
  std::string unknown_fields_;

  std::bitset<10> _has_field_{};
};

}  // namespace perfetto
}  // namespace protos
}  // namespace gen

#endif  // PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_DATA_SOURCE_DESCRIPTOR_PROTO_CPP_H_
/*
 * 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.
 */


#ifndef INCLUDE_PERFETTO_TRACING_CORE_DATA_SOURCE_DESCRIPTOR_H_
#define INCLUDE_PERFETTO_TRACING_CORE_DATA_SOURCE_DESCRIPTOR_H_

// Creates the aliases in the ::perfetto namespace, doing things like:
// using ::perfetto::Foo = ::perfetto::protos::gen::Foo.
// See comments in forward_decls.h for the historical reasons of this
// indirection layer.
// gen_amalgamated expanded: #include "perfetto/tracing/core/forward_decls.h"

// gen_amalgamated expanded: #include "protos/perfetto/common/data_source_descriptor.gen.h"

#endif  // INCLUDE_PERFETTO_TRACING_CORE_DATA_SOURCE_DESCRIPTOR_H_
// gen_amalgamated begin header: include/perfetto/tracing/core/trace_config.h
// gen_amalgamated begin header: gen/protos/perfetto/config/trace_config.gen.h
// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_TRACE_CONFIG_PROTO_CPP_H_
#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_TRACE_CONFIG_PROTO_CPP_H_

#include <stdint.h>
#include <bitset>
#include <vector>
#include <string>
#include <type_traits>

// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
// gen_amalgamated expanded: #include "perfetto/base/export.h"

namespace perfetto {
namespace protos {
namespace gen {
class TraceConfig;
class TraceConfig_SessionSemaphore;
class TraceConfig_CmdTraceStartDelay;
class TraceConfig_AndroidReportConfig;
class TraceConfig_TraceFilter;
class TraceConfig_TraceFilter_StringFilterChain;
class TraceConfig_TraceFilter_StringFilterRule;
class TraceConfig_IncidentReportConfig;
class TraceConfig_IncrementalStateConfig;
class TraceConfig_TriggerConfig;
class TraceConfig_TriggerConfig_Trigger;
class TraceConfig_GuardrailOverrides;
class TraceConfig_StatsdMetadata;
class TraceConfig_ProducerConfig;
class TraceConfig_BuiltinDataSource;
class TraceConfig_DataSource;
class DataSourceConfig;
class TestConfig;
class TestConfig_DummyFields;
class InterceptorConfig;
class ConsoleConfig;
class ChromeConfig;
class SystemInfoConfig;
class TraceConfig_BufferConfig;
enum TraceConfig_LockdownModeOperation : int;
enum TraceConfig_CompressionType : int;
enum TraceConfig_StatsdLogging : int;
enum TraceConfig_TraceFilter_StringFilterPolicy : int;
enum TraceConfig_TriggerConfig_TriggerMode : int;
enum BuiltinClock : int;
enum DataSourceConfig_SessionInitiator : int;
enum ConsoleConfig_Output : int;
enum ChromeConfig_ClientPriority : int;
enum TraceConfig_BufferConfig_FillPolicy : int;
}  // namespace perfetto
}  // namespace protos
}  // namespace gen

namespace protozero {
class Message;
}  // namespace protozero

namespace perfetto {
namespace protos {
namespace gen {
enum TraceConfig_LockdownModeOperation : int {
  TraceConfig_LockdownModeOperation_LOCKDOWN_UNCHANGED = 0,
  TraceConfig_LockdownModeOperation_LOCKDOWN_CLEAR = 1,
  TraceConfig_LockdownModeOperation_LOCKDOWN_SET = 2,
};
enum TraceConfig_CompressionType : int {
  TraceConfig_CompressionType_COMPRESSION_TYPE_UNSPECIFIED = 0,
  TraceConfig_CompressionType_COMPRESSION_TYPE_DEFLATE = 1,
};
enum TraceConfig_StatsdLogging : int {
  TraceConfig_StatsdLogging_STATSD_LOGGING_UNSPECIFIED = 0,
  TraceConfig_StatsdLogging_STATSD_LOGGING_ENABLED = 1,
  TraceConfig_StatsdLogging_STATSD_LOGGING_DISABLED = 2,
};
enum TraceConfig_TraceFilter_StringFilterPolicy : int {
  TraceConfig_TraceFilter_StringFilterPolicy_SFP_UNSPECIFIED = 0,
  TraceConfig_TraceFilter_StringFilterPolicy_SFP_MATCH_REDACT_GROUPS = 1,
  TraceConfig_TraceFilter_StringFilterPolicy_SFP_ATRACE_MATCH_REDACT_GROUPS = 2,
  TraceConfig_TraceFilter_StringFilterPolicy_SFP_MATCH_BREAK = 3,
  TraceConfig_TraceFilter_StringFilterPolicy_SFP_ATRACE_MATCH_BREAK = 4,
  TraceConfig_TraceFilter_StringFilterPolicy_SFP_ATRACE_REPEATED_SEARCH_REDACT_GROUPS = 5,
};
enum TraceConfig_TriggerConfig_TriggerMode : int {
  TraceConfig_TriggerConfig_TriggerMode_UNSPECIFIED = 0,
  TraceConfig_TriggerConfig_TriggerMode_START_TRACING = 1,
  TraceConfig_TriggerConfig_TriggerMode_STOP_TRACING = 2,
  TraceConfig_TriggerConfig_TriggerMode_CLONE_SNAPSHOT = 4,
};
enum TraceConfig_BufferConfig_FillPolicy : int {
  TraceConfig_BufferConfig_FillPolicy_UNSPECIFIED = 0,
  TraceConfig_BufferConfig_FillPolicy_RING_BUFFER = 1,
  TraceConfig_BufferConfig_FillPolicy_DISCARD = 2,
};

class PERFETTO_EXPORT_COMPONENT TraceConfig : public ::protozero::CppMessageObj {
 public:
  using BufferConfig = TraceConfig_BufferConfig;
  using DataSource = TraceConfig_DataSource;
  using BuiltinDataSource = TraceConfig_BuiltinDataSource;
  using ProducerConfig = TraceConfig_ProducerConfig;
  using StatsdMetadata = TraceConfig_StatsdMetadata;
  using GuardrailOverrides = TraceConfig_GuardrailOverrides;
  using TriggerConfig = TraceConfig_TriggerConfig;
  using IncrementalStateConfig = TraceConfig_IncrementalStateConfig;
  using IncidentReportConfig = TraceConfig_IncidentReportConfig;
  using TraceFilter = TraceConfig_TraceFilter;
  using AndroidReportConfig = TraceConfig_AndroidReportConfig;
  using CmdTraceStartDelay = TraceConfig_CmdTraceStartDelay;
  using SessionSemaphore = TraceConfig_SessionSemaphore;
  using LockdownModeOperation = TraceConfig_LockdownModeOperation;
  static constexpr auto LOCKDOWN_UNCHANGED = TraceConfig_LockdownModeOperation_LOCKDOWN_UNCHANGED;
  static constexpr auto LOCKDOWN_CLEAR = TraceConfig_LockdownModeOperation_LOCKDOWN_CLEAR;
  static constexpr auto LOCKDOWN_SET = TraceConfig_LockdownModeOperation_LOCKDOWN_SET;
  static constexpr auto LockdownModeOperation_MIN = TraceConfig_LockdownModeOperation_LOCKDOWN_UNCHANGED;
  static constexpr auto LockdownModeOperation_MAX = TraceConfig_LockdownModeOperation_LOCKDOWN_SET;
  using CompressionType = TraceConfig_CompressionType;
  static constexpr auto COMPRESSION_TYPE_UNSPECIFIED = TraceConfig_CompressionType_COMPRESSION_TYPE_UNSPECIFIED;
  static constexpr auto COMPRESSION_TYPE_DEFLATE = TraceConfig_CompressionType_COMPRESSION_TYPE_DEFLATE;
  static constexpr auto CompressionType_MIN = TraceConfig_CompressionType_COMPRESSION_TYPE_UNSPECIFIED;
  static constexpr auto CompressionType_MAX = TraceConfig_CompressionType_COMPRESSION_TYPE_DEFLATE;
  using StatsdLogging = TraceConfig_StatsdLogging;
  static constexpr auto STATSD_LOGGING_UNSPECIFIED = TraceConfig_StatsdLogging_STATSD_LOGGING_UNSPECIFIED;
  static constexpr auto STATSD_LOGGING_ENABLED = TraceConfig_StatsdLogging_STATSD_LOGGING_ENABLED;
  static constexpr auto STATSD_LOGGING_DISABLED = TraceConfig_StatsdLogging_STATSD_LOGGING_DISABLED;
  static constexpr auto StatsdLogging_MIN = TraceConfig_StatsdLogging_STATSD_LOGGING_UNSPECIFIED;
  static constexpr auto StatsdLogging_MAX = TraceConfig_StatsdLogging_STATSD_LOGGING_DISABLED;
  enum FieldNumbers {
    kBuffersFieldNumber = 1,
    kDataSourcesFieldNumber = 2,
    kBuiltinDataSourcesFieldNumber = 20,
    kDurationMsFieldNumber = 3,
    kPreferSuspendClockForDurationFieldNumber = 36,
    kEnableExtraGuardrailsFieldNumber = 4,
    kLockdownModeFieldNumber = 5,
    kProducersFieldNumber = 6,
    kStatsdMetadataFieldNumber = 7,
    kWriteIntoFileFieldNumber = 8,
    kOutputPathFieldNumber = 29,
    kFileWritePeriodMsFieldNumber = 9,
    kMaxFileSizeBytesFieldNumber = 10,
    kGuardrailOverridesFieldNumber = 11,
    kDeferredStartFieldNumber = 12,
    kFlushPeriodMsFieldNumber = 13,
    kFlushTimeoutMsFieldNumber = 14,
    kDataSourceStopTimeoutMsFieldNumber = 23,
    kNotifyTraceurFieldNumber = 16,
    kBugreportScoreFieldNumber = 30,
    kBugreportFilenameFieldNumber = 38,
    kTriggerConfigFieldNumber = 17,
    kActivateTriggersFieldNumber = 18,
    kIncrementalStateConfigFieldNumber = 21,
    kAllowUserBuildTracingFieldNumber = 19,
    kUniqueSessionNameFieldNumber = 22,
    kCompressionTypeFieldNumber = 24,
    kIncidentReportConfigFieldNumber = 25,
    kStatsdLoggingFieldNumber = 31,
    kTraceUuidMsbFieldNumber = 27,
    kTraceUuidLsbFieldNumber = 28,
    kTraceFilterFieldNumber = 33,
    kAndroidReportConfigFieldNumber = 34,
    kCmdTraceStartDelayFieldNumber = 35,
    kSessionSemaphoresFieldNumber = 39,
  };

  TraceConfig();
  ~TraceConfig() override;
  TraceConfig(TraceConfig&&) noexcept;
  TraceConfig& operator=(TraceConfig&&);
  TraceConfig(const TraceConfig&);
  TraceConfig& operator=(const TraceConfig&);
  bool operator==(const TraceConfig&) const;
  bool operator!=(const TraceConfig& other) const { return !(*this == other); }

  bool ParseFromArray(const void*, size_t) override;
  std::string SerializeAsString() const override;
  std::vector<uint8_t> SerializeAsArray() const override;
  void Serialize(::protozero::Message*) const;

  const std::vector<TraceConfig_BufferConfig>& buffers() const { return buffers_; }
  std::vector<TraceConfig_BufferConfig>* mutable_buffers() { return &buffers_; }
  int buffers_size() const;
  void clear_buffers();
  TraceConfig_BufferConfig* add_buffers();

  const std::vector<TraceConfig_DataSource>& data_sources() const { return data_sources_; }
  std::vector<TraceConfig_DataSource>* mutable_data_sources() { return &data_sources_; }
  int data_sources_size() const;
  void clear_data_sources();
  TraceConfig_DataSource* add_data_sources();

  bool has_builtin_data_sources() const { return _has_field_[20]; }
  const TraceConfig_BuiltinDataSource& builtin_data_sources() const { return *builtin_data_sources_; }
  TraceConfig_BuiltinDataSource* mutable_builtin_data_sources() { _has_field_.set(20)return builtin_data_sources_.get(); }

  bool has_duration_ms() const { return _has_field_[3]; }
  uint32_t duration_ms() const { return duration_ms_; }
  void set_duration_ms(uint32_t value) { duration_ms_ = value; _has_field_.set(3); }

  bool has_prefer_suspend_clock_for_duration() const { return _has_field_[36]; }
  bool prefer_suspend_clock_for_duration() const { return prefer_suspend_clock_for_duration_; }
  void set_prefer_suspend_clock_for_duration(bool value) { prefer_suspend_clock_for_duration_ = value; _has_field_.set(36); }

  bool has_enable_extra_guardrails() const { return _has_field_[4]; }
  bool enable_extra_guardrails() const { return enable_extra_guardrails_; }
  void set_enable_extra_guardrails(bool value) { enable_extra_guardrails_ = value; _has_field_.set(4); }

  bool has_lockdown_mode() const { return _has_field_[5]; }
  TraceConfig_LockdownModeOperation lockdown_mode() const { return lockdown_mode_; }
  void set_lockdown_mode(TraceConfig_LockdownModeOperation value) { lockdown_mode_ = value; _has_field_.set(5); }

  const std::vector<TraceConfig_ProducerConfig>& producers() const { return producers_; }
  std::vector<TraceConfig_ProducerConfig>* mutable_producers() { return &producers_; }
  int producers_size() const;
  void clear_producers();
  TraceConfig_ProducerConfig* add_producers();

  bool has_statsd_metadata() const { return _has_field_[7]; }
  const TraceConfig_StatsdMetadata& statsd_metadata() const { return *statsd_metadata_; }
  TraceConfig_StatsdMetadata* mutable_statsd_metadata() { _has_field_.set(7); return statsd_metadata_.get(); }

  bool has_write_into_file() const { return _has_field_[8]; }
  bool write_into_file() const { return write_into_file_; }
  void set_write_into_file(bool value) { write_into_file_ = value; _has_field_.set(8); }

  bool has_output_path() const { return _has_field_[29]; }
  const std::string& output_path() const { return output_path_; }
  void set_output_path(const std::string& value) { output_path_ = value; _has_field_.set(29); }

  bool has_file_write_period_ms() const { return _has_field_[9]; }
  uint32_t file_write_period_ms() const { return file_write_period_ms_; }
  void set_file_write_period_ms(uint32_t value) { file_write_period_ms_ = value; _has_field_.set(9); }

  bool has_max_file_size_bytes() const { return _has_field_[10]; }
  uint64_t max_file_size_bytes() const { return max_file_size_bytes_; }
  void set_max_file_size_bytes(uint64_t value) { max_file_size_bytes_ = value; _has_field_.set(10); }

  bool has_guardrail_overrides() const { return _has_field_[11]; }
  const TraceConfig_GuardrailOverrides& guardrail_overrides() const { return *guardrail_overrides_; }
  TraceConfig_GuardrailOverrides* mutable_guardrail_overrides() { _has_field_.set(11)return guardrail_overrides_.get(); }

  bool has_deferred_start() const { return _has_field_[12]; }
  bool deferred_start() const { return deferred_start_; }
  void set_deferred_start(bool value) { deferred_start_ = value; _has_field_.set(12); }

  bool has_flush_period_ms() const { return _has_field_[13]; }
  uint32_t flush_period_ms() const { return flush_period_ms_; }
  void set_flush_period_ms(uint32_t value) { flush_period_ms_ = value; _has_field_.set(13); }

  bool has_flush_timeout_ms() const { return _has_field_[14]; }
  uint32_t flush_timeout_ms() const { return flush_timeout_ms_; }
  void set_flush_timeout_ms(uint32_t value) { flush_timeout_ms_ = value; _has_field_.set(14); }

  bool has_data_source_stop_timeout_ms() const { return _has_field_[23]; }
  uint32_t data_source_stop_timeout_ms() const { return data_source_stop_timeout_ms_; }
  void set_data_source_stop_timeout_ms(uint32_t value) { data_source_stop_timeout_ms_ = value; _has_field_.set(23); }

  bool has_notify_traceur() const { return _has_field_[16]; }
  bool notify_traceur() const { return notify_traceur_; }
  void set_notify_traceur(bool value) { notify_traceur_ = value; _has_field_.set(16); }

  bool has_bugreport_score() const { return _has_field_[30]; }
  int32_t bugreport_score() const { return bugreport_score_; }
  void set_bugreport_score(int32_t value) { bugreport_score_ = value; _has_field_.set(30); }

  bool has_bugreport_filename() const { return _has_field_[38]; }
  const std::string& bugreport_filename() const { return bugreport_filename_; }
  void set_bugreport_filename(const std::string& value) { bugreport_filename_ = value; _has_field_.set(38); }

  bool has_trigger_config() const { return _has_field_[17]; }
  const TraceConfig_TriggerConfig& trigger_config() const { return *trigger_config_; }
  TraceConfig_TriggerConfig* mutable_trigger_config() { _has_field_.set(17); return trigger_config_.get(); }

  const std::vector<std::string>& activate_triggers() const { return activate_triggers_; }
  std::vector<std::string>* mutable_activate_triggers() { return &activate_triggers_; }
  int activate_triggers_size() const { return static_cast<int>(activate_triggers_.size()); }
  void clear_activate_triggers() { activate_triggers_.clear(); }
  void add_activate_triggers(std::string value) { activate_triggers_.emplace_back(value); }
  std::string* add_activate_triggers() { activate_triggers_.emplace_back(); return &activate_triggers_.back(); }

  bool has_incremental_state_config() const { return _has_field_[21]; }
  const TraceConfig_IncrementalStateConfig& incremental_state_config() const { return *incremental_state_config_; }
  TraceConfig_IncrementalStateConfig* mutable_incremental_state_config() { _has_field_.set(21); return incremental_state_config_.get(); }

  bool has_allow_user_build_tracing() const { return _has_field_[19]; }
  bool allow_user_build_tracing() const { return allow_user_build_tracing_; }
  void set_allow_user_build_tracing(bool value) { allow_user_build_tracing_ = value; _has_field_.set(19); }

  bool has_unique_session_name() const { return _has_field_[22]; }
  const std::string& unique_session_name() const { return unique_session_name_; }
  void set_unique_session_name(const std::string& value) { unique_session_name_ = value; _has_field_.set(22); }

  bool has_compression_type() const { return _has_field_[24]; }
  TraceConfig_CompressionType compression_type() const { return compression_type_; }
  void set_compression_type(TraceConfig_CompressionType value) { compression_type_ = value; _has_field_.set(24); }

  bool has_incident_report_config() const { return _has_field_[25]; }
  const TraceConfig_IncidentReportConfig& incident_report_config() const { return *incident_report_config_; }
  TraceConfig_IncidentReportConfig* mutable_incident_report_config() { _has_field_.set(25); return incident_report_config_.get(); }

  bool has_statsd_logging() const { return _has_field_[31]; }
  TraceConfig_StatsdLogging statsd_logging() const { return statsd_logging_; }
  void set_statsd_logging(TraceConfig_StatsdLogging value) { statsd_logging_ = value; _has_field_.set(31); }

  bool has_trace_uuid_msb() const { return _has_field_[27]; }
  int64_t trace_uuid_msb() const { return trace_uuid_msb_; }
  void set_trace_uuid_msb(int64_t value) { trace_uuid_msb_ = value; _has_field_.set(27); }

  bool has_trace_uuid_lsb() const { return _has_field_[28]; }
  int64_t trace_uuid_lsb() const { return trace_uuid_lsb_; }
  void set_trace_uuid_lsb(int64_t value) { trace_uuid_lsb_ = value; _has_field_.set(28); }

  bool has_trace_filter() const { return _has_field_[33]; }
  const TraceConfig_TraceFilter& trace_filter() const { return *trace_filter_; }
  TraceConfig_TraceFilter* mutable_trace_filter() { _has_field_.set(33); return trace_filter_.get(); }

  bool has_android_report_config() const { return _has_field_[34]; }
  const TraceConfig_AndroidReportConfig& android_report_config() const { return *android_report_config_; }
  TraceConfig_AndroidReportConfig* mutable_android_report_config() { _has_field_.set(34); return android_report_config_.get(); }

  bool has_cmd_trace_start_delay() const { return _has_field_[35]; }
  const TraceConfig_CmdTraceStartDelay& cmd_trace_start_delay() const { return *cmd_trace_start_delay_; }
  TraceConfig_CmdTraceStartDelay* mutable_cmd_trace_start_delay() { _has_field_.set(35); return cmd_trace_start_delay_.get(); }

  const std::vector<TraceConfig_SessionSemaphore>& session_semaphores() const { return session_semaphores_; }
  std::vector<TraceConfig_SessionSemaphore>* mutable_session_semaphores() { return &session_semaphores_; }
  int session_semaphores_size() const;
  void clear_session_semaphores();
  TraceConfig_SessionSemaphore* add_session_semaphores();

 private:
  std::vector<TraceConfig_BufferConfig> buffers_;
  std::vector<TraceConfig_DataSource> data_sources_;
  ::protozero::CopyablePtr<TraceConfig_BuiltinDataSource> builtin_data_sources_;
  uint32_t duration_ms_{};
  bool prefer_suspend_clock_for_duration_{};
  bool enable_extra_guardrails_{};
  TraceConfig_LockdownModeOperation lockdown_mode_{};
  std::vector<TraceConfig_ProducerConfig> producers_;
  ::protozero::CopyablePtr<TraceConfig_StatsdMetadata> statsd_metadata_;
  bool write_into_file_{};
  std::string output_path_{};
  uint32_t file_write_period_ms_{};
  uint64_t max_file_size_bytes_{};
  ::protozero::CopyablePtr<TraceConfig_GuardrailOverrides> guardrail_overrides_;
  bool deferred_start_{};
  uint32_t flush_period_ms_{};
  uint32_t flush_timeout_ms_{};
  uint32_t data_source_stop_timeout_ms_{};
  bool notify_traceur_{};
  int32_t bugreport_score_{};
  std::string bugreport_filename_{};
  ::protozero::CopyablePtr<TraceConfig_TriggerConfig> trigger_config_;
  std::vector<std::string> activate_triggers_;
  ::protozero::CopyablePtr<TraceConfig_IncrementalStateConfig> incremental_state_config_;
  bool allow_user_build_tracing_{};
  std::string unique_session_name_{};
  TraceConfig_CompressionType compression_type_{};
  ::protozero::CopyablePtr<TraceConfig_IncidentReportConfig> incident_report_config_;
  TraceConfig_StatsdLogging statsd_logging_{};
  int64_t trace_uuid_msb_{};
  int64_t trace_uuid_lsb_{};
  ::protozero::CopyablePtr<TraceConfig_TraceFilter> trace_filter_;
  ::protozero::CopyablePtr<TraceConfig_AndroidReportConfig> android_report_config_;
  ::protozero::CopyablePtr<TraceConfig_CmdTraceStartDelay> cmd_trace_start_delay_;
  std::vector<TraceConfig_SessionSemaphore> session_semaphores_;

  // Allows to preserve unknown protobuf fields for compatibility
  // with future versions of .proto files.
  std::string unknown_fields_;

  std::bitset<40> _has_field_{};
};


class PERFETTO_EXPORT_COMPONENT TraceConfig_SessionSemaphore : public ::protozero::CppMessageObj {
 public:
  enum FieldNumbers {
    kNameFieldNumber = 1,
    kMaxOtherSessionCountFieldNumber = 2,
  };

  TraceConfig_SessionSemaphore();
  ~TraceConfig_SessionSemaphore() override;
  TraceConfig_SessionSemaphore(TraceConfig_SessionSemaphore&&) noexcept;
  TraceConfig_SessionSemaphore& operator=(TraceConfig_SessionSemaphore&&);
  TraceConfig_SessionSemaphore(const TraceConfig_SessionSemaphore&);
  TraceConfig_SessionSemaphore& operator=(const TraceConfig_SessionSemaphore&);
  bool operator==(const TraceConfig_SessionSemaphore&) const;
  bool operator!=(const TraceConfig_SessionSemaphore& other) const { return !(*this == other); }

  bool ParseFromArray(const void*, size_t) override;
  std::string SerializeAsString() const override;
  std::vector<uint8_t> SerializeAsArray() const override;
  void Serialize(::protozero::Message*) const;

  bool has_name() const { return _has_field_[1]; }
  const std::string& name() const { return name_; }
  void set_name(const std::string& value) { name_ = value; _has_field_.set(1); }

  bool has_max_other_session_count() const { return _has_field_[2]; }
  uint64_t max_other_session_count() const { return max_other_session_count_; }
  void set_max_other_session_count(uint64_t value) { max_other_session_count_ = value; _has_field_.set(2); }

 private:
  std::string name_{};
  uint64_t max_other_session_count_{};

  // Allows to preserve unknown protobuf fields for compatibility
  // with future versions of .proto files.
  std::string unknown_fields_;

  std::bitset<3> _has_field_{};
};


class PERFETTO_EXPORT_COMPONENT TraceConfig_CmdTraceStartDelay : public ::protozero::CppMessageObj {
 public:
  enum FieldNumbers {
    kMinDelayMsFieldNumber = 1,
    kMaxDelayMsFieldNumber = 2,
  };

  TraceConfig_CmdTraceStartDelay();
  ~TraceConfig_CmdTraceStartDelay() override;
  TraceConfig_CmdTraceStartDelay(TraceConfig_CmdTraceStartDelay&&) noexcept;
  TraceConfig_CmdTraceStartDelay& operator=(TraceConfig_CmdTraceStartDelay&&);
  TraceConfig_CmdTraceStartDelay(const TraceConfig_CmdTraceStartDelay&);
  TraceConfig_CmdTraceStartDelay& operator=(const TraceConfig_CmdTraceStartDelay&);
  bool operator==(const TraceConfig_CmdTraceStartDelay&) const;
  bool operator!=(const TraceConfig_CmdTraceStartDelay& other) const { return !(*this == other); }

  bool ParseFromArray(const void*, size_t) override;
  std::string SerializeAsString() const override;
  std::vector<uint8_t> SerializeAsArray() const override;
  void Serialize(::protozero::Message*) const;

  bool has_min_delay_ms() const { return _has_field_[1]; }
  uint32_t min_delay_ms() const { return min_delay_ms_; }
  void set_min_delay_ms(uint32_t value) { min_delay_ms_ = value; _has_field_.set(1); }

  bool has_max_delay_ms() const { return _has_field_[2]; }
  uint32_t max_delay_ms() const { return max_delay_ms_; }
  void set_max_delay_ms(uint32_t value) { max_delay_ms_ = value; _has_field_.set(2); }

 private:
  uint32_t min_delay_ms_{};
  uint32_t max_delay_ms_{};

  // Allows to preserve unknown protobuf fields for compatibility
  // with future versions of .proto files.
  std::string unknown_fields_;

  std::bitset<3> _has_field_{};
};


class PERFETTO_EXPORT_COMPONENT TraceConfig_AndroidReportConfig : public ::protozero::CppMessageObj {
 public:
  enum FieldNumbers {
    kReporterServicePackageFieldNumber = 1,
    kReporterServiceClassFieldNumber = 2,
    kSkipReportFieldNumber = 3,
    kUsePipeInFrameworkForTestingFieldNumber = 4,
  };

  TraceConfig_AndroidReportConfig();
  ~TraceConfig_AndroidReportConfig() override;
  TraceConfig_AndroidReportConfig(TraceConfig_AndroidReportConfig&&) noexcept;
  TraceConfig_AndroidReportConfig& operator=(TraceConfig_AndroidReportConfig&&);
  TraceConfig_AndroidReportConfig(const TraceConfig_AndroidReportConfig&);
  TraceConfig_AndroidReportConfig& operator=(const TraceConfig_AndroidReportConfig&);
  bool operator==(const TraceConfig_AndroidReportConfig&) const;
  bool operator!=(const TraceConfig_AndroidReportConfig& other) const { return !(*this == other); }

  bool ParseFromArray(const void*, size_t) override;
  std::string SerializeAsString() const override;
  std::vector<uint8_t> SerializeAsArray() const override;
  void Serialize(::protozero::Message*) const;

  bool has_reporter_service_package() const { return _has_field_[1]; }
  const std::string& reporter_service_package() const { return reporter_service_package_; }
  void set_reporter_service_package(const std::string& value) { reporter_service_package_ = value; _has_field_.set(1); }

  bool has_reporter_service_class() const { return _has_field_[2]; }
  const std::string& reporter_service_class() const { return reporter_service_class_; }
  void set_reporter_service_class(const std::string& value) { reporter_service_class_ = value; _has_field_.set(2); }

  bool has_skip_report() const { return _has_field_[3]; }
  bool skip_report() const { return skip_report_; }
  void set_skip_report(bool value) { skip_report_ = value; _has_field_.set(3); }

  bool has_use_pipe_in_framework_for_testing() const { return _has_field_[4]; }
  bool use_pipe_in_framework_for_testing() const { return use_pipe_in_framework_for_testing_; }
  void set_use_pipe_in_framework_for_testing(bool value) { use_pipe_in_framework_for_testing_ = value; _has_field_.set(4); }

 private:
  std::string reporter_service_package_{};
  std::string reporter_service_class_{};
  bool skip_report_{};
  bool use_pipe_in_framework_for_testing_{};

  // Allows to preserve unknown protobuf fields for compatibility
  // with future versions of .proto files.
  std::string unknown_fields_;

  std::bitset<5> _has_field_{};
};


class PERFETTO_EXPORT_COMPONENT TraceConfig_TraceFilter : public ::protozero::CppMessageObj {
 public:
  using StringFilterRule = TraceConfig_TraceFilter_StringFilterRule;
  using StringFilterChain = TraceConfig_TraceFilter_StringFilterChain;
  using StringFilterPolicy = TraceConfig_TraceFilter_StringFilterPolicy;
  static constexpr auto SFP_UNSPECIFIED = TraceConfig_TraceFilter_StringFilterPolicy_SFP_UNSPECIFIED;
  static constexpr auto SFP_MATCH_REDACT_GROUPS = TraceConfig_TraceFilter_StringFilterPolicy_SFP_MATCH_REDACT_GROUPS;
  static constexpr auto SFP_ATRACE_MATCH_REDACT_GROUPS = TraceConfig_TraceFilter_StringFilterPolicy_SFP_ATRACE_MATCH_REDACT_GROUPS;
  static constexpr auto SFP_MATCH_BREAK = TraceConfig_TraceFilter_StringFilterPolicy_SFP_MATCH_BREAK;
  static constexpr auto SFP_ATRACE_MATCH_BREAK = TraceConfig_TraceFilter_StringFilterPolicy_SFP_ATRACE_MATCH_BREAK;
  static constexpr auto SFP_ATRACE_REPEATED_SEARCH_REDACT_GROUPS = TraceConfig_TraceFilter_StringFilterPolicy_SFP_ATRACE_REPEATED_SEARCH_REDACT_GROUPS;
  static constexpr auto StringFilterPolicy_MIN = TraceConfig_TraceFilter_StringFilterPolicy_SFP_UNSPECIFIED;
  static constexpr auto StringFilterPolicy_MAX = TraceConfig_TraceFilter_StringFilterPolicy_SFP_ATRACE_REPEATED_SEARCH_REDACT_GROUPS;
  enum FieldNumbers {
    kBytecodeFieldNumber = 1,
    kBytecodeV2FieldNumber = 2,
    kStringFilterChainFieldNumber = 3,
  };

  TraceConfig_TraceFilter();
  ~TraceConfig_TraceFilter() override;
  TraceConfig_TraceFilter(TraceConfig_TraceFilter&&) noexcept;
  TraceConfig_TraceFilter& operator=(TraceConfig_TraceFilter&&);
  TraceConfig_TraceFilter(const TraceConfig_TraceFilter&);
  TraceConfig_TraceFilter& operator=(const TraceConfig_TraceFilter&);
  bool operator==(const TraceConfig_TraceFilter&) const;
  bool operator!=(const TraceConfig_TraceFilter& other) const { return !(*this == other); }

  bool ParseFromArray(const void*, size_t) override;
  std::string SerializeAsString() const override;
  std::vector<uint8_t> SerializeAsArray() const override;
  void Serialize(::protozero::Message*) const;

  bool has_bytecode() const { return _has_field_[1]; }
  const std::string& bytecode() const { return bytecode_; }
  void set_bytecode(const std::string& value) { bytecode_ = value; _has_field_.set(1); }
  void set_bytecode(const void* p, size_t s) { bytecode_.assign(reinterpret_cast<const char*>(p), s); _has_field_.set(1); }

  bool has_bytecode_v2() const { return _has_field_[2]; }
  const std::string& bytecode_v2() const { return bytecode_v2_; }
  void set_bytecode_v2(const std::string& value) { bytecode_v2_ = value; _has_field_.set(2); }
  void set_bytecode_v2(const void* p, size_t s) { bytecode_v2_.assign(reinterpret_cast<const char*>(p), s); _has_field_.set(2); }

  bool has_string_filter_chain() const { return _has_field_[3]; }
  const TraceConfig_TraceFilter_StringFilterChain& string_filter_chain() const { return *string_filter_chain_; }
  TraceConfig_TraceFilter_StringFilterChain* mutable_string_filter_chain() { _has_field_.set(3); return string_filter_chain_.get(); }

 private:
  std::string bytecode_{};
  std::string bytecode_v2_{};
  ::protozero::CopyablePtr<TraceConfig_TraceFilter_StringFilterChain> string_filter_chain_;

  // Allows to preserve unknown protobuf fields for compatibility
  // with future versions of .proto files.
  std::string unknown_fields_;

  std::bitset<4> _has_field_{};
};


class PERFETTO_EXPORT_COMPONENT TraceConfig_TraceFilter_StringFilterChain : public ::protozero::CppMessageObj {
 public:
  enum FieldNumbers {
    kRulesFieldNumber = 1,
  };

  TraceConfig_TraceFilter_StringFilterChain();
  ~TraceConfig_TraceFilter_StringFilterChain() override;
  TraceConfig_TraceFilter_StringFilterChain(TraceConfig_TraceFilter_StringFilterChain&&) noexcept;
  TraceConfig_TraceFilter_StringFilterChain& operator=(TraceConfig_TraceFilter_StringFilterChain&&);
  TraceConfig_TraceFilter_StringFilterChain(const TraceConfig_TraceFilter_StringFilterChain&);
  TraceConfig_TraceFilter_StringFilterChain& operator=(const TraceConfig_TraceFilter_StringFilterChain&);
  bool operator==(const TraceConfig_TraceFilter_StringFilterChain&) const;
  bool operator!=(const TraceConfig_TraceFilter_StringFilterChain& other) const { return !(*this == other); }

  bool ParseFromArray(const void*, size_t) override;
  std::string SerializeAsString() const override;
  std::vector<uint8_t> SerializeAsArray() const override;
  void Serialize(::protozero::Message*) const;

  const std::vector<TraceConfig_TraceFilter_StringFilterRule>& rules() const { return rules_; }
  std::vector<TraceConfig_TraceFilter_StringFilterRule>* mutable_rules() { return &rules_; }
  int rules_size() const;
  void clear_rules();
  TraceConfig_TraceFilter_StringFilterRule* add_rules();

 private:
  std::vector<TraceConfig_TraceFilter_StringFilterRule> rules_;

  // Allows to preserve unknown protobuf fields for compatibility
  // with future versions of .proto files.
  std::string unknown_fields_;

  std::bitset<2> _has_field_{};
};


class PERFETTO_EXPORT_COMPONENT TraceConfig_TraceFilter_StringFilterRule : public ::protozero::CppMessageObj {
 public:
  enum FieldNumbers {
    kPolicyFieldNumber = 1,
    kRegexPatternFieldNumber = 2,
    kAtracePayloadStartsWithFieldNumber = 3,
  };

  TraceConfig_TraceFilter_StringFilterRule();
  ~TraceConfig_TraceFilter_StringFilterRule() override;
  TraceConfig_TraceFilter_StringFilterRule(TraceConfig_TraceFilter_StringFilterRule&&) noexcept;
  TraceConfig_TraceFilter_StringFilterRule& operator=(TraceConfig_TraceFilter_StringFilterRule&&);
  TraceConfig_TraceFilter_StringFilterRule(const TraceConfig_TraceFilter_StringFilterRule&);
  TraceConfig_TraceFilter_StringFilterRule& operator=(const TraceConfig_TraceFilter_StringFilterRule&);
  bool operator==(const TraceConfig_TraceFilter_StringFilterRule&) const;
  bool operator!=(const TraceConfig_TraceFilter_StringFilterRule& other) const { return !(*this == other); }

  bool ParseFromArray(const void*, size_t) override;
  std::string SerializeAsString() const override;
  std::vector<uint8_t> SerializeAsArray() const override;
  void Serialize(::protozero::Message*) const;

  bool has_policy() const { return _has_field_[1]; }
  TraceConfig_TraceFilter_StringFilterPolicy policy() const { return policy_; }
  void set_policy(TraceConfig_TraceFilter_StringFilterPolicy value) { policy_ = value; _has_field_.set(1); }

  bool has_regex_pattern() const { return _has_field_[2]; }
  const std::string& regex_pattern() const { return regex_pattern_; }
  void set_regex_pattern(const std::string& value) { regex_pattern_ = value; _has_field_.set(2); }

  bool has_atrace_payload_starts_with() const { return _has_field_[3]; }
  const std::string& atrace_payload_starts_with() const { return atrace_payload_starts_with_; }
  void set_atrace_payload_starts_with(const std::string& value) { atrace_payload_starts_with_ = value; _has_field_.set(3); }

 private:
  TraceConfig_TraceFilter_StringFilterPolicy policy_{};
  std::string regex_pattern_{};
  std::string atrace_payload_starts_with_{};

  // Allows to preserve unknown protobuf fields for compatibility
  // with future versions of .proto files.
  std::string unknown_fields_;

  std::bitset<4> _has_field_{};
};


class PERFETTO_EXPORT_COMPONENT TraceConfig_IncidentReportConfig : public ::protozero::CppMessageObj {
 public:
  enum FieldNumbers {
    kDestinationPackageFieldNumber = 1,
    kDestinationClassFieldNumber = 2,
    kPrivacyLevelFieldNumber = 3,
    kSkipIncidentdFieldNumber = 5,
    kSkipDropboxFieldNumber = 4,
  };

  TraceConfig_IncidentReportConfig();
  ~TraceConfig_IncidentReportConfig() override;
  TraceConfig_IncidentReportConfig(TraceConfig_IncidentReportConfig&&) noexcept;
  TraceConfig_IncidentReportConfig& operator=(TraceConfig_IncidentReportConfig&&);
  TraceConfig_IncidentReportConfig(const TraceConfig_IncidentReportConfig&);
  TraceConfig_IncidentReportConfig& operator=(const TraceConfig_IncidentReportConfig&);
  bool operator==(const TraceConfig_IncidentReportConfig&) const;
  bool operator!=(const TraceConfig_IncidentReportConfig& other) const { return !(*this == other); }

  bool ParseFromArray(const void*, size_t) override;
  std::string SerializeAsString() const override;
  std::vector<uint8_t> SerializeAsArray() const override;
  void Serialize(::protozero::Message*) const;

  bool has_destination_package() const { return _has_field_[1]; }
  const std::string& destination_package() const { return destination_package_; }
  void set_destination_package(const std::string& value) { destination_package_ = value; _has_field_.set(1); }

  bool has_destination_class() const { return _has_field_[2]; }
  const std::string& destination_class() const { return destination_class_; }
  void set_destination_class(const std::string& value) { destination_class_ = value; _has_field_.set(2); }

  bool has_privacy_level() const { return _has_field_[3]; }
  int32_t privacy_level() const { return privacy_level_; }
  void set_privacy_level(int32_t value) { privacy_level_ = value; _has_field_.set(3); }

  bool has_skip_incidentd() const { return _has_field_[5]; }
  bool skip_incidentd() const { return skip_incidentd_; }
  void set_skip_incidentd(bool value) { skip_incidentd_ = value; _has_field_.set(5); }

  bool has_skip_dropbox() const { return _has_field_[4]; }
  bool skip_dropbox() const { return skip_dropbox_; }
  void set_skip_dropbox(bool value) { skip_dropbox_ = value; _has_field_.set(4); }

 private:
  std::string destination_package_{};
  std::string destination_class_{};
  int32_t privacy_level_{};
  bool skip_incidentd_{};
  bool skip_dropbox_{};

  // Allows to preserve unknown protobuf fields for compatibility
  // with future versions of .proto files.
  std::string unknown_fields_;

  std::bitset<6> _has_field_{};
};


class PERFETTO_EXPORT_COMPONENT TraceConfig_IncrementalStateConfig : public ::protozero::CppMessageObj {
 public:
  enum FieldNumbers {
    kClearPeriodMsFieldNumber = 1,
  };

  TraceConfig_IncrementalStateConfig();
  ~TraceConfig_IncrementalStateConfig() override;
  TraceConfig_IncrementalStateConfig(TraceConfig_IncrementalStateConfig&&) noexcept;
  TraceConfig_IncrementalStateConfig& operator=(TraceConfig_IncrementalStateConfig&&);
  TraceConfig_IncrementalStateConfig(const TraceConfig_IncrementalStateConfig&);
  TraceConfig_IncrementalStateConfig& operator=(const TraceConfig_IncrementalStateConfig&);
  bool operator==(const TraceConfig_IncrementalStateConfig&) const;
  bool operator!=(const TraceConfig_IncrementalStateConfig& other) const { return !(*this == other); }

  bool ParseFromArray(const void*, size_t) override;
  std::string SerializeAsString() const override;
  std::vector<uint8_t> SerializeAsArray() const override;
  void Serialize(::protozero::Message*) const;

  bool has_clear_period_ms() const { return _has_field_[1]; }
  uint32_t clear_period_ms() const { return clear_period_ms_; }
  void set_clear_period_ms(uint32_t value) { clear_period_ms_ = value; _has_field_.set(1); }

 private:
  uint32_t clear_period_ms_{};

  // Allows to preserve unknown protobuf fields for compatibility
  // with future versions of .proto files.
  std::string unknown_fields_;

  std::bitset<2> _has_field_{};
};


class PERFETTO_EXPORT_COMPONENT TraceConfig_TriggerConfig : public ::protozero::CppMessageObj {
 public:
  using Trigger = TraceConfig_TriggerConfig_Trigger;
  using TriggerMode = TraceConfig_TriggerConfig_TriggerMode;
  static constexpr auto UNSPECIFIED = TraceConfig_TriggerConfig_TriggerMode_UNSPECIFIED;
  static constexpr auto START_TRACING = TraceConfig_TriggerConfig_TriggerMode_START_TRACING;
  static constexpr auto STOP_TRACING = TraceConfig_TriggerConfig_TriggerMode_STOP_TRACING;
  static constexpr auto CLONE_SNAPSHOT = TraceConfig_TriggerConfig_TriggerMode_CLONE_SNAPSHOT;
  static constexpr auto TriggerMode_MIN = TraceConfig_TriggerConfig_TriggerMode_UNSPECIFIED;
  static constexpr auto TriggerMode_MAX = TraceConfig_TriggerConfig_TriggerMode_CLONE_SNAPSHOT;
  enum FieldNumbers {
    kTriggerModeFieldNumber = 1,
    kUseCloneSnapshotIfAvailableFieldNumber = 5,
    kTriggersFieldNumber = 2,
    kTriggerTimeoutMsFieldNumber = 3,
  };

  TraceConfig_TriggerConfig();
  ~TraceConfig_TriggerConfig() override;
  TraceConfig_TriggerConfig(TraceConfig_TriggerConfig&&) noexcept;
  TraceConfig_TriggerConfig& operator=(TraceConfig_TriggerConfig&&);
  TraceConfig_TriggerConfig(const TraceConfig_TriggerConfig&);
  TraceConfig_TriggerConfig& operator=(const TraceConfig_TriggerConfig&);
  bool operator==(const TraceConfig_TriggerConfig&) const;
  bool operator!=(const TraceConfig_TriggerConfig& other) const { return !(*this == other); }

  bool ParseFromArray(const void*, size_t) override;
  std::string SerializeAsString() const override;
  std::vector<uint8_t> SerializeAsArray() const override;
  void Serialize(::protozero::Message*) const;

  bool has_trigger_mode() const { return _has_field_[1]; }
  TraceConfig_TriggerConfig_TriggerMode trigger_mode() const { return trigger_mode_; }
  void set_trigger_mode(TraceConfig_TriggerConfig_TriggerMode value) { trigger_mode_ = value; _has_field_.set(1); }

  bool has_use_clone_snapshot_if_available() const { return _has_field_[5]; }
  bool use_clone_snapshot_if_available() const { return use_clone_snapshot_if_available_; }
  void set_use_clone_snapshot_if_available(bool value) { use_clone_snapshot_if_available_ = value; _has_field_.set(5); }

  const std::vector<TraceConfig_TriggerConfig_Trigger>& triggers() const { return triggers_; }
  std::vector<TraceConfig_TriggerConfig_Trigger>* mutable_triggers() { return &triggers_; }
  int triggers_size() const;
  void clear_triggers();
  TraceConfig_TriggerConfig_Trigger* add_triggers();

  bool has_trigger_timeout_ms() const { return _has_field_[3]; }
  uint32_t trigger_timeout_ms() const { return trigger_timeout_ms_; }
  void set_trigger_timeout_ms(uint32_t value) { trigger_timeout_ms_ = value; _has_field_.set(3); }

 private:
  TraceConfig_TriggerConfig_TriggerMode trigger_mode_{};
  bool use_clone_snapshot_if_available_{};
  std::vector<TraceConfig_TriggerConfig_Trigger> triggers_;
  uint32_t trigger_timeout_ms_{};

  // Allows to preserve unknown protobuf fields for compatibility
  // with future versions of .proto files.
  std::string unknown_fields_;

  std::bitset<6> _has_field_{};
};


class PERFETTO_EXPORT_COMPONENT TraceConfig_TriggerConfig_Trigger : public ::protozero::CppMessageObj {
 public:
  enum FieldNumbers {
    kNameFieldNumber = 1,
    kProducerNameRegexFieldNumber = 2,
    kStopDelayMsFieldNumber = 3,
    kMaxPer24HFieldNumber = 4,
    kSkipProbabilityFieldNumber = 5,
  };

  TraceConfig_TriggerConfig_Trigger();
  ~TraceConfig_TriggerConfig_Trigger() override;
  TraceConfig_TriggerConfig_Trigger(TraceConfig_TriggerConfig_Trigger&&) noexcept;
  TraceConfig_TriggerConfig_Trigger& operator=(TraceConfig_TriggerConfig_Trigger&&);
  TraceConfig_TriggerConfig_Trigger(const TraceConfig_TriggerConfig_Trigger&);
  TraceConfig_TriggerConfig_Trigger& operator=(const TraceConfig_TriggerConfig_Trigger&);
  bool operator==(const TraceConfig_TriggerConfig_Trigger&) const;
  bool operator!=(const TraceConfig_TriggerConfig_Trigger& other) const { return !(*this == other); }

  bool ParseFromArray(const void*, size_t) override;
  std::string SerializeAsString() const override;
  std::vector<uint8_t> SerializeAsArray() const override;
  void Serialize(::protozero::Message*) const;

  bool has_name() const { return _has_field_[1]; }
  const std::string& name() const { return name_; }
  void set_name(const std::string& value) { name_ = value; _has_field_.set(1); }

  bool has_producer_name_regex() const { return _has_field_[2]; }
  const std::string& producer_name_regex() const { return producer_name_regex_; }
  void set_producer_name_regex(const std::string& value) { producer_name_regex_ = value; _has_field_.set(2); }

  bool has_stop_delay_ms() const { return _has_field_[3]; }
  uint32_t stop_delay_ms() const { return stop_delay_ms_; }
  void set_stop_delay_ms(uint32_t value) { stop_delay_ms_ = value; _has_field_.set(3); }

  bool has_max_per_24_h() const { return _has_field_[4]; }
  uint32_t max_per_24_h() const { return max_per_24_h_; }
  void set_max_per_24_h(uint32_t value) { max_per_24_h_ = value; _has_field_.set(4); }

  bool has_skip_probability() const { return _has_field_[5]; }
  double skip_probability() const { return skip_probability_; }
  void set_skip_probability(double value) { skip_probability_ = value; _has_field_.set(5); }

 private:
  std::string name_{};
  std::string producer_name_regex_{};
  uint32_t stop_delay_ms_{};
  uint32_t max_per_24_h_{};
  double skip_probability_{};

  // Allows to preserve unknown protobuf fields for compatibility
  // with future versions of .proto files.
  std::string unknown_fields_;

  std::bitset<6> _has_field_{};
};


class PERFETTO_EXPORT_COMPONENT TraceConfig_GuardrailOverrides : public ::protozero::CppMessageObj {
 public:
  enum FieldNumbers {
    kMaxUploadPerDayBytesFieldNumber = 1,
    kMaxTracingBufferSizeKbFieldNumber = 2,
  };

  TraceConfig_GuardrailOverrides();
  ~TraceConfig_GuardrailOverrides() override;
  TraceConfig_GuardrailOverrides(TraceConfig_GuardrailOverrides&&) noexcept;
  TraceConfig_GuardrailOverrides& operator=(TraceConfig_GuardrailOverrides&&);
  TraceConfig_GuardrailOverrides(const TraceConfig_GuardrailOverrides&);
  TraceConfig_GuardrailOverrides& operator=(const TraceConfig_GuardrailOverrides&);
  bool operator==(const TraceConfig_GuardrailOverrides&) const;
  bool operator!=(const TraceConfig_GuardrailOverrides& other) const { return !(*this == other); }

  bool ParseFromArray(const void*, size_t) override;
  std::string SerializeAsString() const override;
  std::vector<uint8_t> SerializeAsArray() const override;
  void Serialize(::protozero::Message*) const;

  bool has_max_upload_per_day_bytes() const { return _has_field_[1]; }
  uint64_t max_upload_per_day_bytes() const { return max_upload_per_day_bytes_; }
  void set_max_upload_per_day_bytes(uint64_t value) { max_upload_per_day_bytes_ = value; _has_field_.set(1); }

  bool has_max_tracing_buffer_size_kb() const { return _has_field_[2]; }
  uint32_t max_tracing_buffer_size_kb() const { return max_tracing_buffer_size_kb_; }
  void set_max_tracing_buffer_size_kb(uint32_t value) { max_tracing_buffer_size_kb_ = value; _has_field_.set(2); }

 private:
  uint64_t max_upload_per_day_bytes_{};
  uint32_t max_tracing_buffer_size_kb_{};

  // Allows to preserve unknown protobuf fields for compatibility
  // with future versions of .proto files.
  std::string unknown_fields_;

  std::bitset<3> _has_field_{};
};


class PERFETTO_EXPORT_COMPONENT TraceConfig_StatsdMetadata : public ::protozero::CppMessageObj {
 public:
  enum FieldNumbers {
    kTriggeringAlertIdFieldNumber = 1,
    kTriggeringConfigUidFieldNumber = 2,
    kTriggeringConfigIdFieldNumber = 3,
    kTriggeringSubscriptionIdFieldNumber = 4,
  };

  TraceConfig_StatsdMetadata();
  ~TraceConfig_StatsdMetadata() override;
  TraceConfig_StatsdMetadata(TraceConfig_StatsdMetadata&&) noexcept;
  TraceConfig_StatsdMetadata& operator=(TraceConfig_StatsdMetadata&&);
  TraceConfig_StatsdMetadata(const TraceConfig_StatsdMetadata&);
  TraceConfig_StatsdMetadata& operator=(const TraceConfig_StatsdMetadata&);
  bool operator==(const TraceConfig_StatsdMetadata&) const;
  bool operator!=(const TraceConfig_StatsdMetadata& other) const { return !(*this == other); }

  bool ParseFromArray(const void*, size_t) override;
  std::string SerializeAsString() const override;
  std::vector<uint8_t> SerializeAsArray() const override;
  void Serialize(::protozero::Message*) const;

  bool has_triggering_alert_id() const { return _has_field_[1]; }
  int64_t triggering_alert_id() const { return triggering_alert_id_; }
  void set_triggering_alert_id(int64_t value) { triggering_alert_id_ = value; _has_field_.set(1); }

  bool has_triggering_config_uid() const { return _has_field_[2]; }
  int32_t triggering_config_uid() const { return triggering_config_uid_; }
  void set_triggering_config_uid(int32_t value) { triggering_config_uid_ = value; _has_field_.set(2); }

  bool has_triggering_config_id() const { return _has_field_[3]; }
  int64_t triggering_config_id() const { return triggering_config_id_; }
  void set_triggering_config_id(int64_t value) { triggering_config_id_ = value; _has_field_.set(3); }

  bool has_triggering_subscription_id() const { return _has_field_[4]; }
  int64_t triggering_subscription_id() const { return triggering_subscription_id_; }
  void set_triggering_subscription_id(int64_t value) { triggering_subscription_id_ = value; _has_field_.set(4); }

 private:
  int64_t triggering_alert_id_{};
  int32_t triggering_config_uid_{};
  int64_t triggering_config_id_{};
  int64_t triggering_subscription_id_{};

  // Allows to preserve unknown protobuf fields for compatibility
  // with future versions of .proto files.
  std::string unknown_fields_;

  std::bitset<5> _has_field_{};
};


class PERFETTO_EXPORT_COMPONENT TraceConfig_ProducerConfig : public ::protozero::CppMessageObj {
 public:
  enum FieldNumbers {
    kProducerNameFieldNumber = 1,
    kShmSizeKbFieldNumber = 2,
    kPageSizeKbFieldNumber = 3,
  };

  TraceConfig_ProducerConfig();
  ~TraceConfig_ProducerConfig() override;
  TraceConfig_ProducerConfig(TraceConfig_ProducerConfig&&) noexcept;
  TraceConfig_ProducerConfig& operator=(TraceConfig_ProducerConfig&&);
  TraceConfig_ProducerConfig(const TraceConfig_ProducerConfig&);
  TraceConfig_ProducerConfig& operator=(const TraceConfig_ProducerConfig&);
  bool operator==(const TraceConfig_ProducerConfig&) const;
  bool operator!=(const TraceConfig_ProducerConfig& other) const { return !(*this == other); }

  bool ParseFromArray(const void*, size_t) override;
  std::string SerializeAsString() const override;
  std::vector<uint8_t> SerializeAsArray() const override;
  void Serialize(::protozero::Message*) const;

  bool has_producer_name() const { return _has_field_[1]; }
  const std::string& producer_name() const { return producer_name_; }
  void set_producer_name(const std::string& value) { producer_name_ = value; _has_field_.set(1); }

  bool has_shm_size_kb() const { return _has_field_[2]; }
  uint32_t shm_size_kb() const { return shm_size_kb_; }
  void set_shm_size_kb(uint32_t value) { shm_size_kb_ = value; _has_field_.set(2); }

  bool has_page_size_kb() const { return _has_field_[3]; }
  uint32_t page_size_kb() const { return page_size_kb_; }
  void set_page_size_kb(uint32_t value) { page_size_kb_ = value; _has_field_.set(3); }

 private:
  std::string producer_name_{};
  uint32_t shm_size_kb_{};
  uint32_t page_size_kb_{};

  // Allows to preserve unknown protobuf fields for compatibility
  // with future versions of .proto files.
  std::string unknown_fields_;

  std::bitset<4> _has_field_{};
};


class PERFETTO_EXPORT_COMPONENT TraceConfig_BuiltinDataSource : public ::protozero::CppMessageObj {
 public:
  enum FieldNumbers {
    kDisableClockSnapshottingFieldNumber = 1,
    kDisableTraceConfigFieldNumber = 2,
    kDisableSystemInfoFieldNumber = 3,
    kDisableServiceEventsFieldNumber = 4,
    kPrimaryTraceClockFieldNumber = 5,
    kSnapshotIntervalMsFieldNumber = 6,
    kPreferSuspendClockForSnapshotFieldNumber = 7,
    kDisableChunkUsageHistogramsFieldNumber = 8,
  };

  TraceConfig_BuiltinDataSource();
  ~TraceConfig_BuiltinDataSource() override;
  TraceConfig_BuiltinDataSource(TraceConfig_BuiltinDataSource&&) noexcept;
  TraceConfig_BuiltinDataSource& operator=(TraceConfig_BuiltinDataSource&&);
  TraceConfig_BuiltinDataSource(const TraceConfig_BuiltinDataSource&);
  TraceConfig_BuiltinDataSource& operator=(const TraceConfig_BuiltinDataSource&);
  bool operator==(const TraceConfig_BuiltinDataSource&) const;
  bool operator!=(const TraceConfig_BuiltinDataSource& other) const { return !(*this == other); }

  bool ParseFromArray(const void*, size_t) override;
  std::string SerializeAsString() const override;
  std::vector<uint8_t> SerializeAsArray() const override;
  void Serialize(::protozero::Message*) const;

  bool has_disable_clock_snapshotting() const { return _has_field_[1]; }
  bool disable_clock_snapshotting() const { return disable_clock_snapshotting_; }
  void set_disable_clock_snapshotting(bool value) { disable_clock_snapshotting_ = value; _has_field_.set(1); }

  bool has_disable_trace_config() const { return _has_field_[2]; }
  bool disable_trace_config() const { return disable_trace_config_; }
  void set_disable_trace_config(bool value) { disable_trace_config_ = value; _has_field_.set(2); }

  bool has_disable_system_info() const { return _has_field_[3]; }
  bool disable_system_info() const { return disable_system_info_; }
  void set_disable_system_info(bool value) { disable_system_info_ = value; _has_field_.set(3); }

  bool has_disable_service_events() const { return _has_field_[4]; }
  bool disable_service_events() const { return disable_service_events_; }
  void set_disable_service_events(bool value) { disable_service_events_ = value; _has_field_.set(4); }

  bool has_primary_trace_clock() const { return _has_field_[5]; }
  BuiltinClock primary_trace_clock() const { return primary_trace_clock_; }
  void set_primary_trace_clock(BuiltinClock value) { primary_trace_clock_ = value; _has_field_.set(5); }

  bool has_snapshot_interval_ms() const { return _has_field_[6]; }
  uint32_t snapshot_interval_ms() const { return snapshot_interval_ms_; }
  void set_snapshot_interval_ms(uint32_t value) { snapshot_interval_ms_ = value; _has_field_.set(6); }

  bool has_prefer_suspend_clock_for_snapshot() const { return _has_field_[7]; }
  bool prefer_suspend_clock_for_snapshot() const { return prefer_suspend_clock_for_snapshot_; }
  void set_prefer_suspend_clock_for_snapshot(bool value) { prefer_suspend_clock_for_snapshot_ = value; _has_field_.set(7); }

  bool has_disable_chunk_usage_histograms() const { return _has_field_[8]; }
  bool disable_chunk_usage_histograms() const { return disable_chunk_usage_histograms_; }
  void set_disable_chunk_usage_histograms(bool value) { disable_chunk_usage_histograms_ = value; _has_field_.set(8); }

 private:
  bool disable_clock_snapshotting_{};
  bool disable_trace_config_{};
  bool disable_system_info_{};
  bool disable_service_events_{};
  BuiltinClock primary_trace_clock_{};
  uint32_t snapshot_interval_ms_{};
  bool prefer_suspend_clock_for_snapshot_{};
  bool disable_chunk_usage_histograms_{};

  // Allows to preserve unknown protobuf fields for compatibility
  // with future versions of .proto files.
  std::string unknown_fields_;

  std::bitset<9> _has_field_{};
};


class PERFETTO_EXPORT_COMPONENT TraceConfig_DataSource : public ::protozero::CppMessageObj {
 public:
  enum FieldNumbers {
    kConfigFieldNumber = 1,
    kProducerNameFilterFieldNumber = 2,
    kProducerNameRegexFilterFieldNumber = 3,
  };

  TraceConfig_DataSource();
  ~TraceConfig_DataSource() override;
  TraceConfig_DataSource(TraceConfig_DataSource&&) noexcept;
  TraceConfig_DataSource& operator=(TraceConfig_DataSource&&);
  TraceConfig_DataSource(const TraceConfig_DataSource&);
  TraceConfig_DataSource& operator=(const TraceConfig_DataSource&);
  bool operator==(const TraceConfig_DataSource&) const;
  bool operator!=(const TraceConfig_DataSource& other) const { return !(*this == other); }

  bool ParseFromArray(const void*, size_t) override;
  std::string SerializeAsString() const override;
  std::vector<uint8_t> SerializeAsArray() const override;
  void Serialize(::protozero::Message*) const;

  bool has_config() const { return _has_field_[1]; }
  const DataSourceConfig& config() const { return *config_; }
  DataSourceConfig* mutable_config() { _has_field_.set(1); return config_.get(); }

  const std::vector<std::string>& producer_name_filter() const { return producer_name_filter_; }
  std::vector<std::string>* mutable_producer_name_filter() { return &producer_name_filter_; }
  int producer_name_filter_size() const { return static_cast<int>(producer_name_filter_.size()); }
  void clear_producer_name_filter() { producer_name_filter_.clear(); }
  void add_producer_name_filter(std::string value) { producer_name_filter_.emplace_back(value); }
  std::string* add_producer_name_filter() { producer_name_filter_.emplace_back(); return &producer_name_filter_.back(); }

  const std::vector<std::string>& producer_name_regex_filter() const { return producer_name_regex_filter_; }
  std::vector<std::string>* mutable_producer_name_regex_filter() { return &producer_name_regex_filter_; }
  int producer_name_regex_filter_size() const { return static_cast<int>(producer_name_regex_filter_.size()); }
  void clear_producer_name_regex_filter() { producer_name_regex_filter_.clear(); }
  void add_producer_name_regex_filter(std::string value) { producer_name_regex_filter_.emplace_back(value); }
  std::string* add_producer_name_regex_filter() { producer_name_regex_filter_.emplace_back(); return &producer_name_regex_filter_.back(); }

 private:
  ::protozero::CopyablePtr<DataSourceConfig> config_;
  std::vector<std::string> producer_name_filter_;
  std::vector<std::string> producer_name_regex_filter_;

  // Allows to preserve unknown protobuf fields for compatibility
  // with future versions of .proto files.
  std::string unknown_fields_;

  std::bitset<4> _has_field_{};
};


class PERFETTO_EXPORT_COMPONENT TraceConfig_BufferConfig : public ::protozero::CppMessageObj {
 public:
  using FillPolicy = TraceConfig_BufferConfig_FillPolicy;
  static constexpr auto UNSPECIFIED = TraceConfig_BufferConfig_FillPolicy_UNSPECIFIED;
  static constexpr auto RING_BUFFER = TraceConfig_BufferConfig_FillPolicy_RING_BUFFER;
  static constexpr auto DISCARD = TraceConfig_BufferConfig_FillPolicy_DISCARD;
  static constexpr auto FillPolicy_MIN = TraceConfig_BufferConfig_FillPolicy_UNSPECIFIED;
  static constexpr auto FillPolicy_MAX = TraceConfig_BufferConfig_FillPolicy_DISCARD;
  enum FieldNumbers {
    kSizeKbFieldNumber = 1,
    kFillPolicyFieldNumber = 4,
    kTransferOnCloneFieldNumber = 5,
    kClearBeforeCloneFieldNumber = 6,
  };

  TraceConfig_BufferConfig();
  ~TraceConfig_BufferConfig() override;
  TraceConfig_BufferConfig(TraceConfig_BufferConfig&&) noexcept;
  TraceConfig_BufferConfig& operator=(TraceConfig_BufferConfig&&);
  TraceConfig_BufferConfig(const TraceConfig_BufferConfig&);
  TraceConfig_BufferConfig& operator=(const TraceConfig_BufferConfig&);
  bool operator==(const TraceConfig_BufferConfig&) const;
  bool operator!=(const TraceConfig_BufferConfig& other) const { return !(*this == other); }

  bool ParseFromArray(const void*, size_t) override;
  std::string SerializeAsString() const override;
  std::vector<uint8_t> SerializeAsArray() const override;
  void Serialize(::protozero::Message*) const;

  bool has_size_kb() const { return _has_field_[1]; }
  uint32_t size_kb() const { return size_kb_; }
  void set_size_kb(uint32_t value) { size_kb_ = value; _has_field_.set(1); }

  bool has_fill_policy() const { return _has_field_[4]; }
  TraceConfig_BufferConfig_FillPolicy fill_policy() const { return fill_policy_; }
  void set_fill_policy(TraceConfig_BufferConfig_FillPolicy value) { fill_policy_ = value; _has_field_.set(4); }

  bool has_transfer_on_clone() const { return _has_field_[5]; }
  bool transfer_on_clone() const { return transfer_on_clone_; }
  void set_transfer_on_clone(bool value) { transfer_on_clone_ = value; _has_field_.set(5); }

  bool has_clear_before_clone() const { return _has_field_[6]; }
  bool clear_before_clone() const { return clear_before_clone_; }
  void set_clear_before_clone(bool value) { clear_before_clone_ = value; _has_field_.set(6); }

 private:
  uint32_t size_kb_{};
  TraceConfig_BufferConfig_FillPolicy fill_policy_{};
  bool transfer_on_clone_{};
  bool clear_before_clone_{};

  // Allows to preserve unknown protobuf fields for compatibility
  // with future versions of .proto files.
  std::string unknown_fields_;

  std::bitset<7> _has_field_{};
};

}  // namespace perfetto
}  // namespace protos
}  // namespace gen

#endif  // PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_TRACE_CONFIG_PROTO_CPP_H_
/*
 * 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.
 */


#ifndef INCLUDE_PERFETTO_TRACING_CORE_TRACE_CONFIG_H_
#define INCLUDE_PERFETTO_TRACING_CORE_TRACE_CONFIG_H_

// Creates the aliases in the ::perfetto namespace, doing things like:
// using ::perfetto::Foo = ::perfetto::protos::gen::Foo.
// See comments in forward_decls.h for the historical reasons of this
// indirection layer.
// gen_amalgamated expanded: #include "perfetto/tracing/core/forward_decls.h"

// gen_amalgamated expanded: #include "protos/perfetto/config/trace_config.gen.h"

namespace perfetto {

inline TraceConfig::TriggerConfig::TriggerMode GetTriggerMode(
    const TraceConfig& cfg) {
  auto mode = cfg.trigger_config().trigger_mode();
  if (cfg.trigger_config().use_clone_snapshot_if_available())
    mode = TraceConfig::TriggerConfig::CLONE_SNAPSHOT;
  return mode;
}

}  // namespace perfetto

#endif  // INCLUDE_PERFETTO_TRACING_CORE_TRACE_CONFIG_H_
// gen_amalgamated begin header: include/perfetto/tracing/data_source.h
// gen_amalgamated begin header: include/perfetto/tracing/core/flush_flags.h
/*
 * Copyright (C) 2023 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.
 */


#ifndef INCLUDE_PERFETTO_TRACING_CORE_FLUSH_FLAGS_H_
#define INCLUDE_PERFETTO_TRACING_CORE_FLUSH_FLAGS_H_

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

namespace perfetto {

// This class is a wrapper around the uint64_t flags that are sent across the
// tracing protocol whenenver a flush occurs. It helps determining the reason
// and initiator of the flush.
// NOTE: the values here are part of the tracing protocol ABI. Do not renumber.
class FlushFlags {
 public:
  enum class Initiator : uint64_t {
    // DO NOT RENUMBER, ABI.
    kUnknown = 0,
    kTraced = 1,
    kPerfettoCmd = 2,
    kConsumerSdk = 3,
    kMax,
  };

  enum class Reason : uint64_t {
    // DO NOT RENUMBER, ABI.
    kUnknown = 0,
    kPeriodic = 1,
    kTraceStop = 2,
    kTraceClone = 3,
    kExplicit = 4,
    kMax,
  };

  enum class CloneTarget : uint64_t {
    // DO NOT RENUMBER, ABI.
    kUnknown = 0,
    kBugreport = 1,
    kMax,
  };

  explicit FlushFlags(uint64_t flags = 0) : flags_(flags) {}
  FlushFlags(Initiator i, Reason r, CloneTarget c = CloneTarget::kUnknown)
      : flags_((static_cast<uint64_t>(i) << kInitiatorShift) |
               (static_cast<uint64_t>(r) << kReasonShift) |
               (static_cast<uint64_t>(c) << kCloneTargetShift)) {}

  bool operator==(const FlushFlags& o) const { return flags_ == o.flags_; }
  bool operator!=(const FlushFlags& o) const { return !(*this == o); }

  Initiator initiator() const {
    // Due to version mismatch we might see a value from the future that we
    // didn't know yet. If that happens, short ciruit to kUnknown.
    static_assert(
        uint64_t(Initiator::kMax) - 1 <= (kInitiatorMask >> kInitiatorShift),
        "enum out of range");
    const uint64_t value = (flags_ & kInitiatorMask) >> kInitiatorShift;
    return value < uint64_t(Initiator::kMax) ? Initiator(value)
                                             : Initiator::kUnknown;
  }

  Reason reason() const {
    static_assert(uint64_t(Reason::kMax) - 1 <= (kReasonMask >> kReasonShift),
                  "enum out of range");
    const uint64_t value = (flags_ & kReasonMask) >> kReasonShift;
    return value < uint64_t(Reason::kMax) ? Reason(value) : Reason::kUnknown;
  }

  CloneTarget clone_target() const {
    static_assert(uint64_t(CloneTarget::kMax) - 1 <=
                      (kCloneTargetMask >> kCloneTargetShift),
                  "enum out of range");
    const uint64_t value = (flags_ & kCloneTargetMask) >> kCloneTargetShift;
    return value < uint64_t(CloneTarget::kMax) ? CloneTarget(value)
                                               : CloneTarget::kUnknown;
  }

  uint64_t flags() const { return flags_; }

 private:
  // DO NOT CHANGE, ABI.
  static constexpr uint64_t kReasonMask = 0xF;
  static constexpr uint64_t kReasonShift = 0;
  static constexpr uint64_t kInitiatorMask = 0xF0;
  static constexpr uint64_t kInitiatorShift = 4;
  static constexpr uint64_t kCloneTargetMask = 0xF00;
  static constexpr uint64_t kCloneTargetShift = 8;

  uint64_t flags_ = 0;
};

}  // namespace perfetto

#endif  // INCLUDE_PERFETTO_TRACING_CORE_FLUSH_FLAGS_H_
// gen_amalgamated begin header: include/perfetto/tracing/internal/data_source_type.h
// gen_amalgamated begin header: include/perfetto/tracing/internal/tracing_muxer.h
// gen_amalgamated begin header: include/perfetto/tracing/internal/tracing_tls.h
// gen_amalgamated begin header: include/perfetto/tracing/platform.h
// gen_amalgamated begin header: include/perfetto/base/proc_utils.h
/*
 * Copyright (C) 2019 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.
 */


#ifndef INCLUDE_PERFETTO_BASE_PROC_UTILS_H_
#define INCLUDE_PERFETTO_BASE_PROC_UTILS_H_

#include <stdint.h>

// gen_amalgamated expanded: #include "perfetto/base/build_config.h"

#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
extern "C" {
// Prototype extracted from the Windows SDK to avoid including windows.h.
__declspec(dllimport) unsigned long __stdcall GetCurrentProcessId();
}
#elif PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
#include <zircon/process.h>
#include <zircon/types.h>
#else
#include <unistd.h>
#endif

namespace perfetto {
namespace base {

#if PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
using PlatformProcessId = zx_handle_t;
inline PlatformProcessId GetProcessId() {
  return zx_process_self();
}
#elif PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
using PlatformProcessId = uint64_t;
inline PlatformProcessId GetProcessId() {
  return static_cast<uint64_t>(GetCurrentProcessId());
}
#else
using PlatformProcessId = pid_t;
inline PlatformProcessId GetProcessId() {
  return getpid();
}
#endif

}  // namespace base
}  // namespace perfetto

#endif  // INCLUDE_PERFETTO_BASE_PROC_UTILS_H_
// gen_amalgamated begin header: include/perfetto/base/thread_utils.h
/*
 * 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.
 */


#ifndef INCLUDE_PERFETTO_BASE_THREAD_UTILS_H_
#define INCLUDE_PERFETTO_BASE_THREAD_UTILS_H_

#include <stdint.h>

// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
// gen_amalgamated expanded: #include "perfetto/base/export.h"

#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
extern "C" {
// Prototype extracted from the Windows SDK to avoid including windows.h.
__declspec(dllimport) unsigned long __stdcall GetCurrentThreadId();
}
#elif PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
#include <zircon/types.h>
#elif PERFETTO_BUILDFLAG(PERFETTO_OS_QNX)
#include <sys/types.h>
#include <unistd.h>
#elif PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
    PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
#include <sys/syscall.h>
#include <sys/types.h>
#include <unistd.h>
#else
#include <pthread.h>
#endif

namespace perfetto {
namespace base {

#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
    PERFETTO_BUILDFLAG(PERFETTO_OS_QNX)
using PlatformThreadId = pid_t;
inline PlatformThreadId GetThreadId() {
  return gettid();
}
#elif PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX)
using PlatformThreadId = pid_t;
inline PlatformThreadId GetThreadId() {
  return static_cast<pid_t>(syscall(__NR_gettid));
}
#elif PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
using PlatformThreadId = zx_koid_t;
// Not inlined because the result is cached internally.
PERFETTO_EXPORT_COMPONENT PlatformThreadId GetThreadId();
#elif PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
using PlatformThreadId = uint64_t;
inline PlatformThreadId GetThreadId() {
  uint64_t tid;
  pthread_threadid_np(nullptr, &tid);
  return tid;
}
#elif PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
using PlatformThreadId = uint64_t;
inline PlatformThreadId GetThreadId() {
  return static_cast<uint64_t>(GetCurrentThreadId());
}
#elif PERFETTO_BUILDFLAG(PERFETTO_OS_NACL)
using PlatformThreadId = pid_t;
inline PlatformThreadId GetThreadId() {
  return reinterpret_cast<int32_t>(pthread_self());
}
#else  // Default to pthreads in case no OS is set.
using PlatformThreadId = pthread_t;
inline PlatformThreadId GetThreadId() {
  return pthread_self();
}
#endif

}  // namespace base
}  // namespace perfetto

#endif  // INCLUDE_PERFETTO_BASE_THREAD_UTILS_H_
// gen_amalgamated begin header: include/perfetto/tracing/tracing.h
// gen_amalgamated begin header: include/perfetto/tracing/backend_type.h
/*
 * 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.
 */


#ifndef INCLUDE_PERFETTO_TRACING_BACKEND_TYPE_H_
#define INCLUDE_PERFETTO_TRACING_BACKEND_TYPE_H_

#include <stdint.h>

namespace perfetto {

enum BackendType : uint32_t {
  kUnspecifiedBackend = 0,

  // Connects to a previously-initialized perfetto tracing backend for
  // in-process. If the in-process backend has not been previously initialized
  // it will do so and create the tracing service on a dedicated thread.
  kInProcessBackend = 1 << 0,

  // Connects to the system tracing service (e.g. on Linux/Android/Mac uses a
  // named UNIX socket).
  kSystemBackend = 1 << 1,

  // Used to provide a custom IPC transport to connect to the service.
  // TracingInitArgs::custom_backend must be non-null and point to an
  // indefinitely lived instance.
  kCustomBackend = 1 << 2,
};

}  // namespace perfetto

#endif  // INCLUDE_PERFETTO_TRACING_BACKEND_TYPE_H_
// gen_amalgamated begin header: include/perfetto/tracing/internal/in_process_tracing_backend.h
// gen_amalgamated begin header: include/perfetto/tracing/tracing_backend.h
// gen_amalgamated begin header: include/perfetto/base/platform_handle.h
/*
 * Copyright (C) 2020 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.
 */


#ifndef INCLUDE_PERFETTO_BASE_PLATFORM_HANDLE_H_
#define INCLUDE_PERFETTO_BASE_PLATFORM_HANDLE_H_

#include <stdint.h>

// gen_amalgamated expanded: #include "perfetto/base/build_config.h"

namespace perfetto {
namespace base {

// PlatformHandle should be used only for types that are HANDLE(s) in Windows.
// It should NOT be used to blanket-replace "int fd" in the codebase.
// Windows has two types of "handles", which, in UNIX-land, both map to int:
// 1. File handles returned by the posix-compatibility API like _open().
//    These are just int(s) and should stay such, because all the posix-like API
//    in Windows.h take an int, not a HANDLE.
// 2. Handles returned by old-school WINAPI like CreateFile, CreateEvent etc.
//    These are proper HANDLE(s). PlatformHandle should be used here.
//
// On Windows, sockets have their own type (SOCKET) which is neither a HANDLE
// nor an int. However Windows SOCKET(s) can have an event HANDLE attached
// to them (which in Perfetto is a PlatformHandle), and that can be used in
// WaitForMultipleObjects, hence in base::TaskRunner.AddFileDescriptorWatch().
// On POSIX OSes, a SocketHandle is really just an int (a file descriptor).
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
// Windows.h typedefs HANDLE to void*, and SOCKET to uintptr_t. We use their
// types to avoid leaking Windows.h through our headers.
using PlatformHandle = void*;
using SocketHandle = uintptr_t;

// On Windows both nullptr and 0xffff... (INVALID_HANDLE_VALUE) are invalid.
struct PlatformHandleChecker {
  static inline bool IsValid(PlatformHandle h) {
    return h && h != reinterpret_cast<PlatformHandle>(-1);
  }
};
#else
using PlatformHandle = int;
using SocketHandle = int;
struct PlatformHandleChecker {
  static inline bool IsValid(PlatformHandle h) { return h >= 0; }
};
#endif

// The definition of this lives in base/file_utils.cc (to avoid creating an
// extra build edge for a one liner). This is really an alias for close() (UNIX)
// CloseHandle() (Windows). THe indirection layer is just to avoid leaking
// system headers like Windows.h through perfetto headers.
// Thre return value is always UNIX-style: 0 on success, -1 on failure.
int ClosePlatformHandle(PlatformHandle);

}  // namespace base
}  // namespace perfetto

#endif  // INCLUDE_PERFETTO_BASE_PLATFORM_HANDLE_H_
/*
 * Copyright (C) 2019 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.
 */


#ifndef INCLUDE_PERFETTO_TRACING_TRACING_BACKEND_H_
#define INCLUDE_PERFETTO_TRACING_TRACING_BACKEND_H_

#include <functional>
#include <memory>
#include <string>

// gen_amalgamated expanded: #include "perfetto/base/export.h"
// gen_amalgamated expanded: #include "perfetto/base/platform_handle.h"

// The embedder can (but doesn't have to) extend the TracingBackend class and
// pass as an argument to Tracing::Initialize(kCustomBackend) to override the
// way to reach the service. This is for peculiar cases where the embedder has
// a multi-process architecture and wants to override the IPC transport. The
// real use-case for this at the time of writing is chromium (+ Mojo IPC).
// Extending this class requires depending on the full set of perfetto headers
// (not just /public/). Contact the team before doing so as the non-public
// headers are not guaranteed to be API stable.

namespace perfetto {

namespace base {
class TaskRunner;
}

// These classes are declared in headers outside of /public/.
class Consumer;
class ConsumerEndpoint;
class Producer;
class ProducerEndpoint;

using CreateSocketCallback = std::function<void(base::SocketHandle)>;
using CreateSocketAsync = void (*)(CreateSocketCallback);

// Responsible for connecting to the producer.
class PERFETTO_EXPORT_COMPONENT TracingProducerBackend {
 public:
  virtual ~TracingProducerBackend();

  // Connects a Producer instance and obtains a ProducerEndpoint, which is
  // essentially a 1:1 channel between one Producer and the Service.
  // To disconnect just destroy the returned endpoint object. It is safe to
  // destroy the Producer once Producer::OnDisconnect() has been invoked.
  struct ConnectProducerArgs {
    std::string producer_name;

    // The Producer object that will receive calls like Start/StopDataSource().
    // The caller has to guarantee that this object is valid as long as the
    // returned ProducerEndpoint is alive.
    Producer* producer = nullptr;

    // The task runner where the Producer methods will be called onto.
    // The caller has to guarantee that the passed TaskRunner is valid as long
    // as the returned ProducerEndpoint is alive.
    ::perfetto::base::TaskRunner* task_runner = nullptr;

    // These get propagated from TracingInitArgs and are optionally provided by
    // the client when calling Tracing::Initialize().
    uint32_t shmem_size_hint_bytes = 0;
    uint32_t shmem_page_size_hint_bytes = 0;

    // If true, the backend should allocate a shared memory buffer and provide
    // it to the service when connecting.
    // It's used in startup tracing.
    bool use_producer_provided_smb = false;

    // If set, the producer will call this function to create and connect to a
    // socket. See the corresponding field in TracingInitArgs for more info.
    CreateSocketAsync create_socket_async = nullptr;
  };

  virtual std::unique_ptr<ProducerEndpoint> ConnectProducer(
      const ConnectProducerArgs&) = 0;
};

// Responsible for connecting to the consumer.
class PERFETTO_EXPORT_COMPONENT TracingConsumerBackend {
 public:
  virtual ~TracingConsumerBackend();

  // As above, for the Consumer-side.
  struct ConnectConsumerArgs {
    // The Consumer object that will receive calls like OnTracingDisabled(),
    // OnTraceData().
    Consumer* consumer{};

    // The task runner where the Consumer methods will be called onto.
    ::perfetto::base::TaskRunner* task_runner{};
  };
  virtual std::unique_ptr<ConsumerEndpoint> ConnectConsumer(
      const ConnectConsumerArgs&) = 0;
};

class PERFETTO_EXPORT_COMPONENT TracingBackend : public TracingProducerBackend,
                                                 public TracingConsumerBackend {
 public:
  ~TracingBackend() override;
};

}  // namespace perfetto

#endif  // INCLUDE_PERFETTO_TRACING_TRACING_BACKEND_H_
/*
 * Copyright (C) 2019 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.
 */


#ifndef INCLUDE_PERFETTO_TRACING_INTERNAL_IN_PROCESS_TRACING_BACKEND_H_
#define INCLUDE_PERFETTO_TRACING_INTERNAL_IN_PROCESS_TRACING_BACKEND_H_

// gen_amalgamated expanded: #include "perfetto/base/export.h"
// gen_amalgamated expanded: #include "perfetto/tracing/tracing_backend.h"

namespace perfetto {

namespace base {
class TaskRunner;
}

class Producer;
class TracingService;

namespace internal {

// A built-in implementation of TracingBackend that creates a tracing service
// instance in-process. Instantiated when the embedder calls
// Tracing::Initialize(kInProcessBackend). Solves most in-app-only tracing
// use-cases.
class PERFETTO_EXPORT_COMPONENT InProcessTracingBackend
    : public TracingBackend {
 public:
  static TracingBackend* GetInstance();

  ~InProcessTracingBackend() override;

  // TracingBackend implementation.
  std::unique_ptr<ProducerEndpoint> ConnectProducer(
      const ConnectProducerArgs&) override;
  std::unique_ptr<ConsumerEndpoint> ConnectConsumer(
      const ConnectConsumerArgs&) override;

 private:
  InProcessTracingBackend();
  TracingService* GetOrCreateService(base::TaskRunner*);

  std::unique_ptr<TracingService> service_;
};

}  // namespace internal
}  // namespace perfetto

#endif  // INCLUDE_PERFETTO_TRACING_INTERNAL_IN_PROCESS_TRACING_BACKEND_H_
// gen_amalgamated begin header: include/perfetto/tracing/internal/system_tracing_backend.h
// gen_amalgamated begin header: include/perfetto/tracing/default_socket.h
/*
 * 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.
 */


#ifndef INCLUDE_PERFETTO_TRACING_DEFAULT_SOCKET_H_
#define INCLUDE_PERFETTO_TRACING_DEFAULT_SOCKET_H_

#include <string>
#include <vector>

// gen_amalgamated expanded: #include "perfetto/base/export.h"

namespace perfetto {

PERFETTO_EXPORT_COMPONENT const char* GetConsumerSocket();
// This function is used for tokenize the |producer_socket_names| string into
// multiple producer socket names.
PERFETTO_EXPORT_COMPONENT std::vector<std::string> TokenizeProducerSockets(
    const char* producer_socket_names);
PERFETTO_EXPORT_COMPONENT const char* GetProducerSocket();

// Optionally returns the relay socket name (nullable). The relay socket is used
// for forwarding the IPC messages between the local producers and the remote
// tracing service.
PERFETTO_EXPORT_COMPONENT const char* GetRelaySocket();

}  // namespace perfetto

#endif  // INCLUDE_PERFETTO_TRACING_DEFAULT_SOCKET_H_
/*
 * Copyright (C) 2019 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.
 */


#ifndef INCLUDE_PERFETTO_TRACING_INTERNAL_SYSTEM_TRACING_BACKEND_H_
#define INCLUDE_PERFETTO_TRACING_INTERNAL_SYSTEM_TRACING_BACKEND_H_

// gen_amalgamated expanded: #include "perfetto/base/export.h"
// gen_amalgamated expanded: #include "perfetto/tracing/default_socket.h"
// gen_amalgamated expanded: #include "perfetto/tracing/tracing_backend.h"

namespace perfetto {

namespace base {
class TaskRunner;
}

class Producer;

// Built-in implementations of TracingProducerBackend and TracingConsumerBackend
// that connect to the system tracing daemon (traced) via a UNIX socket using
// the perfetto built-in proto-based IPC mechanism. Instantiated when the
// embedder calls Tracing::Initialize(kSystemBackend). They allow to get
// app-traces fused together with system traces, useful to correlate on the
// timeline system events (e.g. scheduling slices from the kernel) with in-app
// events.
namespace internal {

// Producer backend
class PERFETTO_EXPORT_COMPONENT SystemProducerTracingBackend
    : public TracingProducerBackend {
 public:
  static TracingProducerBackend* GetInstance();

  std::unique_ptr<ProducerEndpoint> ConnectProducer(
      const ConnectProducerArgs&) override;

 private:
  SystemProducerTracingBackend();
};

// Consumer backend
class PERFETTO_EXPORT_COMPONENT SystemConsumerTracingBackend
    : public TracingConsumerBackend {
 public:
  static TracingConsumerBackend* GetInstance();

  std::unique_ptr<ConsumerEndpoint> ConnectConsumer(
      const ConnectConsumerArgs&) override;

 private:
  SystemConsumerTracingBackend();
};

}  // namespace internal
}  // namespace perfetto

#endif  // INCLUDE_PERFETTO_TRACING_INTERNAL_SYSTEM_TRACING_BACKEND_H_
// gen_amalgamated begin header: include/perfetto/tracing/tracing_policy.h
/*
 * 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.
 */


#ifndef INCLUDE_PERFETTO_TRACING_TRACING_POLICY_H_
#define INCLUDE_PERFETTO_TRACING_TRACING_POLICY_H_

#include <functional>

// gen_amalgamated expanded: #include "perfetto/base/export.h"
// gen_amalgamated expanded: #include "perfetto/tracing/backend_type.h"

namespace perfetto {

// Applies policy decisions, such as allowing or denying connections, when
// certain tracing SDK events occur. All methods are called on an internal
// perfetto thread.
class PERFETTO_EXPORT_COMPONENT TracingPolicy {
 public:
  virtual ~TracingPolicy();

  // Called when the current process attempts to connect a new consumer to the
  // backend of |backend_type| to check if the connection should be allowed. Its
  // implementation should execute |result_callback| with the result of the
  // check (synchronuosly or asynchronously on any thread). If the result is
  // false, the consumer connection is aborted. Chrome uses this to restrict
  // creating (system) tracing sessions based on an enterprise policy.
  struct ShouldAllowConsumerSessionArgs {
    BackendType backend_type;
    std::function<void(bool /*allow*/)> result_callback;
  };
  virtual void ShouldAllowConsumerSession(
      const ShouldAllowConsumerSessionArgs&) = 0;
};

}  // namespace perfetto

#endif  // INCLUDE_PERFETTO_TRACING_TRACING_POLICY_H_
/*
 * Copyright (C) 2019 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.
 */


#ifndef INCLUDE_PERFETTO_TRACING_TRACING_H_
#define INCLUDE_PERFETTO_TRACING_TRACING_H_

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

#include <functional>
#include <memory>
#include <string>
#include <tuple>
#include <utility>
#include <vector>

// gen_amalgamated expanded: #include "perfetto/base/compiler.h"
// gen_amalgamated expanded: #include "perfetto/base/export.h"
// gen_amalgamated expanded: #include "perfetto/base/logging.h"
// gen_amalgamated expanded: #include "perfetto/tracing/backend_type.h"
// gen_amalgamated expanded: #include "perfetto/tracing/core/forward_decls.h"
// gen_amalgamated expanded: #include "perfetto/tracing/internal/in_process_tracing_backend.h"
// gen_amalgamated expanded: #include "perfetto/tracing/internal/system_tracing_backend.h"
// gen_amalgamated expanded: #include "perfetto/tracing/tracing_policy.h"

namespace perfetto {

namespace internal {
class TracingMuxerImpl;
}

class TracingBackend;
class Platform;
class StartupTracingSession;  // Declared below.
class TracingSession;         // Declared below.

struct TracingError {
  enum ErrorCode : uint32_t {
    // Peer disconnection.
    kDisconnected = 1,

    // The Start() method failed. This is typically because errors in the passed
    // TraceConfig. More details are available in |message|.
    kTracingFailed = 2,
  };

  ErrorCode code;
  std::string message;

  TracingError(ErrorCode cd, std::string msg)
      : code(cd), message(std::move(msg)) {
    PERFETTO_CHECK(!message.empty());
  }
};

using LogLev = ::perfetto::base::LogLev;
using LogMessageCallbackArgs = ::perfetto::base::LogMessageCallbackArgs;
using LogMessageCallback = ::perfetto::base::LogMessageCallback;

struct TracingInitArgs {
  uint32_t backends = 0;                     // One or more BackendTypes.
  TracingBackend* custom_backend = nullptr;  // [Optional].

  // [Optional] Platform implementation. It allows the embedder to take control
  // of platform-specific bits like thread creation and TLS slot handling. If
  // not set it will use Platform::GetDefaultPlatform().
  Platform* platform = nullptr;

  // [Optional] Tune the size of the shared memory buffer between the current
  // process and the service backend(s). This is a trade-off between memory
  // footprint and the ability to sustain bursts of trace writes (see comments
  // in shared_memory_abi.h).
  // If set, the value must be a multiple of 4KB. The value can be ignored if
  // larger than kMaxShmSize (32MB) or not a multiple of 4KB.
  uint32_t shmem_size_hint_kb = 0;

  // [Optional] Specifies the preferred size of each page in the shmem buffer.
  // This is a trade-off between IPC overhead and fragmentation/efficiency of
  // the shmem buffer in presence of multiple writer threads.
  // Must be one of [4, 8, 16, 32].
  uint32_t shmem_page_size_hint_kb = 0;

  // [Optional] The length of the period during which shared-memory-buffer
  // chunks that have been filled with data are accumulated (batched) on the
  // producer side, before the service is notified of them over an out-of-band
  // IPC call. If, while this period lasts, the shared memory buffer gets too
  // full, the IPC call will be sent immediately. The value of this parameter is
  // a trade-off between IPC traffic overhead and the ability to sustain bursts
  // of trace writes. The higher the value, the more chunks will be batched and
  // the less buffer space will be available to hide the latency of the service,
  // and vice versa. For more details, see the SetBatchCommitsDuration method in
  // shared_memory_arbiter.h.
  //
  // Note: With the default value of 0ms, batching still happens but with a zero
  // delay, i.e. commits will be sent to the service at the next opportunity.
  uint32_t shmem_batch_commits_duration_ms = 0;

  // [Optional] Enables direct producer-side patching of chunks that have not
  // yet been committed to the service. This flag will only have an effect
  // if the service supports direct patching, otherwise it will be ignored.
  bool shmem_direct_patching_enabled = false;

  // [Optional] If set, the policy object is notified when certain SDK events
  // occur and may apply policy decisions, such as denying connections. The
  // embedder is responsible for ensuring the object remains alive for the
  // lifetime of the process.
  TracingPolicy* tracing_policy = nullptr;

  // [Optional] If set, log messages generated by perfetto are passed to this
  // callback instead of being logged directly.
  LogMessageCallback log_message_callback = nullptr;

  // When this flag is set to false, it overrides
  // `DataSource::kSupportsMultipleInstances` for all the data sources.
  // As a result when a tracing session is already running and if we attempt to
  // start another session, it will fail to start the data source which were
  // already active.
  bool supports_multiple_data_source_instances = true;

  // If this flag is set the default clock for taking timestamps is overridden
  // with CLOCK_MONOTONIC (for use in Chrome).
  bool use_monotonic_clock = false;

  // If this flag is set the default clock for taking timestamps is overridden
  // with CLOCK_MONOTONIC_RAW on platforms that support it.
  bool use_monotonic_raw_clock = false;

  // This flag can be set to false in order to avoid enabling the system
  // consumer in Tracing::Initialize(), so that the linker can remove the unused
  // consumer IPC implementation to reduce binary size. This setting only has an
  // effect if kSystemBackend is specified in |backends|. When this option is
  // false, Tracing::NewTrace() will instatiate the system backend only if
  // explicitly specified as kSystemBackend: kUndefinedBackend will consider
  // only already instantiated backends.
  bool enable_system_consumer = true;

  // When true, sets disallow_merging_with_system_tracks in TrackDescriptor,
  // making sure that Trace Processor doesn't merge track event and system
  // event tracks for the same thread.
  bool disallow_merging_with_system_tracks = false;

  // If set, this function will be called by the producer client to create a
  // socket for connection to the system service. The function takes one
  // argument: a callback that takes an open file descriptor. The function
  // should create a socket with the name defined by
  // perfetto::GetProducerSocket(), connect to it, and return the corresponding
  // descriptor via the callback.
  // This is intended for the use-case where a process being traced is run
  // inside a sandbox and can't create sockets directly.
  // Not yet supported for consumer connections currently.
  CreateSocketAsync create_socket_async = nullptr;

 protected:
  friend class Tracing;
  friend class internal::TracingMuxerImpl;

  using BackendFactoryFunction = TracingBackend* (*)();
  using ProducerBackendFactoryFunction = TracingProducerBackend* (*)();
  using ConsumerBackendFactoryFunction = TracingConsumerBackend* (*)();

  BackendFactoryFunction in_process_backend_factory_ = nullptr;
  ProducerBackendFactoryFunction system_producer_backend_factory_ = nullptr;
  ConsumerBackendFactoryFunction system_consumer_backend_factory_ = nullptr;
  bool dcheck_is_on_ = PERFETTO_DCHECK_IS_ON();
};

// The entry-point for using perfetto.
class PERFETTO_EXPORT_COMPONENT Tracing {
 public:
  // Initializes Perfetto with the given backends in the calling process and/or
  // with a user-provided backend. It's possible to call this function more than
  // once to initialize different backends. If a backend was already initialized
  // the call will have no effect on it. All the members of `args` will be
  // ignored in subsequent calls, except those require to initialize new
  // backends (`backends`, `enable_system_consumer`, `shmem_size_hint_kb`,
  // `shmem_page_size_hint_kb` and `shmem_batch_commits_duration_ms`).
  static inline void Initialize(const TracingInitArgs& args)
      PERFETTO_ALWAYS_INLINE {
    TracingInitArgs args_copy(args);
    // This code is inlined to allow dead-code elimination for unused backends.
    // This saves ~200 KB when not using the in-process backend (b/148198993).
    // The logic behind it is the following:
    // Nothing other than the code below references the two GetInstance()
    // methods. From a linker-graph viewpoint, those GetInstance() pull in many
    // other pieces of the codebase (e.g. InProcessTracingBackend pulls the
    // whole TracingServiceImpl, SystemTracingBackend pulls the whole //ipc
    // layer). Due to the inline, the compiler can see through the code and
    // realize that some branches are always not taken. When that happens, no
    // reference to the backends' GetInstance() is emitted and that allows the
    // linker GC to get rid of the entire set of dependencies.
    if (args.backends & kInProcessBackend) {
      args_copy.in_process_backend_factory_ =
          &internal::InProcessTracingBackend::GetInstance;
    }
    if (args.backends & kSystemBackend) {
      args_copy.system_producer_backend_factory_ =
          &internal::SystemProducerTracingBackend::GetInstance;
      if (args.enable_system_consumer) {
        args_copy.system_consumer_backend_factory_ =
            &internal::SystemConsumerTracingBackend::GetInstance;
      }
    }
    InitializeInternal(args_copy);
  }

  // Checks if tracing has been initialized by calling |Initialize|.
  static bool IsInitialized();

  // Start a new tracing session using the given tracing backend. Use
  // |kUnspecifiedBackend| to select an available backend automatically.
  static PERFETTO_ALWAYS_INLINE inline std::unique_ptr<TracingSession> NewTrace(
      BackendType backend = kUnspecifiedBackend);

  // Shut down Perfetto, releasing any allocated OS resources (threads, files,
  // sockets, etc.). Note that Perfetto cannot be reinitialized again in the
  // same process[1]. Instead, this function is meant for shutting down all
  // Perfetto-related code so that it can be safely unloaded, e.g., with
  // dlclose().
  //
  // It is only safe to call this function when all threads recording trace
  // events have been terminated or otherwise guaranteed to not make any further
  // calls into Perfetto.
  //
  // [1] Unless static data is also cleared through other means.
  static void Shutdown();

  // Uninitialize Perfetto. Only exposed for testing scenarios where it can be
  // guaranteed that no tracing sessions or other operations are happening when
  // this call is made.
  static void ResetForTesting();

  // Start a new startup tracing session in the current process. Startup tracing
  // can be used in anticipation of a session that will be started by the
  // specified backend in the near future. The data source configs in the
  // supplied TraceConfig have to (mostly) match those in the config that will
  // later be provided by the backend.
  // Learn more about config matching at ComputeStartupConfigHash.
  //
  // Note that startup tracing requires that either:
  //  (a) the service backend already has an SMB set up, or
  //  (b) the service backend to support producer-provided SMBs if the backend
  //      is not yet connected or no SMB has been set up yet
  //      (See `use_producer_provided_smb`). If necessary, the
  //      client library will briefly disconnect and reconnect the backend to
  //      supply an SMB to the backend. If the service does not accept the SMB,
  //      startup tracing will be aborted, but the service may still start the
  //      corresponding tracing session later.
  //
  // Startup tracing is NOT supported with the in-process backend. For this
  // backend, you can just start a regular tracing session and block until it is
  // set up instead.
  //
  // The client library will start the data sources instances specified in the
  // config with a placeholder target buffer. Once the backend starts a matching
  // tracing session, the session will resume as normal. If no matching session
  // is started after a timeout (or the backend doesn't accept the
  // producer-provided SMB), the startup tracing session will be aborted
  // and the data source instances stopped.
  struct OnStartupTracingSetupCallbackArgs {
    int num_data_sources_started;
  };
  struct SetupStartupTracingOpts {
    BackendType backend = kUnspecifiedBackend;
    uint32_t timeout_ms = 10000;

    // If set, this callback is executed (on an internal Perfetto thread) when
    // startup tracing was set up.
    std::function<void(OnStartupTracingSetupCallbackArgs)> on_setup;

    // If set, this callback is executed (on an internal Perfetto thread) if any
    // data sources were aborted, e.g. due to exceeding the timeout or as a
    // response to Abort().
    std::function<void()> on_aborted;

    // If set, this callback is executed (on an internal Perfetto thread) after
    // all data sources were adopted by a tracing session initiated by the
    // backend.
    std::function<void()> on_adopted;
  };

  static std::unique_ptr<StartupTracingSession> SetupStartupTracing(
      const TraceConfig& config,
      SetupStartupTracingOpts);

  // Blocking version of above method, so callers can ensure that tracing is
  // active before proceeding with app startup. Calls into
  // DataSource::Trace() or trace macros right after this method are written
  // into the startup session.
  static std::unique_ptr<StartupTracingSession> SetupStartupTracingBlocking(
      const TraceConfig& config,
      SetupStartupTracingOpts);

  // Informs the tracing services to activate any of these triggers if any
  // tracing session was waiting for them.
  //
  // Sends the trigger signal to all the initialized backends that are currently
  // connected and that connect in the next `ttl_ms` milliseconds (but
  // returns immediately anyway).
  static void ActivateTriggers(const std::vector<std::string>& triggers,
                               uint32_t ttl_ms);

 private:
  static void InitializeInternal(const TracingInitArgs&);
  static std::unique_ptr<TracingSession> NewTraceInternal(
      BackendType,
      TracingConsumerBackend* (*system_backend_factory)());

  Tracing() = delete;
};

class PERFETTO_EXPORT_COMPONENT TracingSession {
 public:
  virtual ~TracingSession();

  // Configure the session passing the trace config.
  // If a writable file handle is given through |fd|, the trace will
  // automatically written to that file. Otherwise you should call ReadTrace()
  // to retrieve the trace data. This call does not take ownership of |fd|.
  // TODO(primiano): add an error callback.
  virtual void Setup(const TraceConfig&, int fd = -1) = 0;

  // Enable tracing asynchronously. Use SetOnStartCallback() to get a
  // notification when the session has fully started.
  virtual void Start() = 0;

  // Enable tracing and block until tracing has started. Note that if data
  // sources are registered after this call was initiated, the call may return
  // before the additional data sources have started. Also, if other producers
  // (e.g., with system-wide tracing) have registered data sources without start
  // notification support, this call may return before those data sources have
  // started.
  virtual void StartBlocking() = 0;

  // Struct passed as argument to the callback passed to CloneTrace().
  struct CloneTraceCallbackArgs {
    bool success;
    std::string error;
    // UUID of the cloned session.
    int64_t uuid_msb;
    int64_t uuid_lsb;
  };

  // Struct passed as argument to CloneTrace().
  struct CloneTraceArgs {
    // The unique_session_name of the session that should be cloned.
    std::string unique_session_name;
  };

  // Clones an existing initialized tracing session from the same `BackendType`
  // as this tracing session, and attaches to it. The session is cloned in
  // read-only mode and can only be used to read a snapshot of an existing
  // tracing session. For each session, only one CloneTrace call can be pending
  // at the same time; subsequent calls after the callback is executed are
  // supported.
  using CloneTraceCallback = std::function<void(CloneTraceCallbackArgs)>;
  virtual void CloneTrace(CloneTraceArgs args, CloneTraceCallback);

  // This callback will be invoked when all data sources have acknowledged that
  // tracing has started. This callback will be invoked on an internal perfetto
  // thread.
  virtual void SetOnStartCallback(std::function<void()>) = 0;

  // This callback can be used to get a notification when some error occurred
  // (e.g., peer disconnection). Error type will be passed as an argument. This
  // callback will be invoked on an internal perfetto thread.
  virtual void SetOnErrorCallback(std::function<void(TracingError)>) = 0;

  // Issues a flush request, asking all data sources to ack the request, within
  // the specified timeout. A "flush" is a fence to ensure visibility of data in
  // the async tracing pipeline. It guarantees that all data written before the
  // Flush() call will be visible in the trace buffer and hence by the
  // ReadTrace() / ReadTraceBlocking() methods.
  // Args:
  //  callback: will be invoked on an internal perfetto thread when all data
  //    sources have acked, or the timeout is reached. The bool argument
  //    will be true if all data sources acked within the timeout, false if
  //    the timeout was hit or some other error occurred (e.g. the tracing
  //    session wasn't started or ended).
  //  timeout_ms: how much time the service will wait for data source acks. If
  //    0, the global timeout specified in the TraceConfig (flush_timeout_ms)
  //    will be used. If flush_timeout_ms is also unspecified, a default value
  //    of 5s will be used.
  // Known issues:
  //    Because flushing is still based on service-side scraping, the very last
  //    trace packet for each data source thread will not be visible. Fixing
  //    this requires either propagating the Flush() to the data sources or
  //    changing the order of atomic operations in the service (b/162206162).
  //    Until then, a workaround is to make sure to call
  //    DataSource::Trace([](TraceContext ctx) { ctx.Flush(); }) just before
  //    stopping, on each thread where DataSource::Trace has been previously
  //    called.
  virtual void Flush(std::function<void(bool)>, uint32_t timeout_ms = 0) = 0;

  // Blocking version of Flush(). Waits until all data sources have acked and
  // returns the success/failure status.
  bool FlushBlocking(uint32_t timeout_ms = 0);

  // Disable tracing asynchronously.
  // Use SetOnStopCallback() to get a notification when the tracing session is
  // fully stopped and all data sources have acked.
  virtual void Stop() = 0;

  // Disable tracing and block until tracing has stopped.
  virtual void StopBlocking() = 0;

  // This callback will be invoked when tracing is disabled.
  // This can happen either when explicitly calling TracingSession.Stop() or
  // when the trace reaches its |duration_ms| time limit.
  // This callback will be invoked on an internal perfetto thread.
  virtual void SetOnStopCallback(std::function<void()>) = 0;

  // Changes the TraceConfig for an active tracing session. The session must
  // have been configured and started before. Note that the tracing service
  // only supports changing a subset of TraceConfig fields,
  // see ConsumerEndpoint::ChangeTraceConfig().
  virtual void ChangeTraceConfig(const TraceConfig&) = 0;

  // Struct passed as argument to the callback passed to ReadTrace().
  // [data, size] is guaranteed to contain 1 or more full trace packets, which
  // can be decoded using trace.proto. No partial or truncated packets are
  // exposed. If the trace is empty this returns a zero-sized nullptr with
  // |has_more| == true to signal EOF.
  // This callback will be invoked on an internal perfetto thread.
  struct ReadTraceCallbackArgs {
    const char* data = nullptr;
    size_t size = 0;

    // When false, this will be the last invocation of the callback for this
    // read cycle.
    bool has_more = false;
  };

  // Reads back the trace data (raw protobuf-encoded bytes) asynchronously.
  // Can be called at any point during the trace, typically but not necessarily,
  // after stopping. If this is called before the end of the trace (i.e. before
  // Stop() / StopBlocking()), in almost all cases you need to call
  // Flush() / FlushBlocking() before Read(). This is to guarantee that tracing
  // data in-flight in the data sources is committed into the tracing buffers
  // before reading them.
  // Reading the trace data is a destructive operation w.r.t. contents of the
  // trace buffer and is not idempotent.
  // A single ReadTrace() call can yield >1 callback invocations, until
  // |has_more| is false.
  using ReadTraceCallback = std::function<void(ReadTraceCallbackArgs)>;
  virtual void ReadTrace(ReadTraceCallback) = 0;

  // Synchronous version of ReadTrace(). It blocks the calling thread until all
  // the trace contents are read. This is slow and inefficient (involves more
  // copies) and is mainly intended for testing.
  std::vector<char> ReadTraceBlocking();

  // Struct passed as an argument to the callback for GetTraceStats(). Contains
  // statistics about the tracing session.
  struct GetTraceStatsCallbackArgs {
    // Whether or not querying statistics succeeded.
    bool success = false;
    // Serialized TraceStats protobuf message. To decode:
    //
    //   perfetto::protos::gen::TraceStats trace_stats;
    //   trace_stats.ParseFromArray(args.trace_stats_data.data(),
    //                              args.trace_stats_data.size());
    //
    std::vector<uint8_t> trace_stats_data;
  };

  // Requests a snapshot of statistical data for this tracing session. Only one
  // query may be active at a time. This callback will be invoked on an internal
  // perfetto thread.
  using GetTraceStatsCallback = std::function<void(GetTraceStatsCallbackArgs)>;
  virtual void GetTraceStats(GetTraceStatsCallback) = 0;

  // Synchronous version of GetTraceStats() for convenience.
  GetTraceStatsCallbackArgs GetTraceStatsBlocking();

  // Struct passed as an argument to the callback for QueryServiceState().
  // Contains information about registered data sources.
  struct QueryServiceStateCallbackArgs {
    // Whether or not getting the service state succeeded.
    bool success = false;
    // Serialized TracingServiceState protobuf message. To decode:
    //
    //   perfetto::protos::gen::TracingServiceState state;
    //   state.ParseFromArray(args.service_state_data.data(),
    //                        args.service_state_data.size());
    //
    std::vector<uint8_t> service_state_data;
  };

  // Requests a snapshot of the tracing service state for this session. Only one
  // request per session may be active at a time. This callback will be invoked
  // on an internal perfetto thread.
  using QueryServiceStateCallback =
      std::function<void(QueryServiceStateCallbackArgs)>;
  virtual void QueryServiceState(QueryServiceStateCallback) = 0;

  // Synchronous version of QueryServiceState() for convenience.
  QueryServiceStateCallbackArgs QueryServiceStateBlocking();
};

class PERFETTO_EXPORT_COMPONENT StartupTracingSession {
 public:
  // Note that destroying the StartupTracingSession object will not abort the
  // startup session automatically. Call Abort() explicitly to do so.
  virtual ~StartupTracingSession();

  // Abort any active but still unbound data source instances that belong to
  // this startup tracing session. Does not affect data source instances that
  // were already bound to a service-controlled session.
  virtual void Abort() = 0;

  // Same as above, but blocks the current thread until aborted.
  // Note some of the internal (non observable from public APIs) cleanup might
  // be done even after this method returns.
  virtual void AbortBlocking() = 0;
};

PERFETTO_ALWAYS_INLINE inline std::unique_ptr<TracingSession> Tracing::NewTrace(
    BackendType backend) {
  // This code is inlined to allow dead-code elimination for unused consumer
  // implementation. The logic behind it is the following:
  // Nothing other than the code below references the GetInstance() method
  // below. From a linker-graph viewpoint, those GetInstance() pull in many
  // other pieces of the codebase (ConsumerOnlySystemTracingBackend pulls
  // ConsumerIPCClient). Due to the inline, the compiler can see through the
  // code and realize that some branches are always not taken. When that
  // happens, no reference to the backends' GetInstance() is emitted and that
  // allows the linker GC to get rid of the entire set of dependencies.
  TracingConsumerBackend* (*system_backend_factory)();
  system_backend_factory = nullptr;
  // In case PERFETTO_IPC is disabled, a fake system backend is used, which
  // always panics. NewTrace(kSystemBackend) should fail if PERFETTO_IPC is
  // diabled, not panic.
#if PERFETTO_BUILDFLAG(PERFETTO_IPC)
  if (backend & kSystemBackend) {
    system_backend_factory =
        &internal::SystemConsumerTracingBackend::GetInstance;
  }
#endif
  return NewTraceInternal(backend, system_backend_factory);
}

}  // namespace perfetto

#endif  // INCLUDE_PERFETTO_TRACING_TRACING_H_
/*
 * Copyright (C) 2019 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.
 */


#ifndef INCLUDE_PERFETTO_TRACING_PLATFORM_H_
#define INCLUDE_PERFETTO_TRACING_PLATFORM_H_

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

#include <functional>
#include <memory>
#include <string>

// gen_amalgamated expanded: #include "perfetto/base/export.h"
// gen_amalgamated expanded: #include "perfetto/base/logging.h"
// gen_amalgamated expanded: #include "perfetto/base/proc_utils.h"
// gen_amalgamated expanded: #include "perfetto/base/thread_utils.h"
// gen_amalgamated expanded: #include "perfetto/tracing/tracing.h"

namespace perfetto {

namespace base {
class TaskRunner;
}  // namespace base

// This abstract class is used to abstract dependencies on platform-specific
// primitives that cannot be implemented by the perfetto codebase and must be
// provided or overridden by the embedder.
// This is, for instance, for cases where we want to use some particular
// base:: class in Chrome and provide instead POSIX fallbacks for other
// embedders.

// Base class for thread-local objects. This is to get a basic object vtable and
// delegate destruction to the embedder. See Platform::CreateThreadLocalObject.
class PERFETTO_EXPORT_COMPONENT PlatformThreadLocalObject {
 public:
  // Implemented by perfetto internal code. The embedder must call this when
  // implementing GetOrCreateThreadLocalObject() to create an instance for the
  // first time on each thread.
  static std::unique_ptr<PlatformThreadLocalObject> CreateInstance();
  virtual ~PlatformThreadLocalObject();
};

class PERFETTO_EXPORT_COMPONENT Platform {
 public:
  // Embedders can use this unless they have custom needs (e.g. Chrome wanting
  // to use its own base class for TLS).
  static Platform* GetDefaultPlatform();

  // Embedders can call this to set process ID in those cases where getpid()
  // returns incorrect values (e.g. for sandboxed processes in Chromium).
  // Should only be called once, before tracing has been initialized.
  static void SetCurrentProcessId(base::PlatformProcessId process_id) {
    PERFETTO_CHECK(!process_id_);
    PERFETTO_DCHECK(!Tracing::IsInitialized());
    process_id_ = process_id;
  }

  // Returns process ID previously set by SetCurrentProcessId, or the process
  // ID provided by the OS if no custom ID was provided.
  static base::PlatformProcessId GetCurrentProcessId() {
    if (process_id_)
      return process_id_;
    return base::GetProcessId();
  }

  virtual ~Platform();

  // Creates a thread-local object. The embedder must:
  // - Create an instance per-thread calling ThreadLocalObject::CreateInstance.
  // - Own the lifetime of the returned object as long as the thread is alive.
  // - Destroy it when the thread exits.
  // Perfetto requires only one thread-local object overall (obviously, one
  // instance per-thread) from the embedder.
  using ThreadLocalObject = ::perfetto::PlatformThreadLocalObject;
  virtual ThreadLocalObject* GetOrCreateThreadLocalObject() = 0;

  // Creates a sequenced task runner. The easiest implementation is to create
  // a new thread (e.g. use base::ThreadTaskRunner) but this can also be
  // implemented in some more clever way (e.g. using chromiums's scheduler).
  struct CreateTaskRunnerArgs {
    // Optional. Sets the name to the newly created task runner. In the default
    // PosixPlatform implementation this causes a pthread_setname_np(). This is
    // only for ease of debugging, it does not affect the tracing behavior.
    std::string name_for_debugging;
  };
  virtual std::unique_ptr<base::TaskRunner> CreateTaskRunner(
      const CreateTaskRunnerArgs&) = 0;

  // Used to derive the producer name. Mostly relevant when using the
  // kSystemBackend mode. It can be an arbitrary string when using the
  // in-process mode.
  virtual std::string GetCurrentProcessName() = 0;

  // Tear down any persistent platform state (e.g., TLS variables). The platform
  // interface must not be used after calling this function.
  virtual void Shutdown();

  // Returns the thread ID provided by the OS by default. Chromium uses
  // different thread IDs on some platforms, so it needs the ability to
  // override this method.
  virtual base::PlatformThreadId GetCurrentThreadId();

 private:
  static base::PlatformProcessId process_id_;
};

}  // namespace perfetto

#endif  // INCLUDE_PERFETTO_TRACING_PLATFORM_H_
/*
 * Copyright (C) 2019 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.
 */


#ifndef INCLUDE_PERFETTO_TRACING_INTERNAL_TRACING_TLS_H_
#define INCLUDE_PERFETTO_TRACING_INTERNAL_TRACING_TLS_H_

#include <array>
#include <memory>

// gen_amalgamated expanded: #include "perfetto/tracing/internal/basic_types.h"
// gen_amalgamated expanded: #include "perfetto/tracing/internal/data_source_internal.h"
// gen_amalgamated expanded: #include "perfetto/tracing/platform.h"

namespace perfetto {

class TraceWriterBase;

namespace internal {

// Organization of the thread-local storage
// ----------------------------------------
// First of all, remember the cardinality of the problem: at any point in time
// there are M data sources registered (i.e. number of subclasses of DataSource)
// and up to N concurrent instances for each data source, so up to M * N total
// data source instances around.
// Each data source instance can be accessed by T threads (no upper bound).
// We can safely put hard limits both to M and N (i.e. say that we support at
// most 32 data source types per process and up to 8 concurrent instances).
//
// We want to make it so from the Platform viewpoint, we use only one global
// TLS object, so T instances in total, one per thread, regardless of M and N.
// This allows to deal with at-thread-exit destruction only in one place, rather
// than N, M or M * N.
//
// Visually:
//                     [    Thread 1   ] [    Thread 2   ] [    Thread T   ]
//                     +---------------+ +---------------+ +---------------+
// Data source Foo     |               | |               | |               |
//  Instance 1         |     TLS       | |     TLS       | |     TLS       |
//  Instance 2         |    Object     | |    Object     | |    Object     |
//  Instance 3         |               | |               | |               |
//                     |               | |               | |               |
// Data source Bar     |               | |               | |               |
//  Instance 1         |               | |               | |               |
//  Instance 2         |               | |               | |               |
//                     +---------------+ +---------------+ +---------------+
//
// Each TLS Object is organized as an array of M DataSourceThreadLocalState.
// Each DSTLS itself is an array of up to N per-instance objects.
// The only per-instance object for now is the TraceWriter.
// So for each data source, for each instance, for each thread we keep one
// TraceWriter.
// The lookup is O(1): Given the TLS object, the TraceWriter is just tls[M][N].
class TracingTLS : public Platform::ThreadLocalObject {
 public:
  ~TracingTLS() override;

  // This is checked against TraceMuxerImpl's global generation counter to
  // handle destruction of TraceWriter(s) that belong to data sources that
  // have been stopped. When the two numbers diverge, a scan of all the
  // thread-local TraceWriter(s) is issued.
  uint32_t generation = 0;

  // This flag is true while this thread is inside a trace point for any data
  // source or in other delicate parts of the tracing machinery during which we
  // should not try to trace. Used to prevent unexpected re-entrancy.
  // This flag is also load-bearing when handling re-entrancy during thread-exit
  // handlers. See comment in TracingTLS::~TracingTLS().
  bool is_in_trace_point = false;

  // Used inside a trace point (only one trace point per thread can be active at
  // any time) to cache the instances bitmap.
  uint32_t cached_instances = 0;

  // By default all data source instances have independent thread-local state
  // (see above).
  std::array<DataSourceThreadLocalState, kMaxDataSources> data_sources_tls{};

  // Track event data sources, however, share the same thread-local state in
  // order to be able to share trace writers and interning state across all
  // track event categories.
  DataSourceThreadLocalState track_event_tls{};
};

struct ScopedReentrancyAnnotator {
  ScopedReentrancyAnnotator(TracingTLS& root_tls) : root_tls_(root_tls) {
    PERFETTO_DCHECK(!root_tls_.is_in_trace_point);
    root_tls_.is_in_trace_point = true;
  }
  ~ScopedReentrancyAnnotator() { root_tls_.is_in_trace_point = false; }

 private:
  TracingTLS& root_tls_;
};

}  // namespace internal
}  // namespace perfetto

#endif  // INCLUDE_PERFETTO_TRACING_INTERNAL_TRACING_TLS_H_
/*
 * Copyright (C) 2019 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.
 */


#ifndef INCLUDE_PERFETTO_TRACING_INTERNAL_TRACING_MUXER_H_
#define INCLUDE_PERFETTO_TRACING_INTERNAL_TRACING_MUXER_H_

#include <atomic>
#include <memory>

// gen_amalgamated expanded: #include "perfetto/base/export.h"
// gen_amalgamated expanded: #include "perfetto/tracing/core/forward_decls.h"
// gen_amalgamated expanded: #include "perfetto/tracing/interceptor.h"
// gen_amalgamated expanded: #include "perfetto/tracing/internal/basic_types.h"
// gen_amalgamated expanded: #include "perfetto/tracing/internal/tracing_tls.h"
// gen_amalgamated expanded: #include "perfetto/tracing/platform.h"
namespace perfetto {

class DataSourceBase;
class TraceWriterBase;
struct TracingInitArgs;
class TracingSession;

namespace internal {

struct DataSourceParams {
  bool supports_multiple_instances;
  bool requires_callbacks_under_lock;
};

struct DataSourceStaticState;

// This class acts as a bridge between the public API methods and the
// TracingBackend(s). It exposes a simplified view of the world to the API
// methods, so that they don't have to care about the multiplicity of backends.
// It handles all the bookkeeping to map data source instances and trace writers
// to the various backends.
// See tracing_muxer_impl.h for the full picture. This class contains only the
// fewer fields and methods that need to be exposed to public/ headers. Fields
// and methods that are required to implement them should go into
// src/tracing/internal/tracing_muxer_impl.h instead: that one can pull in
// perfetto headers outside of public, this one cannot.
class PERFETTO_EXPORT_COMPONENT TracingMuxer {
 public:
  static TracingMuxer* Get() { return instance_; }

  virtual ~TracingMuxer();

  TracingTLS* GetOrCreateTracingTLS() {
    return static_cast<TracingTLS*>(platform_->GetOrCreateThreadLocalObject());
  }

  // This method can fail and return false if trying to register more than
  // kMaxDataSources types.
  using DataSourceFactory = std::function<std::unique_ptr<DataSourceBase>()>;
  virtual bool RegisterDataSource(const DataSourceDescriptor&,
                                  DataSourceFactory,
                                  DataSourceParams,
                                  bool no_flush,
                                  DataSourceStaticState*) = 0;

  // Updates the DataSourceDescriptor for the DataSource.
  virtual void UpdateDataSourceDescriptor(const DataSourceDescriptor&,
                                          const DataSourceStaticState*) = 0;

  // It identifies the right backend and forwards the call to it.
  // The returned TraceWriter must be used within the same sequence (for most
  // projects this means "same thread"). Alternatively the client needs to take
  // care of using synchronization primitives to prevent concurrent accesses.
  virtual std::unique_ptr<TraceWriterBase> CreateTraceWriter(
      DataSourceStaticState*,
      uint32_t data_source_instance_index,
      DataSourceState*,
      BufferExhaustedPolicy buffer_exhausted_policy) = 0;

  virtual void DestroyStoppedTraceWritersForCurrentThread() = 0;

  uint32_t generation(std::memory_order ord) { return generation_.load(ord); }

  using InterceptorFactory = std::function<std::unique_ptr<InterceptorBase>()>;
  virtual void RegisterInterceptor(const InterceptorDescriptor&,
                                   InterceptorFactory,
                                   InterceptorBase::TLSFactory,
                                   InterceptorBase::TracePacketCallback) = 0;

  // Informs the tracing services to activate any of these triggers if any
  // tracing session was waiting for them.
  //
  // Sends the trigger signal to all the initialized backends that are currently
  // connected and that connect in the next `ttl_ms` milliseconds (but returns
  // immediately anyway).
  virtual void ActivateTriggers(const std::vector<std::string>&,
                                uint32_t ttl_ms) = 0;

  base::PlatformThreadId GetCurrentThreadId() {
    return platform_->GetCurrentThreadId();
  }

 protected:
  explicit TracingMuxer(Platform* platform) : platform_(platform) {}

  static TracingMuxer* instance_;
  Platform* const platform_ = nullptr;

  // Incremented every time a data source is destroyed. See tracing_tls.h.
  std::atomic<uint32_t> generation_{};
};

}  // namespace internal
}  // namespace perfetto

#endif  // INCLUDE_PERFETTO_TRACING_INTERNAL_TRACING_MUXER_H_
#ifndef INCLUDE_PERFETTO_TRACING_INTERNAL_DATA_SOURCE_TYPE_H_
#define INCLUDE_PERFETTO_TRACING_INTERNAL_DATA_SOURCE_TYPE_H_

// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
// gen_amalgamated expanded: #include "perfetto/base/export.h"
// gen_amalgamated expanded: #include "perfetto/tracing/core/forward_decls.h"
// gen_amalgamated expanded: #include "perfetto/tracing/internal/data_source_internal.h"
// gen_amalgamated expanded: #include "perfetto/tracing/internal/tracing_muxer.h"

namespace perfetto {
namespace internal {

// Represents a data source type (not an instance).
//
// All the static state of a DataSource<T> lives here (including
// DataSourceStaticState).
//
// The C shared library API wrapper cannot use DataSource<T>, because it needs
// to create new data source types at runtime, so it uses this directly.
//
// The main reason why this intermediate class exist is to decouple the
// DataSourceStaticState from the specific DataSource<T>. The C API cannot
// dynamically create template instances and it needs a way to decouple those at
// runtime.
class PERFETTO_EXPORT_COMPONENT DataSourceType {
 public:
  // Function pointer type used to create custom per instance thread local
  // state.
  using CreateCustomTlsFn =
      DataSourceInstanceThreadLocalState::ObjectWithDeleter (*)(
          DataSourceInstanceThreadLocalState* tls_inst,
          uint32_t instance_index,
          void* user_arg);
  // Function pointer type used to create custom per instance thread local
  // incremental state (which might be cleared periodically by the tracing
  // service).
  using CreateIncrementalStateFn =
      DataSourceInstanceThreadLocalState::ObjectWithDeleter (*)(
          DataSourceInstanceThreadLocalState* tls_inst,
          uint32_t instance_index,
          void* user_arg);

  // Registers the data source type with the central tracing muxer.
  // * `descriptor` is the data source protobuf descriptor.
  // * `factory` is a std::function used to create instances of the data source
  //   type.
  // * `buffer_exhausted_policy` specifies what to do when the shared memory
  //   buffer runs out of chunks.
  // * `create_custom_tls_fn` and `create_incremental_state_fn` are function
  //   pointers called to create custom state. They will receive `user_arg` as
  //   an extra param.
  bool Register(const DataSourceDescriptor& descriptor,
                TracingMuxer::DataSourceFactory factory,
                internal::DataSourceParams params,
                BufferExhaustedPolicy buffer_exhausted_policy,
                bool no_flush,
                CreateCustomTlsFn create_custom_tls_fn,
                CreateIncrementalStateFn create_incremental_state_fn,
                void* user_arg) {
    buffer_exhausted_policy_ = buffer_exhausted_policy;
    create_custom_tls_fn_ = create_custom_tls_fn;
    create_incremental_state_fn_ = create_incremental_state_fn;
    user_arg_ = user_arg;
    auto* tracing_impl = TracingMuxer::Get();
    return tracing_impl->RegisterDataSource(descriptor, factory, params,
                                            no_flush, &state_);
  }

  // Updates the data source type descriptor.
  void UpdateDescriptor(const DataSourceDescriptor& descriptor) {
    auto* tracing_impl = TracingMuxer::Get();
    tracing_impl->UpdateDataSourceDescriptor(descriptor, &state_);
  }

  // The beginning of a trace point.
  //
  // `tls_state` must point to a thread local variable that caches a pointer to
  // an internal per data source type thread local state.
  //
  // `instances` must point to a copy of the current active instances for the
  // data source type.
  //
  // `DataSourceTraits` can be used to customize the thread local storage used
  // for the data source type.
  //
  // `TracePointTraits` and `trace_point_data` are customization point for
  // getting the active instances bitmap.
  //
  // If this returns false, the trace point must be skipped.
  template <typename DataSourceTraits, typename TracePointTraits>
  bool TracePrologue(
      DataSourceThreadLocalState** tls_state,
      uint32_t* instances,
      typename TracePointTraits::TracePointData trace_point_data) {
    // See tracing_muxer.h for the structure of the TLS.
    if (PERFETTO_UNLIKELY(!*tls_state)) {
      *tls_state = GetOrCreateDataSourceTLS<DataSourceTraits>();
      // If the TLS hasn't been obtained yet, it's possible that this thread
      // hasn't observed the initialization of global state like the muxer yet.
      // To ensure that the thread "sees" the effects of such initialization,
      // we have to reload |instances| with an acquire fence, ensuring that any
      // initialization performed before instances was updated is visible
      // in this thread.
      *instances &= TracePointTraits::GetActiveInstances(trace_point_data)
                        ->load(std::memory_order_acquire);
      if (!*instances)
        return false;
    }
    auto* tracing_impl = TracingMuxer::Get();

    // Avoid re-entering the trace point recursively.
    if (PERFETTO_UNLIKELY((*tls_state)->root_tls->is_in_trace_point))
      return false;

    (*tls_state)->root_tls->is_in_trace_point = true;

    // TracingTLS::generation is a global monotonic counter that is incremented
    // every time a tracing session is stopped. We use that as a signal to force
    // a slow-path garbage collection of all the trace writers for the current
    // thread and to destroy the ones that belong to tracing sessions that have
    // ended. This is to avoid having too many TraceWriter instances alive, each
    // holding onto one chunk of the shared memory buffer.
    // Rationale why memory_order_relaxed should be fine:
    // - The TraceWriter object that we use is always constructed and destructed
    //   on the current thread. There is no risk of accessing a half-initialized
    //   TraceWriter (which would be really bad).
    // - In the worst case, in the case of a race on the generation check, we
    //   might end up using a TraceWriter for the same data source that belongs
    //   to a stopped session. This is not really wrong, as we don't give any
    //   guarantee on the global atomicity of the stop. In the worst case the
    //   service will reject the data commit if this arrives too late.

    if (PERFETTO_UNLIKELY(
            (*tls_state)->root_tls->generation !=
            tracing_impl->generation(std::memory_order_relaxed))) {
      // Will update root_tls->generation.
      tracing_impl->DestroyStoppedTraceWritersForCurrentThread();
    }

    return true;
  }

  // Must be called at the ending of a trace point that was not skipped.
  void TraceEpilogue(DataSourceThreadLocalState* tls_state) {
    tls_state->root_tls->is_in_trace_point = false;
  }

  struct InstancesIterator {
    // A bitmap of the currenly active instances.
    uint32_t cached_instances;
    // The current instance index.
    uint32_t i;
    // The current instance. If this is `nullptr`, the iteration is over.
    DataSourceInstanceThreadLocalState* instance;
  };

  // Returns an iterator to the active instances of this data source type.
  //
  // `cached_instances` is a copy of the bitmap of the active instances for this
  // data source type (usually just a copy of ValidInstances(), but can be
  // customized).
  //
  // `tls_state` is the thread local pointer obtained from TracePrologue.
  //
  // `TracePointTraits` and `trace_point_data` are customization point for
  // getting the active instances bitmap.
  template <typename TracePointTraits>
  InstancesIterator BeginIteration(
      uint32_t cached_instances,
      DataSourceThreadLocalState* tls_state,
      typename TracePointTraits::TracePointData trace_point_data) {
    InstancesIterator it{};
    it.cached_instances = cached_instances;
    FirstActiveInstance<TracePointTraits>(&it, tls_state, trace_point_data);
    return it;
  }

  // Advances `*iterator` to point to the next active instance of this data
  // source type.
  //
  // `tls_state` is the thread local pointer obtained from TracePrologue.
  //
  // `TracePointTraits` and `trace_point_data` are customization point for
  // getting the active instances bitmap.
  template <typename TracePointTraits>
  void NextIteration(
      InstancesIterator* iterator,
      DataSourceThreadLocalState* tls_state,
      typename TracePointTraits::TracePointData trace_point_data) {
    iterator->i++;
    FirstActiveInstance<TracePointTraits>(iterator, tls_state,
                                          trace_point_data);
  }

  void* GetIncrementalState(
      internal::DataSourceInstanceThreadLocalState* tls_inst,
      uint32_t instance_index) {
    // Recreate incremental state data if it has been reset by the service.
    if (tls_inst->incremental_state_generation !=
        static_state()->GetUnsafe(instance_index)->incremental_state_generation.load(
            std::memory_order_relaxed)) {
      tls_inst->incremental_state.reset();
      CreateIncrementalState(tls_inst, instance_index);
    }
    return tls_inst->incremental_state.get();
  }

  std::atomic<uint32_t>* valid_instances() { return &state_.valid_instances; }

  DataSourceStaticState* static_state() { return &state_; }

 private:
  void CreateIncrementalState(
      internal::DataSourceInstanceThreadLocalState* tls_inst,
      uint32_t instance_index) {
    PERFETTO_DCHECK(create_incremental_state_fn_ != nullptr);
    tls_inst->incremental_state =
        create_incremental_state_fn_(tls_inst, instance_index, user_arg_);
    tls_inst->incremental_state_generation =
        static_state()->GetUnsafe(instance_index)->incremental_state_generation.load(
            std::memory_order_relaxed);
  }

  void PopulateTlsInst(DataSourceInstanceThreadLocalState* tls_inst,
                       DataSourceState* instance_state,
                       uint32_t instance_index);

  // Advances `*iterator` to the first active instance whose index is greater or
  // equal than `iterator->i`.
  template <typename TracePointTraits>
  void FirstActiveInstance(
      InstancesIterator* iterator,
      DataSourceThreadLocalState* tls_state,
      typename TracePointTraits::TracePointData trace_point_data) {
    iterator->instance = nullptr;
    for (; iterator->i < kMaxDataSourceInstances; iterator->i++) {
      DataSourceState* instance_state =
          state_.TryGetCached(iterator->cached_instances, iterator->i);
      if (!instance_state)
        continue;
      // Even if we passed the check above, the DataSourceInstance might be
      // still destroyed concurrently while this code runs. The code below is
      // designed to deal with such race, as follows:
      // - We don't access the user-defined data source instance state. The only
      //   bits of state we use are |backend_id| and |buffer_id|.
      // - Beyond those two integers, we access only the TraceWriter here. The
      //   TraceWriter is always safe because it lives on the TLS.
      // - |instance_state| is backed by static storage, so the pointer is
      //   always valid, even after the data source instance is destroyed.
      // - In the case of a race-on-destruction, we'll still see the latest
      //   backend_id and buffer_id and in the worst case keep trying writing
      //   into the tracing shared memory buffer after stopped. But this isn't
      //   really any worse than the case of the stop IPC being delayed by the
      //   kernel scheduler. The tracing service is robust against data commit
      //   attemps made after tracing is stopped.
      // There is a theoretical race that would case the wrong behavior w.r.t
      // writing data in the wrong buffer, but it's so rare that we ignore it:
      // if the data source is stopped and started kMaxDataSourceInstances
      // times (so that the same id is recycled) while we are in this function,
      // we might end up reusing the old data source's backend_id and buffer_id
      // for the new one, because we don't see the generation change past this
      // point. But stopping and starting tracing (even once) takes so much
      // handshaking to make this extremely unrealistic.

      auto& tls_inst = tls_state->per_instance[iterator->i];
      if (PERFETTO_UNLIKELY(!tls_inst.trace_writer)) {
        // Here we need an acquire barrier, which matches the release-store made
        // by TracingMuxerImpl::SetupDataSource(), to ensure that the backend_id
        // and buffer_id are consistent.
        iterator->cached_instances &=
            TracePointTraits::GetActiveInstances(trace_point_data)
                ->load(std::memory_order_acquire);
        instance_state =
            state_.TryGetCached(iterator->cached_instances, iterator->i);
        if (!instance_state || !instance_state->trace_lambda_enabled.load(
                                   std::memory_order_relaxed))
          continue;
        PopulateTlsInst(&tls_inst, instance_state, iterator->i);
      }
      iterator->instance = &tls_inst;
      break;
    }
  }

  // Note that the returned object is one per-thread per-data-source-type, NOT
  // per data-source *instance*.
  template <typename DataSourceTraits>
  DataSourceThreadLocalState* GetOrCreateDataSourceTLS() {
    auto* tracing_impl = TracingMuxer::Get();
    TracingTLS* root_tls = tracing_impl->GetOrCreateTracingTLS();
    DataSourceThreadLocalState* ds_tls =
        DataSourceTraits::GetDataSourceTLS(&state_, root_tls);
    // We keep re-initializing as the initialization is idempotent and not worth
    // the code for extra checks. Also, ds_tls->static_state might point to
    // another data source if ResetForTesting() has been used.
    ds_tls->static_state = &state_;
    assert(!ds_tls->root_tls || ds_tls->root_tls == root_tls);
    ds_tls->root_tls = root_tls;
    return ds_tls;
  }

  DataSourceStaticState state_;
  BufferExhaustedPolicy buffer_exhausted_policy_{};
  CreateCustomTlsFn create_custom_tls_fn_ = nullptr;
  CreateIncrementalStateFn create_incremental_state_fn_ = nullptr;
  // User defined pointer that carries extra content for the fn_ callbacks
  // above. Only used in the C shared library.
  void* user_arg_ = nullptr;
};

}  // namespace internal
}  // namespace perfetto

#endif  // INCLUDE_PERFETTO_TRACING_INTERNAL_DATA_SOURCE_TYPE_H_
// gen_amalgamated begin header: gen/protos/perfetto/trace/trace_packet.pbzero.h
// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.

#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACE_PACKET_PROTO_H_
#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACE_PACKET_PROTO_H_

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

// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"

namespace perfetto {
namespace protos {
namespace pbzero {
class AndroidCameraFrameEvent;
class AndroidCameraSessionStats;
class AndroidEnergyEstimationBreakdown;
class AndroidGameInterventionList;
class AndroidLogPacket;
class AndroidSystemProperty;
class BatteryCounters;
class ChromeBenchmarkMetadata;
class ChromeEventBundle;
class ChromeMetadataPacket;
class ChromeTrigger;
class ClockSnapshot;
class CpuInfo;
class DeobfuscationMapping;
class EntityStateResidency;
class EtwTraceEventBundle;
class ExtensionDescriptor;
class FrameTimelineEvent;
class FtraceEventBundle;
class FtraceStats;
class GpuCounterEvent;
class GpuLog;
class GpuMemTotalEvent;
class GpuRenderStageEvent;
class GraphicsFrameEvent;
class HeapGraph;
class InitialDisplayState;
class InodeFileMap;
class InternedData;
class LayersSnapshotProto;
class MemoryTrackerSnapshot;
class ModuleSymbols;
class NetworkPacketBundle;
class NetworkPacketEvent;
class PackagesList;
class PerfSample;
class PerfettoMetatrace;
class PixelModemEvents;
class PixelModemTokenDatabase;
class PowerRails;
class ProcessDescriptor;
class ProcessStats;
class ProcessTree;
class ProfilePacket;
class ProfiledFrameSymbols;
class ProtoLogMessage;
class ProtoLogViewerConfig;
class RemoteClockSync;
class ShellHandlerMappings;
class ShellTransition;
class SmapsPacket;
class StatsdAtom;
class StreamingAllocation;
class StreamingFree;
class StreamingProfilePacket;
class SysStats;
class SystemInfo;
class TestEvent;
class ThreadDescriptor;
class TraceConfig;
class TracePacketDefaults;
class TraceStats;
class TraceUuid;
class TracingServiceEvent;
class TrackDescriptor;
class TrackEvent;
class TrackEventRangeOfInterest;
class TransactionTraceEntry;
class TranslationTable;
class Trigger;
class UiState;
class V8CodeMove;
class V8InternalCode;
class V8JsCode;
class V8RegExpCode;
class V8WasmCode;
class VulkanApiEvent;
class VulkanMemoryEvent;
class WinscopeExtensions;
// Namespace pbzero.
// Namespace protos.
// Namespace perfetto.

namespace perfetto {
namespace protos {
namespace pbzero {

namespace perfetto_pbzero_enum_TracePacket {
enum SequenceFlags : int32_t {
  SEQ_UNSPECIFIED = 0,
  SEQ_INCREMENTAL_STATE_CLEARED = 1,
  SEQ_NEEDS_INCREMENTAL_STATE = 2,
};
// namespace perfetto_pbzero_enum_TracePacket
using TracePacket_SequenceFlags = perfetto_pbzero_enum_TracePacket::SequenceFlags;


constexpr TracePacket_SequenceFlags TracePacket_SequenceFlags_MIN = TracePacket_SequenceFlags::SEQ_UNSPECIFIED;
constexpr TracePacket_SequenceFlags TracePacket_SequenceFlags_MAX = TracePacket_SequenceFlags::SEQ_NEEDS_INCREMENTAL_STATE;


PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
const char* TracePacket_SequenceFlags_Name(::perfetto::protos::pbzero::TracePacket_SequenceFlags value) {
  switch (value) {
  case ::perfetto::protos::pbzero::TracePacket_SequenceFlags::SEQ_UNSPECIFIED:
    return "SEQ_UNSPECIFIED";

  case ::perfetto::protos::pbzero::TracePacket_SequenceFlags::SEQ_INCREMENTAL_STATE_CLEARED:
    return "SEQ_INCREMENTAL_STATE_CLEARED";

  case ::perfetto::protos::pbzero::TracePacket_SequenceFlags::SEQ_NEEDS_INCREMENTAL_STATE:
    return "SEQ_NEEDS_INCREMENTAL_STATE";
  }
  return "PBZERO_UNKNOWN_ENUM_VALUE";
}

class TracePacket_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/900, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
 public:
  TracePacket_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
  explicit TracePacket_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
  explicit TracePacket_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
  bool has_timestamp() const { return at<8>().valid(); }
  uint64_t timestamp() const { return at<8>().as_uint64(); }
  bool has_timestamp_clock_id() const { return at<58>().valid(); }
  uint32_t timestamp_clock_id() const { return at<58>().as_uint32(); }
  bool has_process_tree() const { return at<2>().valid(); }
  ::protozero::ConstBytes process_tree() const { return at<2>().as_bytes(); }
  bool has_process_stats() const { return at<9>().valid(); }
  ::protozero::ConstBytes process_stats() const { return at<9>().as_bytes(); }
  bool has_inode_file_map() const { return at<4>().valid(); }
  ::protozero::ConstBytes inode_file_map() const { return at<4>().as_bytes(); }
  bool has_chrome_events() const { return at<5>().valid(); }
  ::protozero::ConstBytes chrome_events() const { return at<5>().as_bytes(); }
  bool has_clock_snapshot() const { return at<6>().valid(); }
  ::protozero::ConstBytes clock_snapshot() const { return at<6>().as_bytes(); }
  bool has_sys_stats() const { return at<7>().valid(); }
  ::protozero::ConstBytes sys_stats() const { return at<7>().as_bytes(); }
  bool has_track_event() const { return at<11>().valid(); }
  ::protozero::ConstBytes track_event() const { return at<11>().as_bytes(); }
  bool has_trace_uuid() const { return at<89>().valid(); }
  ::protozero::ConstBytes trace_uuid() const { return at<89>().as_bytes(); }
  bool has_trace_config() const { return at<33>().valid(); }
  ::protozero::ConstBytes trace_config() const { return at<33>().as_bytes(); }
  bool has_ftrace_stats() const { return at<34>().valid(); }
  ::protozero::ConstBytes ftrace_stats() const { return at<34>().as_bytes(); }
  bool has_trace_stats() const { return at<35>().valid(); }
  ::protozero::ConstBytes trace_stats() const { return at<35>().as_bytes(); }
  bool has_profile_packet() const { return at<37>().valid(); }
  ::protozero::ConstBytes profile_packet() const { return at<37>().as_bytes(); }
  bool has_streaming_allocation() const { return at<74>().valid(); }
  ::protozero::ConstBytes streaming_allocation() const { return at<74>().as_bytes(); }
  bool has_streaming_free() const { return at<75>().valid(); }
  ::protozero::ConstBytes streaming_free() const { return at<75>().as_bytes(); }
  bool has_battery() const { return at<38>().valid(); }
  ::protozero::ConstBytes battery() const { return at<38>().as_bytes(); }
  bool has_power_rails() const { return at<40>().valid(); }
  ::protozero::ConstBytes power_rails() const { return at<40>().as_bytes(); }
  bool has_android_log() const { return at<39>().valid(); }
  ::protozero::ConstBytes android_log() const { return at<39>().as_bytes(); }
  bool has_system_info() const { return at<45>().valid(); }
  ::protozero::ConstBytes system_info() const { return at<45>().as_bytes(); }
  bool has_trigger() const { return at<46>().valid(); }
  ::protozero::ConstBytes trigger() const { return at<46>().as_bytes(); }
  bool has_chrome_trigger() const { return at<109>().valid(); }
  ::protozero::ConstBytes chrome_trigger() const { return at<109>().as_bytes(); }
  bool has_packages_list() const { return at<47>().valid(); }
  ::protozero::ConstBytes packages_list() const { return at<47>().as_bytes(); }
  bool has_chrome_benchmark_metadata() const { return at<48>().valid(); }
  ::protozero::ConstBytes chrome_benchmark_metadata() const { return at<48>().as_bytes(); }
  bool has_perfetto_metatrace() const { return at<49>().valid(); }
  ::protozero::ConstBytes perfetto_metatrace() const { return at<49>().as_bytes(); }
  bool has_chrome_metadata() const { return at<51>().valid(); }
  ::protozero::ConstBytes chrome_metadata() const { return at<51>().as_bytes(); }
  bool has_gpu_counter_event() const { return at<52>().valid(); }
  ::protozero::ConstBytes gpu_counter_event() const { return at<52>().as_bytes(); }
  bool has_gpu_render_stage_event() const { return at<53>().valid(); }
  ::protozero::ConstBytes gpu_render_stage_event() const { return at<53>().as_bytes(); }
  bool has_streaming_profile_packet() const { return at<54>().valid(); }
  ::protozero::ConstBytes streaming_profile_packet() const { return at<54>().as_bytes(); }
  bool has_heap_graph() const { return at<56>().valid(); }
  ::protozero::ConstBytes heap_graph() const { return at<56>().as_bytes(); }
  bool has_graphics_frame_event() const { return at<57>().valid(); }
  ::protozero::ConstBytes graphics_frame_event() const { return at<57>().as_bytes(); }
  bool has_vulkan_memory_event() const { return at<62>().valid(); }
  ::protozero::ConstBytes vulkan_memory_event() const { return at<62>().as_bytes(); }
  bool has_gpu_log() const { return at<63>().valid(); }
  ::protozero::ConstBytes gpu_log() const { return at<63>().as_bytes(); }
  bool has_vulkan_api_event() const { return at<65>().valid(); }
  ::protozero::ConstBytes vulkan_api_event() const { return at<65>().as_bytes(); }
  bool has_perf_sample() const { return at<66>().valid(); }
  ::protozero::ConstBytes perf_sample() const { return at<66>().as_bytes(); }
  bool has_cpu_info() const { return at<67>().valid(); }
  ::protozero::ConstBytes cpu_info() const { return at<67>().as_bytes(); }
  bool has_smaps_packet() const { return at<68>().valid(); }
  ::protozero::ConstBytes smaps_packet() const { return at<68>().as_bytes(); }
  bool has_service_event() const { return at<69>().valid(); }
  ::protozero::ConstBytes service_event() const { return at<69>().as_bytes(); }
  bool has_initial_display_state() const { return at<70>().valid(); }
  ::protozero::ConstBytes initial_display_state() const { return at<70>().as_bytes(); }
  bool has_gpu_mem_total_event() const { return at<71>().valid(); }
  ::protozero::ConstBytes gpu_mem_total_event() const { return at<71>().as_bytes(); }
  bool has_memory_tracker_snapshot() const { return at<73>().valid(); }
  ::protozero::ConstBytes memory_tracker_snapshot() const { return at<73>().as_bytes(); }
  bool has_frame_timeline_event() const { return at<76>().valid(); }
  ::protozero::ConstBytes frame_timeline_event() const { return at<76>().as_bytes(); }
  bool has_android_energy_estimation_breakdown() const { return at<77>().valid(); }
  ::protozero::ConstBytes android_energy_estimation_breakdown() const { return at<77>().as_bytes(); }
  bool has_ui_state() const { return at<78>().valid(); }
  ::protozero::ConstBytes ui_state() const { return at<78>().as_bytes(); }
  bool has_android_camera_frame_event() const { return at<80>().valid(); }
  ::protozero::ConstBytes android_camera_frame_event() const { return at<80>().as_bytes(); }
  bool has_android_camera_session_stats() const { return at<81>().valid(); }
  ::protozero::ConstBytes android_camera_session_stats() const { return at<81>().as_bytes(); }
  bool has_translation_table() const { return at<82>().valid(); }
  ::protozero::ConstBytes translation_table() const { return at<82>().as_bytes(); }
  bool has_android_game_intervention_list() const { return at<83>().valid(); }
  ::protozero::ConstBytes android_game_intervention_list() const { return at<83>().as_bytes(); }
  bool has_statsd_atom() const { return at<84>().valid(); }
  ::protozero::ConstBytes statsd_atom() const { return at<84>().as_bytes(); }
  bool has_android_system_property() const { return at<86>().valid(); }
  ::protozero::ConstBytes android_system_property() const { return at<86>().as_bytes(); }
  bool has_entity_state_residency() const { return at<91>().valid(); }
  ::protozero::ConstBytes entity_state_residency() const { return at<91>().as_bytes(); }
  bool has_profiled_frame_symbols() const { return at<55>().valid(); }
  ::protozero::ConstBytes profiled_frame_symbols() const { return at<55>().as_bytes(); }
  bool has_module_symbols() const { return at<61>().valid(); }
  ::protozero::ConstBytes module_symbols() const { return at<61>().as_bytes(); }
  bool has_deobfuscation_mapping() const { return at<64>().valid(); }
  ::protozero::ConstBytes deobfuscation_mapping() const { return at<64>().as_bytes(); }
  bool has_track_descriptor() const { return at<60>().valid(); }
  ::protozero::ConstBytes track_descriptor() const { return at<60>().as_bytes(); }
  bool has_process_descriptor() const { return at<43>().valid(); }
  ::protozero::ConstBytes process_descriptor() const { return at<43>().as_bytes(); }
  bool has_thread_descriptor() const { return at<44>().valid(); }
  ::protozero::ConstBytes thread_descriptor() const { return at<44>().as_bytes(); }
  bool has_ftrace_events() const { return at<1>().valid(); }
  ::protozero::ConstBytes ftrace_events() const { return at<1>().as_bytes(); }
  bool has_synchronization_marker() const { return at<36>().valid(); }
  ::protozero::ConstBytes synchronization_marker() const { return at<36>().as_bytes(); }
  bool has_compressed_packets() const { return at<50>().valid(); }
  ::protozero::ConstBytes compressed_packets() const { return at<50>().as_bytes(); }
  bool has_extension_descriptor() const { return at<72>().valid(); }
  ::protozero::ConstBytes extension_descriptor() const { return at<72>().as_bytes(); }
  bool has_network_packet() const { return at<88>().valid(); }
  ::protozero::ConstBytes network_packet() const { return at<88>().as_bytes(); }
  bool has_network_packet_bundle() const { return at<92>().valid(); }
  ::protozero::ConstBytes network_packet_bundle() const { return at<92>().as_bytes(); }
  bool has_track_event_range_of_interest() const { return at<90>().valid(); }
  ::protozero::ConstBytes track_event_range_of_interest() const { return at<90>().as_bytes(); }
  bool has_surfaceflinger_layers_snapshot() const { return at<93>().valid(); }
  ::protozero::ConstBytes surfaceflinger_layers_snapshot() const { return at<93>().as_bytes(); }
  bool has_surfaceflinger_transactions() const { return at<94>().valid(); }
  ::protozero::ConstBytes surfaceflinger_transactions() const { return at<94>().as_bytes(); }
  bool has_shell_transition() const { return at<96>().valid(); }
  ::protozero::ConstBytes shell_transition() const { return at<96>().as_bytes(); }
  bool has_shell_handler_mappings() const { return at<97>().valid(); }
  ::protozero::ConstBytes shell_handler_mappings() const { return at<97>().as_bytes(); }
  bool has_protolog_message() const { return at<104>().valid(); }
  ::protozero::ConstBytes protolog_message() const { return at<104>().as_bytes(); }
  bool has_protolog_viewer_config() const { return at<105>().valid(); }
  ::protozero::ConstBytes protolog_viewer_config() const { return at<105>().as_bytes(); }
  bool has_winscope_extensions() const { return at<112>().valid(); }
  ::protozero::ConstBytes winscope_extensions() const { return at<112>().as_bytes(); }
  bool has_etw_events() const { return at<95>().valid(); }
  ::protozero::ConstBytes etw_events() const { return at<95>().as_bytes(); }
  bool has_v8_js_code() const { return at<99>().valid(); }
  ::protozero::ConstBytes v8_js_code() const { return at<99>().as_bytes(); }
  bool has_v8_internal_code() const { return at<100>().valid(); }
  ::protozero::ConstBytes v8_internal_code() const { return at<100>().as_bytes(); }
  bool has_v8_wasm_code() const { return at<101>().valid(); }
  ::protozero::ConstBytes v8_wasm_code() const { return at<101>().as_bytes(); }
  bool has_v8_reg_exp_code() const { return at<102>().valid(); }
  ::protozero::ConstBytes v8_reg_exp_code() const { return at<102>().as_bytes(); }
  bool has_v8_code_move() const { return at<103>().valid(); }
  ::protozero::ConstBytes v8_code_move() const { return at<103>().as_bytes(); }
  bool has_remote_clock_sync() const { return at<107>().valid(); }
  ::protozero::ConstBytes remote_clock_sync() const { return at<107>().as_bytes(); }
  bool has_pixel_modem_events() const { return at<110>().valid(); }
  ::protozero::ConstBytes pixel_modem_events() const { return at<110>().as_bytes(); }
  bool has_pixel_modem_token_database() const { return at<111>().valid(); }
  ::protozero::ConstBytes pixel_modem_token_database() const { return at<111>().as_bytes(); }
  bool has_clone_snapshot_trigger() const { return at<113>().valid(); }
  ::protozero::ConstBytes clone_snapshot_trigger() const { return at<113>().as_bytes(); }
  bool has_for_testing() const { return at<900>().valid(); }
  ::protozero::ConstBytes for_testing() const { return at<900>().as_bytes(); }
  bool has_trusted_uid() const { return at<3>().valid(); }
  int32_t trusted_uid() const { return at<3>().as_int32(); }
  bool has_trusted_packet_sequence_id() const { return at<10>().valid(); }
  uint32_t trusted_packet_sequence_id() const { return at<10>().as_uint32(); }
  bool has_trusted_pid() const { return at<79>().valid(); }
  int32_t trusted_pid() const { return at<79>().as_int32(); }
  bool has_interned_data() const { return at<12>().valid(); }
  ::protozero::ConstBytes interned_data() const { return at<12>().as_bytes(); }
  bool has_sequence_flags() const { return at<13>().valid(); }
  uint32_t sequence_flags() const { return at<13>().as_uint32(); }
  bool has_incremental_state_cleared() const { return at<41>().valid(); }
  bool incremental_state_cleared() const { return at<41>().as_bool(); }
  bool has_trace_packet_defaults() const { return at<59>().valid(); }
  ::protozero::ConstBytes trace_packet_defaults() const { return at<59>().as_bytes(); }
  bool has_previous_packet_dropped() const { return at<42>().valid(); }
  bool previous_packet_dropped() const { return at<42>().as_bool(); }
  bool has_first_packet_on_sequence() const { return at<87>().valid(); }
  bool first_packet_on_sequence() const { return at<87>().as_bool(); }
  bool has_machine_id() const { return at<98>().valid(); }
  uint32_t machine_id() const { return at<98>().as_uint32(); }
};

class TracePacket : public ::protozero::Message {
 public:
  using Decoder = TracePacket_Decoder;
  enum : int32_t {
    kTimestampFieldNumber = 8,
    kTimestampClockIdFieldNumber = 58,
    kProcessTreeFieldNumber = 2,
    kProcessStatsFieldNumber = 9,
    kInodeFileMapFieldNumber = 4,
    kChromeEventsFieldNumber = 5,
    kClockSnapshotFieldNumber = 6,
    kSysStatsFieldNumber = 7,
    kTrackEventFieldNumber = 11,
    kTraceUuidFieldNumber = 89,
    kTraceConfigFieldNumber = 33,
    kFtraceStatsFieldNumber = 34,
    kTraceStatsFieldNumber = 35,
    kProfilePacketFieldNumber = 37,
    kStreamingAllocationFieldNumber = 74,
    kStreamingFreeFieldNumber = 75,
    kBatteryFieldNumber = 38,
    kPowerRailsFieldNumber = 40,
    kAndroidLogFieldNumber = 39,
    kSystemInfoFieldNumber = 45,
    kTriggerFieldNumber = 46,
    kChromeTriggerFieldNumber = 109,
    kPackagesListFieldNumber = 47,
    kChromeBenchmarkMetadataFieldNumber = 48,
    kPerfettoMetatraceFieldNumber = 49,
    kChromeMetadataFieldNumber = 51,
    kGpuCounterEventFieldNumber = 52,
    kGpuRenderStageEventFieldNumber = 53,
    kStreamingProfilePacketFieldNumber = 54,
    kHeapGraphFieldNumber = 56,
    kGraphicsFrameEventFieldNumber = 57,
    kVulkanMemoryEventFieldNumber = 62,
    kGpuLogFieldNumber = 63,
    kVulkanApiEventFieldNumber = 65,
    kPerfSampleFieldNumber = 66,
    kCpuInfoFieldNumber = 67,
    kSmapsPacketFieldNumber = 68,
    kServiceEventFieldNumber = 69,
    kInitialDisplayStateFieldNumber = 70,
    kGpuMemTotalEventFieldNumber = 71,
    kMemoryTrackerSnapshotFieldNumber = 73,
    kFrameTimelineEventFieldNumber = 76,
    kAndroidEnergyEstimationBreakdownFieldNumber = 77,
    kUiStateFieldNumber = 78,
    kAndroidCameraFrameEventFieldNumber = 80,
    kAndroidCameraSessionStatsFieldNumber = 81,
    kTranslationTableFieldNumber = 82,
    kAndroidGameInterventionListFieldNumber = 83,
    kStatsdAtomFieldNumber = 84,
    kAndroidSystemPropertyFieldNumber = 86,
    kEntityStateResidencyFieldNumber = 91,
    kProfiledFrameSymbolsFieldNumber = 55,
    kModuleSymbolsFieldNumber = 61,
    kDeobfuscationMappingFieldNumber = 64,
    kTrackDescriptorFieldNumber = 60,
    kProcessDescriptorFieldNumber = 43,
    kThreadDescriptorFieldNumber = 44,
    kFtraceEventsFieldNumber = 1,
    kSynchronizationMarkerFieldNumber = 36,
    kCompressedPacketsFieldNumber = 50,
    kExtensionDescriptorFieldNumber = 72,
    kNetworkPacketFieldNumber = 88,
    kNetworkPacketBundleFieldNumber = 92,
    kTrackEventRangeOfInterestFieldNumber = 90,
    kSurfaceflingerLayersSnapshotFieldNumber = 93,
    kSurfaceflingerTransactionsFieldNumber = 94,
    kShellTransitionFieldNumber = 96,
    kShellHandlerMappingsFieldNumber = 97,
    kProtologMessageFieldNumber = 104,
    kProtologViewerConfigFieldNumber = 105,
    kWinscopeExtensionsFieldNumber = 112,
    kEtwEventsFieldNumber = 95,
    kV8JsCodeFieldNumber = 99,
    kV8InternalCodeFieldNumber = 100,
    kV8WasmCodeFieldNumber = 101,
    kV8RegExpCodeFieldNumber = 102,
    kV8CodeMoveFieldNumber = 103,
    kRemoteClockSyncFieldNumber = 107,
    kPixelModemEventsFieldNumber = 110,
    kPixelModemTokenDatabaseFieldNumber = 111,
    kCloneSnapshotTriggerFieldNumber = 113,
    kForTestingFieldNumber = 900,
    kTrustedUidFieldNumber = 3,
    kTrustedPacketSequenceIdFieldNumber = 10,
    kTrustedPidFieldNumber = 79,
    kInternedDataFieldNumber = 12,
    kSequenceFlagsFieldNumber = 13,
    kIncrementalStateClearedFieldNumber = 41,
    kTracePacketDefaultsFieldNumber = 59,
    kPreviousPacketDroppedFieldNumber = 42,
    kFirstPacketOnSequenceFieldNumber = 87,
    kMachineIdFieldNumber = 98,
  };
  static constexpr const char* GetName() { return ".perfetto.protos.TracePacket"; }


  using SequenceFlags = ::perfetto::protos::pbzero::TracePacket_SequenceFlags;
  static inline const char* SequenceFlags_Name(SequenceFlags value) {
    return ::perfetto::protos::pbzero::TracePacket_SequenceFlags_Name(value);
  }
  static inline const SequenceFlags SEQ_UNSPECIFIED = SequenceFlags::SEQ_UNSPECIFIED;
  static inline const SequenceFlags SEQ_INCREMENTAL_STATE_CLEARED = SequenceFlags::SEQ_INCREMENTAL_STATE_CLEARED;
  static inline const SequenceFlags SEQ_NEEDS_INCREMENTAL_STATE = SequenceFlags::SEQ_NEEDS_INCREMENTAL_STATE;

  using FieldMetadata_Timestamp =
    ::protozero::proto_utils::FieldMetadata<
      8,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kUint64,
      uint64_t,
      TracePacket>;

  static constexpr FieldMetadata_Timestamp kTimestamp{};
  void set_timestamp(uint64_t value) {
    static constexpr uint32_t field_id = FieldMetadata_Timestamp::kFieldId;
    // Call the appropriate protozero::Message::Append(field_id, ...)
    // method based on the type of the field.
    ::protozero::internal::FieldWriter<
      ::protozero::proto_utils::ProtoSchemaType::kUint64>
        ::Append(*this, field_id, value);
  }

  using FieldMetadata_TimestampClockId =
    ::protozero::proto_utils::FieldMetadata<
      58,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kUint32,
      uint32_t,
      TracePacket>;

  static constexpr FieldMetadata_TimestampClockId kTimestampClockId{};
  void set_timestamp_clock_id(uint32_t value) {
    static constexpr uint32_t field_id = FieldMetadata_TimestampClockId::kFieldId;
    // Call the appropriate protozero::Message::Append(field_id, ...)
    // method based on the type of the field.
    ::protozero::internal::FieldWriter<
      ::protozero::proto_utils::ProtoSchemaType::kUint32>
        ::Append(*this, field_id, value);
  }

  using FieldMetadata_ProcessTree =
    ::protozero::proto_utils::FieldMetadata<
      2,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      ProcessTree,
      TracePacket>;

  static constexpr FieldMetadata_ProcessTree kProcessTree{};
  template <typename T = ProcessTree> T* set_process_tree() {
    return BeginNestedMessage<T>(2);
  }


  using FieldMetadata_ProcessStats =
    ::protozero::proto_utils::FieldMetadata<
      9,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      ProcessStats,
      TracePacket>;

  static constexpr FieldMetadata_ProcessStats kProcessStats{};
  template <typename T = ProcessStats> T* set_process_stats() {
    return BeginNestedMessage<T>(9);
  }


  using FieldMetadata_InodeFileMap =
    ::protozero::proto_utils::FieldMetadata<
      4,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      InodeFileMap,
      TracePacket>;

  static constexpr FieldMetadata_InodeFileMap kInodeFileMap{};
  template <typename T = InodeFileMap> T* set_inode_file_map() {
    return BeginNestedMessage<T>(4);
  }


  using FieldMetadata_ChromeEvents =
    ::protozero::proto_utils::FieldMetadata<
      5,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      ChromeEventBundle,
      TracePacket>;

  static constexpr FieldMetadata_ChromeEvents kChromeEvents{};
  template <typename T = ChromeEventBundle> T* set_chrome_events() {
    return BeginNestedMessage<T>(5);
  }


  using FieldMetadata_ClockSnapshot =
    ::protozero::proto_utils::FieldMetadata<
      6,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      ClockSnapshot,
      TracePacket>;

  static constexpr FieldMetadata_ClockSnapshot kClockSnapshot{};
  template <typename T = ClockSnapshot> T* set_clock_snapshot() {
    return BeginNestedMessage<T>(6);
  }


  using FieldMetadata_SysStats =
    ::protozero::proto_utils::FieldMetadata<
      7,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      SysStats,
      TracePacket>;

  static constexpr FieldMetadata_SysStats kSysStats{};
  template <typename T = SysStats> T* set_sys_stats() {
    return BeginNestedMessage<T>(7);
  }


  using FieldMetadata_TrackEvent =
    ::protozero::proto_utils::FieldMetadata<
      11,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      TrackEvent,
      TracePacket>;

  static constexpr FieldMetadata_TrackEvent kTrackEvent{};
  template <typename T = TrackEvent> T* set_track_event() {
    return BeginNestedMessage<T>(11);
  }


  using FieldMetadata_TraceUuid =
    ::protozero::proto_utils::FieldMetadata<
      89,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      TraceUuid,
      TracePacket>;

  static constexpr FieldMetadata_TraceUuid kTraceUuid{};
  template <typename T = TraceUuid> T* set_trace_uuid() {
    return BeginNestedMessage<T>(89);
  }


  using FieldMetadata_TraceConfig =
    ::protozero::proto_utils::FieldMetadata<
      33,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      TraceConfig,
      TracePacket>;

  static constexpr FieldMetadata_TraceConfig kTraceConfig{};
  template <typename T = TraceConfig> T* set_trace_config() {
    return BeginNestedMessage<T>(33);
  }


  using FieldMetadata_FtraceStats =
    ::protozero::proto_utils::FieldMetadata<
      34,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      FtraceStats,
      TracePacket>;

  static constexpr FieldMetadata_FtraceStats kFtraceStats{};
  template <typename T = FtraceStats> T* set_ftrace_stats() {
    return BeginNestedMessage<T>(34);
  }


  using FieldMetadata_TraceStats =
    ::protozero::proto_utils::FieldMetadata<
      35,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      TraceStats,
      TracePacket>;

  static constexpr FieldMetadata_TraceStats kTraceStats{};
  template <typename T = TraceStats> T* set_trace_stats() {
    return BeginNestedMessage<T>(35);
  }


  using FieldMetadata_ProfilePacket =
    ::protozero::proto_utils::FieldMetadata<
      37,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      ProfilePacket,
      TracePacket>;

  static constexpr FieldMetadata_ProfilePacket kProfilePacket{};
  template <typename T = ProfilePacket> T* set_profile_packet() {
    return BeginNestedMessage<T>(37);
  }


  using FieldMetadata_StreamingAllocation =
    ::protozero::proto_utils::FieldMetadata<
      74,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      StreamingAllocation,
      TracePacket>;

  static constexpr FieldMetadata_StreamingAllocation kStreamingAllocation{};
  template <typename T = StreamingAllocation> T* set_streaming_allocation() {
    return BeginNestedMessage<T>(74);
  }


  using FieldMetadata_StreamingFree =
    ::protozero::proto_utils::FieldMetadata<
      75,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      StreamingFree,
      TracePacket>;

  static constexpr FieldMetadata_StreamingFree kStreamingFree{};
  template <typename T = StreamingFree> T* set_streaming_free() {
    return BeginNestedMessage<T>(75);
  }


  using FieldMetadata_Battery =
    ::protozero::proto_utils::FieldMetadata<
      38,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      BatteryCounters,
      TracePacket>;

  static constexpr FieldMetadata_Battery kBattery{};
  template <typename T = BatteryCounters> T* set_battery() {
    return BeginNestedMessage<T>(38);
  }


  using FieldMetadata_PowerRails =
    ::protozero::proto_utils::FieldMetadata<
      40,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      PowerRails,
      TracePacket>;

  static constexpr FieldMetadata_PowerRails kPowerRails{};
  template <typename T = PowerRails> T* set_power_rails() {
    return BeginNestedMessage<T>(40);
  }


  using FieldMetadata_AndroidLog =
    ::protozero::proto_utils::FieldMetadata<
      39,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      AndroidLogPacket,
      TracePacket>;

  static constexpr FieldMetadata_AndroidLog kAndroidLog{};
  template <typename T = AndroidLogPacket> T* set_android_log() {
    return BeginNestedMessage<T>(39);
  }


  using FieldMetadata_SystemInfo =
    ::protozero::proto_utils::FieldMetadata<
      45,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      SystemInfo,
      TracePacket>;

  static constexpr FieldMetadata_SystemInfo kSystemInfo{};
  template <typename T = SystemInfo> T* set_system_info() {
    return BeginNestedMessage<T>(45);
  }


  using FieldMetadata_Trigger =
    ::protozero::proto_utils::FieldMetadata<
      46,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      Trigger,
      TracePacket>;

  static constexpr FieldMetadata_Trigger kTrigger{};
  template <typename T = Trigger> T* set_trigger() {
    return BeginNestedMessage<T>(46);
  }


  using FieldMetadata_ChromeTrigger =
    ::protozero::proto_utils::FieldMetadata<
      109,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      ChromeTrigger,
      TracePacket>;

  static constexpr FieldMetadata_ChromeTrigger kChromeTrigger{};
  template <typename T = ChromeTrigger> T* set_chrome_trigger() {
    return BeginNestedMessage<T>(109);
  }


  using FieldMetadata_PackagesList =
    ::protozero::proto_utils::FieldMetadata<
      47,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      PackagesList,
      TracePacket>;

  static constexpr FieldMetadata_PackagesList kPackagesList{};
  template <typename T = PackagesList> T* set_packages_list() {
    return BeginNestedMessage<T>(47);
  }


  using FieldMetadata_ChromeBenchmarkMetadata =
    ::protozero::proto_utils::FieldMetadata<
      48,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      ChromeBenchmarkMetadata,
      TracePacket>;

  static constexpr FieldMetadata_ChromeBenchmarkMetadata kChromeBenchmarkMetadata{};
  template <typename T = ChromeBenchmarkMetadata> T* set_chrome_benchmark_metadata() {
    return BeginNestedMessage<T>(48);
  }


  using FieldMetadata_PerfettoMetatrace =
    ::protozero::proto_utils::FieldMetadata<
      49,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      PerfettoMetatrace,
      TracePacket>;

  static constexpr FieldMetadata_PerfettoMetatrace kPerfettoMetatrace{};
  template <typename T = PerfettoMetatrace> T* set_perfetto_metatrace() {
    return BeginNestedMessage<T>(49);
  }


  using FieldMetadata_ChromeMetadata =
    ::protozero::proto_utils::FieldMetadata<
      51,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      ChromeMetadataPacket,
      TracePacket>;

  static constexpr FieldMetadata_ChromeMetadata kChromeMetadata{};
  template <typename T = ChromeMetadataPacket> T* set_chrome_metadata() {
    return BeginNestedMessage<T>(51);
  }


  using FieldMetadata_GpuCounterEvent =
    ::protozero::proto_utils::FieldMetadata<
      52,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      GpuCounterEvent,
      TracePacket>;

  static constexpr FieldMetadata_GpuCounterEvent kGpuCounterEvent{};
  template <typename T = GpuCounterEvent> T* set_gpu_counter_event() {
    return BeginNestedMessage<T>(52);
  }


  using FieldMetadata_GpuRenderStageEvent =
    ::protozero::proto_utils::FieldMetadata<
      53,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      GpuRenderStageEvent,
      TracePacket>;

  static constexpr FieldMetadata_GpuRenderStageEvent kGpuRenderStageEvent{};
  template <typename T = GpuRenderStageEvent> T* set_gpu_render_stage_event() {
    return BeginNestedMessage<T>(53);
  }


  using FieldMetadata_StreamingProfilePacket =
    ::protozero::proto_utils::FieldMetadata<
      54,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      StreamingProfilePacket,
      TracePacket>;

  static constexpr FieldMetadata_StreamingProfilePacket kStreamingProfilePacket{};
  template <typename T = StreamingProfilePacket> T* set_streaming_profile_packet() {
    return BeginNestedMessage<T>(54);
  }


  using FieldMetadata_HeapGraph =
    ::protozero::proto_utils::FieldMetadata<
      56,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      HeapGraph,
      TracePacket>;

  static constexpr FieldMetadata_HeapGraph kHeapGraph{};
  template <typename T = HeapGraph> T* set_heap_graph() {
    return BeginNestedMessage<T>(56);
  }


  using FieldMetadata_GraphicsFrameEvent =
    ::protozero::proto_utils::FieldMetadata<
      57,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      GraphicsFrameEvent,
      TracePacket>;

  static constexpr FieldMetadata_GraphicsFrameEvent kGraphicsFrameEvent{};
  template <typename T = GraphicsFrameEvent> T* set_graphics_frame_event() {
    return BeginNestedMessage<T>(57);
  }


  using FieldMetadata_VulkanMemoryEvent =
    ::protozero::proto_utils::FieldMetadata<
      62,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      VulkanMemoryEvent,
      TracePacket>;

  static constexpr FieldMetadata_VulkanMemoryEvent kVulkanMemoryEvent{};
  template <typename T = VulkanMemoryEvent> T* set_vulkan_memory_event() {
    return BeginNestedMessage<T>(62);
  }


  using FieldMetadata_GpuLog =
    ::protozero::proto_utils::FieldMetadata<
      63,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      GpuLog,
      TracePacket>;

  static constexpr FieldMetadata_GpuLog kGpuLog{};
  template <typename T = GpuLog> T* set_gpu_log() {
    return BeginNestedMessage<T>(63);
  }


  using FieldMetadata_VulkanApiEvent =
    ::protozero::proto_utils::FieldMetadata<
      65,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      VulkanApiEvent,
      TracePacket>;

  static constexpr FieldMetadata_VulkanApiEvent kVulkanApiEvent{};
  template <typename T = VulkanApiEvent> T* set_vulkan_api_event() {
    return BeginNestedMessage<T>(65);
  }


  using FieldMetadata_PerfSample =
    ::protozero::proto_utils::FieldMetadata<
      66,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      PerfSample,
      TracePacket>;

  static constexpr FieldMetadata_PerfSample kPerfSample{};
  template <typename T = PerfSample> T* set_perf_sample() {
    return BeginNestedMessage<T>(66);
  }


  using FieldMetadata_CpuInfo =
    ::protozero::proto_utils::FieldMetadata<
      67,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      CpuInfo,
      TracePacket>;

  static constexpr FieldMetadata_CpuInfo kCpuInfo{};
  template <typename T = CpuInfo> T* set_cpu_info() {
    return BeginNestedMessage<T>(67);
  }


  using FieldMetadata_SmapsPacket =
    ::protozero::proto_utils::FieldMetadata<
      68,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      SmapsPacket,
      TracePacket>;

  static constexpr FieldMetadata_SmapsPacket kSmapsPacket{};
  template <typename T = SmapsPacket> T* set_smaps_packet() {
    return BeginNestedMessage<T>(68);
  }


  using FieldMetadata_ServiceEvent =
    ::protozero::proto_utils::FieldMetadata<
      69,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      TracingServiceEvent,
      TracePacket>;

  static constexpr FieldMetadata_ServiceEvent kServiceEvent{};
  template <typename T = TracingServiceEvent> T* set_service_event() {
    return BeginNestedMessage<T>(69);
  }


  using FieldMetadata_InitialDisplayState =
    ::protozero::proto_utils::FieldMetadata<
      70,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      InitialDisplayState,
      TracePacket>;

  static constexpr FieldMetadata_InitialDisplayState kInitialDisplayState{};
  template <typename T = InitialDisplayState> T* set_initial_display_state() {
    return BeginNestedMessage<T>(70);
  }


  using FieldMetadata_GpuMemTotalEvent =
    ::protozero::proto_utils::FieldMetadata<
      71,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      GpuMemTotalEvent,
      TracePacket>;

  static constexpr FieldMetadata_GpuMemTotalEvent kGpuMemTotalEvent{};
  template <typename T = GpuMemTotalEvent> T* set_gpu_mem_total_event() {
    return BeginNestedMessage<T>(71);
  }


  using FieldMetadata_MemoryTrackerSnapshot =
    ::protozero::proto_utils::FieldMetadata<
      73,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      MemoryTrackerSnapshot,
      TracePacket>;

  static constexpr FieldMetadata_MemoryTrackerSnapshot kMemoryTrackerSnapshot{};
  template <typename T = MemoryTrackerSnapshot> T* set_memory_tracker_snapshot() {
    return BeginNestedMessage<T>(73);
  }


  using FieldMetadata_FrameTimelineEvent =
    ::protozero::proto_utils::FieldMetadata<
      76,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      FrameTimelineEvent,
      TracePacket>;

  static constexpr FieldMetadata_FrameTimelineEvent kFrameTimelineEvent{};
  template <typename T = FrameTimelineEvent> T* set_frame_timeline_event() {
    return BeginNestedMessage<T>(76);
  }


  using FieldMetadata_AndroidEnergyEstimationBreakdown =
    ::protozero::proto_utils::FieldMetadata<
      77,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      AndroidEnergyEstimationBreakdown,
      TracePacket>;

  static constexpr FieldMetadata_AndroidEnergyEstimationBreakdown kAndroidEnergyEstimationBreakdown{};
  template <typename T = AndroidEnergyEstimationBreakdown> T* set_android_energy_estimation_breakdown() {
    return BeginNestedMessage<T>(77);
  }


  using FieldMetadata_UiState =
    ::protozero::proto_utils::FieldMetadata<
      78,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      UiState,
      TracePacket>;

  static constexpr FieldMetadata_UiState kUiState{};
  template <typename T = UiState> T* set_ui_state() {
    return BeginNestedMessage<T>(78);
  }


  using FieldMetadata_AndroidCameraFrameEvent =
    ::protozero::proto_utils::FieldMetadata<
      80,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      AndroidCameraFrameEvent,
      TracePacket>;

  static constexpr FieldMetadata_AndroidCameraFrameEvent kAndroidCameraFrameEvent{};
  template <typename T = AndroidCameraFrameEvent> T* set_android_camera_frame_event() {
    return BeginNestedMessage<T>(80);
  }


  using FieldMetadata_AndroidCameraSessionStats =
    ::protozero::proto_utils::FieldMetadata<
      81,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      AndroidCameraSessionStats,
      TracePacket>;

  static constexpr FieldMetadata_AndroidCameraSessionStats kAndroidCameraSessionStats{};
  template <typename T = AndroidCameraSessionStats> T* set_android_camera_session_stats() {
    return BeginNestedMessage<T>(81);
  }


  using FieldMetadata_TranslationTable =
    ::protozero::proto_utils::FieldMetadata<
      82,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      TranslationTable,
      TracePacket>;

  static constexpr FieldMetadata_TranslationTable kTranslationTable{};
  template <typename T = TranslationTable> T* set_translation_table() {
    return BeginNestedMessage<T>(82);
  }


  using FieldMetadata_AndroidGameInterventionList =
    ::protozero::proto_utils::FieldMetadata<
      83,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      AndroidGameInterventionList,
      TracePacket>;

  static constexpr FieldMetadata_AndroidGameInterventionList kAndroidGameInterventionList{};
  template <typename T = AndroidGameInterventionList> T* set_android_game_intervention_list() {
    return BeginNestedMessage<T>(83);
  }


  using FieldMetadata_StatsdAtom =
    ::protozero::proto_utils::FieldMetadata<
      84,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      StatsdAtom,
      TracePacket>;

  static constexpr FieldMetadata_StatsdAtom kStatsdAtom{};
  template <typename T = StatsdAtom> T* set_statsd_atom() {
    return BeginNestedMessage<T>(84);
  }


  using FieldMetadata_AndroidSystemProperty =
    ::protozero::proto_utils::FieldMetadata<
      86,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      AndroidSystemProperty,
      TracePacket>;

  static constexpr FieldMetadata_AndroidSystemProperty kAndroidSystemProperty{};
  template <typename T = AndroidSystemProperty> T* set_android_system_property() {
    return BeginNestedMessage<T>(86);
  }


  using FieldMetadata_EntityStateResidency =
    ::protozero::proto_utils::FieldMetadata<
      91,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      EntityStateResidency,
      TracePacket>;

  static constexpr FieldMetadata_EntityStateResidency kEntityStateResidency{};
  template <typename T = EntityStateResidency> T* set_entity_state_residency() {
    return BeginNestedMessage<T>(91);
  }


  using FieldMetadata_ProfiledFrameSymbols =
    ::protozero::proto_utils::FieldMetadata<
      55,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      ProfiledFrameSymbols,
      TracePacket>;

  static constexpr FieldMetadata_ProfiledFrameSymbols kProfiledFrameSymbols{};
  template <typename T = ProfiledFrameSymbols> T* set_profiled_frame_symbols() {
    return BeginNestedMessage<T>(55);
  }


  using FieldMetadata_ModuleSymbols =
    ::protozero::proto_utils::FieldMetadata<
      61,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      ModuleSymbols,
      TracePacket>;

  static constexpr FieldMetadata_ModuleSymbols kModuleSymbols{};
  template <typename T = ModuleSymbols> T* set_module_symbols() {
    return BeginNestedMessage<T>(61);
  }


  using FieldMetadata_DeobfuscationMapping =
    ::protozero::proto_utils::FieldMetadata<
      64,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      DeobfuscationMapping,
      TracePacket>;

  static constexpr FieldMetadata_DeobfuscationMapping kDeobfuscationMapping{};
  template <typename T = DeobfuscationMapping> T* set_deobfuscation_mapping() {
    return BeginNestedMessage<T>(64);
  }


  using FieldMetadata_TrackDescriptor =
    ::protozero::proto_utils::FieldMetadata<
      60,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      TrackDescriptor,
      TracePacket>;

  static constexpr FieldMetadata_TrackDescriptor kTrackDescriptor{};
  template <typename T = TrackDescriptor> T* set_track_descriptor() {
    return BeginNestedMessage<T>(60);
  }


  using FieldMetadata_ProcessDescriptor =
    ::protozero::proto_utils::FieldMetadata<
      43,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      ProcessDescriptor,
      TracePacket>;

  static constexpr FieldMetadata_ProcessDescriptor kProcessDescriptor{};
  template <typename T = ProcessDescriptor> T* set_process_descriptor() {
    return BeginNestedMessage<T>(43);
  }


  using FieldMetadata_ThreadDescriptor =
    ::protozero::proto_utils::FieldMetadata<
      44,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      ThreadDescriptor,
      TracePacket>;

  static constexpr FieldMetadata_ThreadDescriptor kThreadDescriptor{};
  template <typename T = ThreadDescriptor> T* set_thread_descriptor() {
    return BeginNestedMessage<T>(44);
  }


  using FieldMetadata_FtraceEvents =
    ::protozero::proto_utils::FieldMetadata<
      1,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      FtraceEventBundle,
      TracePacket>;

  static constexpr FieldMetadata_FtraceEvents kFtraceEvents{};
  template <typename T = FtraceEventBundle> T* set_ftrace_events() {
    return BeginNestedMessage<T>(1);
  }


  using FieldMetadata_SynchronizationMarker =
    ::protozero::proto_utils::FieldMetadata<
      36,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kBytes,
      std::string,
      TracePacket>;

  static constexpr FieldMetadata_SynchronizationMarker kSynchronizationMarker{};
  void set_synchronization_marker(const uint8_t* data, size_t size) {
    AppendBytes(FieldMetadata_SynchronizationMarker::kFieldId, data, size);
  }
  void set_synchronization_marker(::protozero::ConstBytes bytes) {
    AppendBytes(FieldMetadata_SynchronizationMarker::kFieldId, bytes.data, bytes.size);
  }
  void set_synchronization_marker(std::string value) {
    static constexpr uint32_t field_id = FieldMetadata_SynchronizationMarker::kFieldId;
    // Call the appropriate protozero::Message::Append(field_id, ...)
    // method based on the type of the field.
    ::protozero::internal::FieldWriter<
      ::protozero::proto_utils::ProtoSchemaType::kBytes>
        ::Append(*this, field_id, value);
  }

  using FieldMetadata_CompressedPackets =
    ::protozero::proto_utils::FieldMetadata<
      50,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kBytes,
      std::string,
      TracePacket>;

  static constexpr FieldMetadata_CompressedPackets kCompressedPackets{};
  void set_compressed_packets(const uint8_t* data, size_t size) {
    AppendBytes(FieldMetadata_CompressedPackets::kFieldId, data, size);
  }
  void set_compressed_packets(::protozero::ConstBytes bytes) {
    AppendBytes(FieldMetadata_CompressedPackets::kFieldId, bytes.data, bytes.size);
  }
  void set_compressed_packets(std::string value) {
    static constexpr uint32_t field_id = FieldMetadata_CompressedPackets::kFieldId;
    // Call the appropriate protozero::Message::Append(field_id, ...)
    // method based on the type of the field.
    ::protozero::internal::FieldWriter<
      ::protozero::proto_utils::ProtoSchemaType::kBytes>
        ::Append(*this, field_id, value);
  }

  using FieldMetadata_ExtensionDescriptor =
    ::protozero::proto_utils::FieldMetadata<
      72,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      ExtensionDescriptor,
      TracePacket>;

  static constexpr FieldMetadata_ExtensionDescriptor kExtensionDescriptor{};
  template <typename T = ExtensionDescriptor> T* set_extension_descriptor() {
    return BeginNestedMessage<T>(72);
  }


  using FieldMetadata_NetworkPacket =
    ::protozero::proto_utils::FieldMetadata<
      88,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      NetworkPacketEvent,
      TracePacket>;

  static constexpr FieldMetadata_NetworkPacket kNetworkPacket{};
  template <typename T = NetworkPacketEvent> T* set_network_packet() {
    return BeginNestedMessage<T>(88);
  }


  using FieldMetadata_NetworkPacketBundle =
    ::protozero::proto_utils::FieldMetadata<
      92,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      NetworkPacketBundle,
      TracePacket>;

  static constexpr FieldMetadata_NetworkPacketBundle kNetworkPacketBundle{};
  template <typename T = NetworkPacketBundle> T* set_network_packet_bundle() {
    return BeginNestedMessage<T>(92);
  }


  using FieldMetadata_TrackEventRangeOfInterest =
    ::protozero::proto_utils::FieldMetadata<
      90,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      TrackEventRangeOfInterest,
      TracePacket>;

  static constexpr FieldMetadata_TrackEventRangeOfInterest kTrackEventRangeOfInterest{};
  template <typename T = TrackEventRangeOfInterest> T* set_track_event_range_of_interest() {
    return BeginNestedMessage<T>(90);
  }


  using FieldMetadata_SurfaceflingerLayersSnapshot =
    ::protozero::proto_utils::FieldMetadata<
      93,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      LayersSnapshotProto,
      TracePacket>;

  static constexpr FieldMetadata_SurfaceflingerLayersSnapshot kSurfaceflingerLayersSnapshot{};
  template <typename T = LayersSnapshotProto> T* set_surfaceflinger_layers_snapshot() {
    return BeginNestedMessage<T>(93);
  }


  using FieldMetadata_SurfaceflingerTransactions =
    ::protozero::proto_utils::FieldMetadata<
      94,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      TransactionTraceEntry,
      TracePacket>;

  static constexpr FieldMetadata_SurfaceflingerTransactions kSurfaceflingerTransactions{};
  template <typename T = TransactionTraceEntry> T* set_surfaceflinger_transactions() {
    return BeginNestedMessage<T>(94);
  }


  using FieldMetadata_ShellTransition =
    ::protozero::proto_utils::FieldMetadata<
      96,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      ShellTransition,
      TracePacket>;

  static constexpr FieldMetadata_ShellTransition kShellTransition{};
  template <typename T = ShellTransition> T* set_shell_transition() {
    return BeginNestedMessage<T>(96);
  }


  using FieldMetadata_ShellHandlerMappings =
    ::protozero::proto_utils::FieldMetadata<
      97,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      ShellHandlerMappings,
      TracePacket>;

  static constexpr FieldMetadata_ShellHandlerMappings kShellHandlerMappings{};
  template <typename T = ShellHandlerMappings> T* set_shell_handler_mappings() {
    return BeginNestedMessage<T>(97);
  }


  using FieldMetadata_ProtologMessage =
    ::protozero::proto_utils::FieldMetadata<
      104,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      ProtoLogMessage,
      TracePacket>;

  static constexpr FieldMetadata_ProtologMessage kProtologMessage{};
  template <typename T = ProtoLogMessage> T* set_protolog_message() {
    return BeginNestedMessage<T>(104);
  }


  using FieldMetadata_ProtologViewerConfig =
    ::protozero::proto_utils::FieldMetadata<
      105,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      ProtoLogViewerConfig,
      TracePacket>;

  static constexpr FieldMetadata_ProtologViewerConfig kProtologViewerConfig{};
  template <typename T = ProtoLogViewerConfig> T* set_protolog_viewer_config() {
    return BeginNestedMessage<T>(105);
  }


  using FieldMetadata_WinscopeExtensions =
    ::protozero::proto_utils::FieldMetadata<
      112,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      WinscopeExtensions,
      TracePacket>;

  static constexpr FieldMetadata_WinscopeExtensions kWinscopeExtensions{};
  template <typename T = WinscopeExtensions> T* set_winscope_extensions() {
    return BeginNestedMessage<T>(112);
  }


  using FieldMetadata_EtwEvents =
    ::protozero::proto_utils::FieldMetadata<
      95,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      EtwTraceEventBundle,
      TracePacket>;

  static constexpr FieldMetadata_EtwEvents kEtwEvents{};
  template <typename T = EtwTraceEventBundle> T* set_etw_events() {
    return BeginNestedMessage<T>(95);
  }


  using FieldMetadata_V8JsCode =
    ::protozero::proto_utils::FieldMetadata<
      99,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      V8JsCode,
      TracePacket>;

  static constexpr FieldMetadata_V8JsCode kV8JsCode{};
  template <typename T = V8JsCode> T* set_v8_js_code() {
    return BeginNestedMessage<T>(99);
  }


  using FieldMetadata_V8InternalCode =
    ::protozero::proto_utils::FieldMetadata<
      100,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      V8InternalCode,
      TracePacket>;

  static constexpr FieldMetadata_V8InternalCode kV8InternalCode{};
  template <typename T = V8InternalCode> T* set_v8_internal_code() {
    return BeginNestedMessage<T>(100);
  }


  using FieldMetadata_V8WasmCode =
    ::protozero::proto_utils::FieldMetadata<
      101,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      V8WasmCode,
      TracePacket>;

  static constexpr FieldMetadata_V8WasmCode kV8WasmCode{};
  template <typename T = V8WasmCode> T* set_v8_wasm_code() {
    return BeginNestedMessage<T>(101);
  }


  using FieldMetadata_V8RegExpCode =
    ::protozero::proto_utils::FieldMetadata<
      102,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      V8RegExpCode,
      TracePacket>;

  static constexpr FieldMetadata_V8RegExpCode kV8RegExpCode{};
  template <typename T = V8RegExpCode> T* set_v8_reg_exp_code() {
    return BeginNestedMessage<T>(102);
  }


  using FieldMetadata_V8CodeMove =
    ::protozero::proto_utils::FieldMetadata<
      103,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      V8CodeMove,
      TracePacket>;

  static constexpr FieldMetadata_V8CodeMove kV8CodeMove{};
  template <typename T = V8CodeMove> T* set_v8_code_move() {
    return BeginNestedMessage<T>(103);
  }


  using FieldMetadata_RemoteClockSync =
    ::protozero::proto_utils::FieldMetadata<
      107,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      RemoteClockSync,
      TracePacket>;

  static constexpr FieldMetadata_RemoteClockSync kRemoteClockSync{};
  template <typename T = RemoteClockSync> T* set_remote_clock_sync() {
    return BeginNestedMessage<T>(107);
  }


  using FieldMetadata_PixelModemEvents =
    ::protozero::proto_utils::FieldMetadata<
      110,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      PixelModemEvents,
      TracePacket>;

  static constexpr FieldMetadata_PixelModemEvents kPixelModemEvents{};
  template <typename T = PixelModemEvents> T* set_pixel_modem_events() {
    return BeginNestedMessage<T>(110);
  }


  using FieldMetadata_PixelModemTokenDatabase =
    ::protozero::proto_utils::FieldMetadata<
      111,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      PixelModemTokenDatabase,
      TracePacket>;

  static constexpr FieldMetadata_PixelModemTokenDatabase kPixelModemTokenDatabase{};
  template <typename T = PixelModemTokenDatabase> T* set_pixel_modem_token_database() {
    return BeginNestedMessage<T>(111);
  }


  using FieldMetadata_CloneSnapshotTrigger =
    ::protozero::proto_utils::FieldMetadata<
      113,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      Trigger,
      TracePacket>;

  static constexpr FieldMetadata_CloneSnapshotTrigger kCloneSnapshotTrigger{};
  template <typename T = Trigger> T* set_clone_snapshot_trigger() {
    return BeginNestedMessage<T>(113);
  }


  using FieldMetadata_ForTesting =
    ::protozero::proto_utils::FieldMetadata<
      900,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      TestEvent,
      TracePacket>;

  static constexpr FieldMetadata_ForTesting kForTesting{};
  template <typename T = TestEvent> T* set_for_testing() {
    return BeginNestedMessage<T>(900);
  }


  using FieldMetadata_TrustedUid =
    ::protozero::proto_utils::FieldMetadata<
      3,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kInt32,
      int32_t,
      TracePacket>;

  static constexpr FieldMetadata_TrustedUid kTrustedUid{};
  void set_trusted_uid(int32_t value) {
    static constexpr uint32_t field_id = FieldMetadata_TrustedUid::kFieldId;
    // Call the appropriate protozero::Message::Append(field_id, ...)
    // method based on the type of the field.
    ::protozero::internal::FieldWriter<
      ::protozero::proto_utils::ProtoSchemaType::kInt32>
        ::Append(*this, field_id, value);
  }

  using FieldMetadata_TrustedPacketSequenceId =
    ::protozero::proto_utils::FieldMetadata<
      10,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kUint32,
      uint32_t,
      TracePacket>;

  static constexpr FieldMetadata_TrustedPacketSequenceId kTrustedPacketSequenceId{};
  void set_trusted_packet_sequence_id(uint32_t value) {
    static constexpr uint32_t field_id = FieldMetadata_TrustedPacketSequenceId::kFieldId;
    // Call the appropriate protozero::Message::Append(field_id, ...)
    // method based on the type of the field.
    ::protozero::internal::FieldWriter<
      ::protozero::proto_utils::ProtoSchemaType::kUint32>
        ::Append(*this, field_id, value);
  }

  using FieldMetadata_TrustedPid =
    ::protozero::proto_utils::FieldMetadata<
      79,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kInt32,
      int32_t,
      TracePacket>;

  static constexpr FieldMetadata_TrustedPid kTrustedPid{};
  void set_trusted_pid(int32_t value) {
    static constexpr uint32_t field_id = FieldMetadata_TrustedPid::kFieldId;
    // Call the appropriate protozero::Message::Append(field_id, ...)
    // method based on the type of the field.
    ::protozero::internal::FieldWriter<
      ::protozero::proto_utils::ProtoSchemaType::kInt32>
        ::Append(*this, field_id, value);
  }

  using FieldMetadata_InternedData =
    ::protozero::proto_utils::FieldMetadata<
      12,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      InternedData,
      TracePacket>;

  static constexpr FieldMetadata_InternedData kInternedData{};
  template <typename T = InternedData> T* set_interned_data() {
    return BeginNestedMessage<T>(12);
  }


  using FieldMetadata_SequenceFlags =
    ::protozero::proto_utils::FieldMetadata<
      13,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kUint32,
      uint32_t,
      TracePacket>;

  static constexpr FieldMetadata_SequenceFlags kSequenceFlags{};
  void set_sequence_flags(uint32_t value) {
    static constexpr uint32_t field_id = FieldMetadata_SequenceFlags::kFieldId;
    // Call the appropriate protozero::Message::Append(field_id, ...)
    // method based on the type of the field.
    ::protozero::internal::FieldWriter<
      ::protozero::proto_utils::ProtoSchemaType::kUint32>
        ::Append(*this, field_id, value);
  }

  using FieldMetadata_IncrementalStateCleared =
    ::protozero::proto_utils::FieldMetadata<
      41,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kBool,
      bool,
      TracePacket>;

  static constexpr FieldMetadata_IncrementalStateCleared kIncrementalStateCleared{};
  void set_incremental_state_cleared(bool value) {
    static constexpr uint32_t field_id = FieldMetadata_IncrementalStateCleared::kFieldId;
    // Call the appropriate protozero::Message::Append(field_id, ...)
    // method based on the type of the field.
    ::protozero::internal::FieldWriter<
      ::protozero::proto_utils::ProtoSchemaType::kBool>
        ::Append(*this, field_id, value);
  }

  using FieldMetadata_TracePacketDefaults =
    ::protozero::proto_utils::FieldMetadata<
      59,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kMessage,
      TracePacketDefaults,
      TracePacket>;

  static constexpr FieldMetadata_TracePacketDefaults kTracePacketDefaults{};
  template <typename T = TracePacketDefaults> T* set_trace_packet_defaults() {
    return BeginNestedMessage<T>(59);
  }


  using FieldMetadata_PreviousPacketDropped =
    ::protozero::proto_utils::FieldMetadata<
      42,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kBool,
      bool,
      TracePacket>;

  static constexpr FieldMetadata_PreviousPacketDropped kPreviousPacketDropped{};
  void set_previous_packet_dropped(bool value) {
    static constexpr uint32_t field_id = FieldMetadata_PreviousPacketDropped::kFieldId;
    // Call the appropriate protozero::Message::Append(field_id, ...)
    // method based on the type of the field.
    ::protozero::internal::FieldWriter<
      ::protozero::proto_utils::ProtoSchemaType::kBool>
        ::Append(*this, field_id, value);
  }

  using FieldMetadata_FirstPacketOnSequence =
    ::protozero::proto_utils::FieldMetadata<
      87,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kBool,
      bool,
      TracePacket>;

  static constexpr FieldMetadata_FirstPacketOnSequence kFirstPacketOnSequence{};
  void set_first_packet_on_sequence(bool value) {
    static constexpr uint32_t field_id = FieldMetadata_FirstPacketOnSequence::kFieldId;
    // Call the appropriate protozero::Message::Append(field_id, ...)
    // method based on the type of the field.
    ::protozero::internal::FieldWriter<
      ::protozero::proto_utils::ProtoSchemaType::kBool>
        ::Append(*this, field_id, value);
  }

  using FieldMetadata_MachineId =
    ::protozero::proto_utils::FieldMetadata<
      98,
      ::protozero::proto_utils::RepetitionType::kNotRepeated,
      ::protozero::proto_utils::ProtoSchemaType::kUint32,
      uint32_t,
      TracePacket>;

  static constexpr FieldMetadata_MachineId kMachineId{};
  void set_machine_id(uint32_t value) {
    static constexpr uint32_t field_id = FieldMetadata_MachineId::kFieldId;
    // Call the appropriate protozero::Message::Append(field_id, ...)
    // method based on the type of the field.
    ::protozero::internal::FieldWriter<
      ::protozero::proto_utils::ProtoSchemaType::kUint32>
        ::Append(*this, field_id, value);
  }
};

// Namespace.
// Namespace.
// Namespace.
#endif  // Include guard.
/*
 * Copyright (C) 2019 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.
 */


#ifndef INCLUDE_PERFETTO_TRACING_DATA_SOURCE_H_
#define INCLUDE_PERFETTO_TRACING_DATA_SOURCE_H_

// This header contains the key class (DataSource) that a producer app should
// override in order to create a custom data source that gets tracing Start/Stop
// notifications and emits tracing data.

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

#include <array>
#include <atomic>
#include <functional>
#include <memory>
#include <mutex>

// gen_amalgamated expanded: #include "perfetto/protozero/message_handle.h"
// gen_amalgamated expanded: #include "perfetto/tracing/buffer_exhausted_policy.h"
// gen_amalgamated expanded: #include "perfetto/tracing/core/flush_flags.h"
// gen_amalgamated expanded: #include "perfetto/tracing/core/forward_decls.h"
// gen_amalgamated expanded: #include "perfetto/tracing/internal/basic_types.h"
// gen_amalgamated expanded: #include "perfetto/tracing/internal/data_source_internal.h"
// gen_amalgamated expanded: #include "perfetto/tracing/internal/data_source_type.h"
// gen_amalgamated expanded: #include "perfetto/tracing/internal/tracing_muxer.h"
// gen_amalgamated expanded: #include "perfetto/tracing/locked_handle.h"
// gen_amalgamated expanded: #include "perfetto/tracing/trace_writer_base.h"

// gen_amalgamated expanded: #include "protos/perfetto/trace/trace_packet.pbzero.h"

// DEPRECATED: Instead of using this macro, prefer specifying symbol linkage
// attributes explicitly using the `_WITH_ATTRS` macro variants (e.g.,
// PERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS_WITH_ATTRS). This avoids
// potential macro definition collisions between two libraries using Perfetto.
//
// PERFETTO_COMPONENT_EXPORT is used to mark symbols in Perfetto's headers
// (typically templates) that are defined by the user outside of Perfetto and
// should be made visible outside the current module. (e.g., in Chrome's
// component build).
#if !defined(PERFETTO_COMPONENT_EXPORT)
#if PERFETTO_BUILDFLAG(PERFETTO_COMPILER_MSVC)
// Workaround for C4003: not enough arguments for function-like macro invocation
// 'PERFETTO_INTERNAL_DECLARE_TRACK_EVENT_DATA_SOURCE'
#define PERFETTO_COMPONENT_EXPORT __declspec()
#else
#define PERFETTO_COMPONENT_EXPORT
#endif
#endif

namespace perfetto {
namespace internal {
class TracingMuxerImpl;
class TrackEventCategoryRegistry;
template <typenameconst internal::TrackEventCategoryRegistry*>
class TrackEventDataSource;
}  // namespace internal

namespace shlib {
class TrackEvent;
}  // namespace shlib

namespace test {
class DataSourceInternalForTest;
}  // namespace test

// Base class with the virtual methods to get start/stop notifications.
// Embedders are supposed to derive the templated version below, not this one.
class PERFETTO_EXPORT_COMPONENT DataSourceBase {
 public:
  virtual ~DataSourceBase();

  // TODO(primiano): change the const& args below to be pointers instead. It
  // makes it more awkward to handle output arguments and require mutable(s).
  // This requires synchronizing a breaking API change for existing embedders.

  // OnSetup() is invoked when tracing is configured. In most cases this happens
  // just before starting the trace. In the case of deferred start (see
  // deferred_start in trace_config.proto) start might happen later.
  //
  // Can be called from any thread.
  class SetupArgs {
   public:
    // This is valid only within the scope of the OnSetup() call and must not
    // be retained.
    const DataSourceConfig* config = nullptr;

    // Backend type.
    BackendType backend_type = kUnspecifiedBackend;

    // The index of this data source instance (0..kMaxDataSourceInstances - 1).
    uint32_t internal_instance_index = 0;
  };
  virtual void OnSetup(const SetupArgs&);

  class StartArgs {
   public:
    // The index of this data source instance (0..kMaxDataSourceInstances - 1).
    uint32_t internal_instance_index = 0;
  };
  // Invoked after tracing is actually started.
  //
  // Can be called from any thread.
  virtual void OnStart(const StartArgs&);

  class PERFETTO_EXPORT_COMPONENT StopArgs {
   public:
    virtual ~StopArgs();

    // HandleAsynchronously() can optionally be called to defer the tracing
    // session stop and write tracing data just before stopping.
    // This function returns a closure that must be invoked after the last
    // trace events have been emitted. The returned closure can be called from
    // any thread. The caller also needs to explicitly call TraceContext.Flush()
    // from the last Trace() lambda invocation because no other implicit flushes
    // will happen after the stop signal.
    // When this function is called, the tracing service will defer the stop of
    // the tracing session until the returned closure is invoked.
    // However, the caller cannot hang onto this closure for too long. The
    // tracing service will forcefully stop the tracing session without waiting
    // for pending producers after TraceConfig.data_source_stop_timeout_ms
    // (default: 5s, can be overridden by Consumers when starting a trace).
    // If the closure is called after this timeout an error will be logged and
    // the trace data emitted will not be present in the trace. No other
    // functional side effects (e.g. crashes or corruptions) will happen. In
    // other words, it is fine to accidentally hold onto this closure for too
    // long but, if that happens, some tracing data will be lost.
    virtual std::function<void()> HandleStopAsynchronously() const = 0;

    // The index of this data source instance (0..kMaxDataSourceInstances - 1).
    uint32_t internal_instance_index = 0;
  };
  // Invoked before tracing is stopped.
  //
  // Can be called from any thread. Blocking this for too long it's not a good
  // idea and can cause deadlocks. Use HandleAsynchronously() to postpone
  // disabling the data source instance.
  virtual void OnStop(const StopArgs&);

  class ClearIncrementalStateArgs {
   public:
    // The index of this data source instance (0..kMaxDataSourceInstances - 1).
    uint32_t internal_instance_index = 0;
  };
  // Invoked before marking the thread local per-instance incremental state
  // outdated.
  //
  // Can be called from any thread.
  virtual void WillClearIncrementalState(const ClearIncrementalStateArgs&);

  class FlushArgs {
   public:
    virtual ~FlushArgs();

    // HandleFlushAsynchronously() can be called to postpone acknowledging the
    // flush request. This function returns a closure that must be invoked after
    // the flush request has been processed. The returned closure can be called
    // from any thread.
    virtual std::function<void()> HandleFlushAsynchronously() const = 0;

    // The index of this data source instance (0..kMaxDataSourceInstances - 1).
    uint32_t internal_instance_index = 0;

    // The reason and initiator of the flush. See flush_flags.h .
    FlushFlags flush_flags;
  };
  // Called when the tracing service requests a Flush. Users can override this
  // to tell other threads to flush their TraceContext for this data source
  // (the library cannot execute code on all the threads on its own).
  //
  // Can be called from any thread. Blocking this for too long it's not a good
  // idea and can cause deadlocks. Use HandleAsynchronously() to postpone
  // sending the flush acknowledgement to the service.
  virtual void OnFlush(const FlushArgs&);

  // Determines whether a startup session can be adopted by a service-initiated
  // tracing session (i.e. whether their configs are compatible).
  virtual bool CanAdoptStartupSession(const DataSourceConfig& startup_config,
                                      const DataSourceConfig& service_config);
};

struct DefaultDataSourceTraits {
  // |IncrementalStateType| can optionally be used store custom per-sequence
  // incremental data (e.g., interning tables).
  using IncrementalStateType = void;
  // |TlsStateType| can optionally be used to store custom per-sequence
  // session data, which is not reset when incremental state is cleared
  // (e.g. configuration options).
  using TlsStateType = void;

  // Allows overriding what type of thread-local state configuration the data
  // source uses. By default every data source gets independent thread-local
  // state, which means every instance uses separate trace writers and
  // incremental state even on the same thread. Some data sources (most notably
  // the track event data source) want to share trace writers and incremental
  // state on the same thread.
  static internal::DataSourceThreadLocalState* GetDataSourceTLS(
      internal::DataSourceStaticState* static_state,
      internal::TracingTLS* root_tls) {
    auto* ds_tls = &root_tls->data_sources_tls[static_state->index];
    // ds_tls->static_state can be:
    // * nullptr
    // * equal to static_state
    // * equal to the static state of a different data source, in tests (when
    //   ResetForTesting() has been used)
    // In any case, there's no need to do anything, the caller will reinitialize
    // static_state.
    return ds_tls;
  }
};

// Holds the type for a DataSource. Accessed by the static Trace() method
// fastpaths. This allows redefinitions under a component where a component
// specific export macro is used.
// Due to C2086 (redefinition) error on MSVC/clang-cl, internal::DataSourceType
// can't be a static data member. To avoid explicit specialization after
// instantiation error, type() needs to be in a template helper class that's
// instantiated independently from DataSource. See b/280777748.
template <typename DerivedDataSource,
          typename DataSourceTraits = DefaultDataSourceTraits>
struct DataSourceHelper {
  static internal::DataSourceType& type() {
    static perfetto::internal::DataSourceType type_;
    return type_;
  }
};

// Templated base class meant to be derived by embedders to create a custom data
// source. DerivedDataSource must be the type of the derived class itself, e.g.:
// class MyDataSource : public DataSource<MyDataSource> {...}.
//
// |DataSourceTraits| allows customizing the behavior of the data source. See
// |DefaultDataSourceTraits|.
template <typename DerivedDataSource,
          typename DataSourceTraits = DefaultDataSourceTraits>
class DataSource : public DataSourceBase {
  struct DefaultTracePointTraits;
  using Helper = DataSourceHelper<DerivedDataSource, DataSourceTraits>;

 public:
  // The BufferExhaustedPolicy to use for TraceWriters of this DataSource.
  // Override this in your DataSource class to change the default, which is to
  // drop data on shared memory overruns.
  constexpr static BufferExhaustedPolicy kBufferExhaustedPolicy =
      BufferExhaustedPolicy::kDrop;

  // When this flag is false, we cannot have multiple instances of this data
  // source. When a data source is already active and if we attempt
  // to start another instance of that data source (via another tracing
  // session), it will fail to start the second instance of data source.
  static constexpr bool kSupportsMultipleInstances = true;

  // When this flag is true, DataSource callbacks (OnSetup, OnStart, etc.) are
  // called under the lock (the same that is used in GetDataSourceLocked
  // function). This is not recommended because it can lead to deadlocks, but
  // it was the default behavior for a long time and some embedders rely on it
  // to protect concurrent access to the DataSource members. So we keep the
  // "true" value as the default.
  static constexpr bool kRequiresCallbacksUnderLock = true;

  // Argument passed to the lambda function passed to Trace() (below).
  class TraceContext {
   public:
    using TracePacketHandle =
        ::protozero::MessageHandle<::perfetto::protos::pbzero::TracePacket>;

    TraceContext(TraceContext&&) noexcept = default;
    ~TraceContext() {
      // If the data source is being intercepted, flush the trace writer after
      // each trace point to make sure the interceptor sees the data right away.
      if (PERFETTO_UNLIKELY(tls_inst_->is_intercepted))
        Flush();
    }

    // Adds an empty trace packet to the trace to ensure that the service can
    // safely read the last event from the trace buffer.
    // See PERFETTO_INTERNAL_ADD_EMPTY_EVENT macros for context.
    void AddEmptyTracePacket() {
      // If nothing was written since the last empty packet, there's nothing to
      // scrape, so adding more empty packets serves no purpose.
      if (tls_inst_->trace_writer->written() ==
          tls_inst_->last_empty_packet_position) {
        return;
      }
      tls_inst_->trace_writer->NewTracePacket();
      tls_inst_->last_empty_packet_position =
          tls_inst_->trace_writer->written();
    }

    TracePacketHandle NewTracePacket() {
      return tls_inst_->trace_writer->NewTracePacket();
    }

    // Forces a commit of the thread-local tracing data written so far to the
    // service. This is almost never required (tracing data is periodically
    // committed as trace pages are filled up) and has a non-negligible
    // performance hit (requires an IPC + refresh of the current thread-local
    // chunk). The only case when this should be used is when handling OnStop()
    // asynchronously, to ensure sure that the data is committed before the
    // Stop timeout expires.
    // The TracePacketHandle obtained by the last NewTracePacket() call must be
    // finalized before calling Flush() (either implicitly by going out of scope
    // or by explicitly calling Finalize()).
    // |cb| is an optional callback. When non-null it will request the
    // service to ACK the flush and will be invoked on an internal thread after
    // the service has  acknowledged it. The callback might be NEVER INVOKED if
    // the service crashes or the IPC connection is dropped.
    void Flush(std::function<void()> cb = {}) {
      tls_inst_->trace_writer->Flush(cb);
    }

    // Returns the number of bytes written on the current thread by the current
    // data-source since its creation.
    // This can be useful for splitting protos that might grow very large.
    uint64_t written() { return tls_inst_->trace_writer->written(); }

    // Returns a RAII handle to access the data source instance, guaranteeing
    // that it won't be deleted on another thread (because of trace stopping)
    // while accessing it from within the Trace() lambda.
    // The returned handle can be invalid (nullptr) if tracing is stopped
    // immediately before calling this. The caller is supposed to check for its
    // validity before using it. After checking, the handle is guaranteed to
    // remain valid until the handle goes out of scope.
    LockedHandle<DerivedDataSource> GetDataSourceLocked() const {
      auto* internal_state =
          Helper::type().static_state()->TryGet(instance_index_);
      if (!internal_state)
        return LockedHandle<DerivedDataSource>();
      std::unique_lock<std::recursive_mutex> lock(internal_state->lock);
      return LockedHandle<DerivedDataSource>(
          std::move(lock),
          static_cast<DerivedDataSource*>(internal_state->data_source.get()));
    }

    // Post-condition: returned ptr will be non-null.
    typename DataSourceTraits::TlsStateType* GetCustomTlsState() {
      PERFETTO_DCHECK(tls_inst_->data_source_custom_tls);
      return reinterpret_cast<typename DataSourceTraits::TlsStateType*>(
          tls_inst_->data_source_custom_tls.get());
    }

    typename DataSourceTraits::IncrementalStateType* GetIncrementalState() {
      return static_cast<typename DataSourceTraits::IncrementalStateType*>(
          Helper::type().GetIncrementalState(tls_inst_, instance_index_));
    }

   private:
    friend class DataSource;
    template <typenameconst internal::TrackEventCategoryRegistry*>
    friend class internal::TrackEventDataSource;
    TraceContext(internal::DataSourceInstanceThreadLocalState* tls_inst,
                 uint32_t instance_index)
        : tls_inst_(tls_inst), instance_index_(instance_index) {}
    TraceContext(const TraceContext&) = delete;
    TraceContext& operator=(const TraceContext&) = delete;

    internal::DataSourceInstanceThreadLocalState* const tls_inst_;
    uint32_t const instance_index_;
  };

  // The main tracing method. Tracing code should call this passing a lambda as
  // argument, with the following signature: void(TraceContext).
  // The lambda will be called synchronously (i.e., always before Trace()
  // returns) only if tracing is enabled and the data source has been enabled in
  // the tracing config.
  // The lambda can be called more than once per Trace() call, in the case of
  // concurrent tracing sessions (or even if the data source is instantiated
  // twice within the same trace config).
  template <typename Lambda>
  static void Trace(Lambda tracing_fn) {
    CallIfEnabled<DefaultTracePointTraits>([&tracing_fn](uint32_t instances) {
      TraceWithInstances<DefaultTracePointTraits>(instances,
                                                  std::move(tracing_fn));
    });
  }

  // An efficient trace point guard for checking if this data source is active.
  // |callback| is a function which will only be called if there are active
  // instances. It is given an instance state parameter, which should be passed
  // to TraceWithInstances() to actually record trace data.
  template <typename Traits = DefaultTracePointTraits, typename Callback>
  static void CallIfEnabled(Callback callback,
                            typename Traits::TracePointData trace_point_data =
                                {}) PERFETTO_ALWAYS_INLINE {
    // |instances| is a per-class bitmap that tells:
    // 1. If the data source is enabled at all.
    // 2. The index of the slot within
    //    internal::DataSourceStaticState::instances that holds the instance
    //    state. In turn this allows to map the data source to the tracing
    //    session and buffers.
    // memory_order_relaxed is okay because:
    // - |instances| is re-read with an acquire barrier below if this succeeds.
    // - The code between this point and the acquire-load is based on static
    //    storage which has indefinite lifetime.
    uint32_t instances = Traits::GetActiveInstances(trace_point_data)
                             ->load(std::memory_order_relaxed);

    // This is the tracing fast-path. Bail out immediately if tracing is not
    // enabled (or tracing is enabled but not for this data source).
    if (PERFETTO_LIKELY(!instances))
      return;
    callback(instances);
  }

  // The "lower half" of a trace point which actually performs tracing after
  // this data source has been determined to be active.
  // |instances| must be the instance state value retrieved through
  // CallIfEnabled().
  // |tracing_fn| will be called to record trace data as in Trace().
  //
  // |trace_point_data| is an optional parameter given to |Traits::
  // GetActiveInstances| to make it possible to use custom storage for
  // the data source enabled state. This is, for example, used by TrackEvent to
  // implement per-tracing category enabled states.
  template <typename Traits = DefaultTracePointTraits, typename Lambda>
  static void TraceWithInstances(
      uint32_t cached_instances,
      Lambda tracing_fn,
      typename Traits::TracePointData trace_point_data = {}) {
    PERFETTO_DCHECK(cached_instances);

    if (!Helper::type().template TracePrologue<DataSourceTraits, Traits>(
            &tls_state_, &cached_instances, trace_point_data)) {
      return;
    }

    for (internal::DataSourceType::InstancesIterator it =
             Helper::type().template BeginIteration<Traits>(
                 cached_instances, tls_state_, trace_point_data);
         it.instance; Helper::type().template NextIteration<Traits>(
             &it, tls_state_, trace_point_data)) {
      tracing_fn(TraceContext(it.instance, it.i));
    }

    Helper::type().TraceEpilogue(tls_state_);
  }

  // Registers the data source on all tracing backends, including ones that
  // connect after the registration. Doing so enables the data source to receive
  // Setup/Start/Stop notifications and makes the Trace() method work when
  // tracing is enabled and the data source is selected.
  // This must be called after Tracing::Initialize().
  // Can return false to signal failure if attemping to register more than
  // kMaxDataSources (32) data sources types or if tracing hasn't been
  // initialized.
  // The optional |constructor_args| will be passed to the data source when it
  // is constructed.
  template <class... Args>
  static bool Register(const DataSourceDescriptor& descriptor,
                       const Args&... constructor_args) {
    // Silences -Wunused-variable warning in case the trace method is not used
    // by the translation unit that declares the data source.
    (void)tls_state_;

    auto factory = [constructor_args...]() {
      return std::unique_ptr<DataSourceBase>(
          new DerivedDataSource(constructor_args...));
    };
    constexpr bool no_flush =
        std::is_same_v<decltype(&DerivedDataSource::OnFlush),
                       decltype(&DataSourceBase::OnFlush)>;
    internal::DataSourceParams params{
        DerivedDataSource::kSupportsMultipleInstances,
        DerivedDataSource::kRequiresCallbacksUnderLock};
    return Helper::type().Register(
        descriptor, factory, params, DerivedDataSource::kBufferExhaustedPolicy,
        no_flush,
        GetCreateTlsFn(
            static_cast<typename DataSourceTraits::TlsStateType*>(nullptr)),
        GetCreateIncrementalStateFn(
            static_cast<typename DataSourceTraits::IncrementalStateType*>(
                nullptr)),
        nullptr);
  }

  // Updates the data source descriptor.
  static void UpdateDescriptor(const DataSourceDescriptor& descriptor) {
    Helper::type().UpdateDescriptor(descriptor);
  }

 private:
  friend ::perfetto::test::DataSourceInternalForTest;
  friend ::perfetto::shlib::TrackEvent;
  // Traits for customizing the behavior of a specific trace point.
  struct DefaultTracePointTraits {
    // By default, every call to DataSource::Trace() will record trace events
    // for every active instance of that data source. A single trace point can,
    // however, use a custom set of enable flags for more fine grained control
    // of when that trace point is active.
    //
    // DANGER: when doing this, the data source must use the appropriate memory
    // fences when changing the state of the bitmap.
    //
    // |TraceWithInstances| may be optionally given an additional parameter for
    // looking up the enable flags. That parameter is passed as |TracePointData|
    // to |GetActiveInstances|. This is, for example, used by TrackEvent to
    // implement per-category enabled states.
    struct TracePointData {};
    static constexpr std::atomic<uint32_t>* GetActiveInstances(TracePointData) {
      return Helper::type().valid_instances();
    }
  };

  template <typename T>
  static internal::DataSourceInstanceThreadLocalState::ObjectWithDeleter
  CreateIncrementalState(internal::DataSourceInstanceThreadLocalState*,
                         uint32_t,
                         void*) {
    return internal::DataSourceInstanceThreadLocalState::ObjectWithDeleter(
        reinterpret_cast<void*>(new T()),
        [](void* p) { delete reinterpret_cast<T*>(p); });
  }

  // The second parameter here is used to specialize the case where there is no
  // incremental state type.
  template <typename T>
  static internal::DataSourceType::CreateIncrementalStateFn
  GetCreateIncrementalStateFn(const T*) {
    return &CreateIncrementalState<T>;
  }

  static internal::DataSourceType::CreateIncrementalStateFn
  GetCreateIncrementalStateFn(const void*) {
    return nullptr;
  }

  template <typename T>
  static internal::DataSourceInstanceThreadLocalState::ObjectWithDeleter
  CreateDataSourceCustomTls(
      internal::DataSourceInstanceThreadLocalState* tls_inst,
      uint32_t instance_index,
      void*) {
    return internal::DataSourceInstanceThreadLocalState::ObjectWithDeleter(
        reinterpret_cast<void*>(new T(TraceContext(tls_inst, instance_index))),
        [](void* p) { delete reinterpret_cast<T*>(p); });
  }

  // The second parameter here is used to specialize the case where there is no
  // tls state type.
  template <typename T>
  static internal::DataSourceType::CreateCustomTlsFn GetCreateTlsFn(const T*) {
    return &CreateDataSourceCustomTls<T>;
  }

  static internal::DataSourceType::CreateCustomTlsFn GetCreateTlsFn(
      const void*) {
    return nullptr;
  }

  // This TLS object is a cached raw pointer and has deliberately no destructor.
  // The Platform implementation is supposed to create and manage the lifetime
  // of the Platform::ThreadLocalObject and take care of destroying it.
  // This is because non-POD thread_local variables have subtleties (global
  // destructors) that we need to defer to the embedder. In chromium's platform
  // implementation, for instance, the tls slot is implemented using
  // chromium's base::ThreadLocalStorage.
  static thread_local internal::DataSourceThreadLocalState* tls_state_;
};

// static
template <typename T, typename D>
thread_local internal::DataSourceThreadLocalState* DataSource<T, D>::tls_state_;

}  // namespace perfetto

// If placed at the end of a macro declaration, eats the semicolon at the end of
// the macro invocation (e.g., "MACRO(...);") to avoid warnings about extra
// semicolons.
#define PERFETTO_INTERNAL_SWALLOW_SEMICOLON() \
  extern int perfetto_internal_unused

// This macro must be used once for each data source next to the data source's
// declaration.
#define PERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS(...)  \
  PERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS_WITH_ATTRS( \
      PERFETTO_COMPONENT_EXPORT, __VA_ARGS__)

// Similar to `PERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS` but it also takes
// custom attributes, which are useful when DataSource is defined in a component
// where a component specific export macro is used.
#define PERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS_WITH_ATTRS(attrs, ...) \
  template <>                                                              \
  attrs perfetto::internal::DataSourceType&                                \
  perfetto::DataSourceHelper<__VA_ARGS__>::type()

// This macro must be used once for each data source in one source file to
// allocate static storage for the data source's static state.
#define PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(...)  \
  PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS_WITH_ATTRS( \
      PERFETTO_COMPONENT_EXPORT, __VA_ARGS__)

// Similar to `PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS` but it also takes
// custom attributes, which are useful when DataSource is defined in a component
// where a component specific export macro is used.
#define PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS_WITH_ATTRS(attrs, ...) \
  template <>                                                             \
  perfetto::internal::DataSourceType&                                     \
  perfetto::DataSourceHelper<__VA_ARGS__>::type() {                       \
    static perfetto::internal::DataSourceType type_;                      \
    return type_;                                                         \
  }                                                                       \
  PERFETTO_INTERNAL_SWALLOW_SEMICOLON()

#endif  // INCLUDE_PERFETTO_TRACING_DATA_SOURCE_H_
// gen_amalgamated begin header: include/perfetto/tracing/track_event.h
// gen_amalgamated begin header: include/perfetto/tracing/internal/track_event_data_source.h
// gen_amalgamated begin header: include/perfetto/base/template_util.h
/*
 * 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.
 */


#ifndef INCLUDE_PERFETTO_BASE_TEMPLATE_UTIL_H_
#define INCLUDE_PERFETTO_BASE_TEMPLATE_UTIL_H_

#include <cstddef>
#include <type_traits>

namespace perfetto {
namespace base {

// Helper to express preferences in an overload set. If more than one overload
// is available for a given set of parameters the overload with the higher
// priority will be chosen.
template <size_t I>
struct priority_tag : priority_tag<I - 1> {};

template <>
struct priority_tag<0> {};

// enable_if_t is an implementation of std::enable_if_t from C++14.
//
// Specification:
// https://en.cppreference.com/w/cpp/types/enable_if
template <bool B, class T = void>
using enable_if_t = typename std::enable_if<B, T>::type;

// decay_t is an implementation of std::decay_t from C++14.
//
// Specification:
// https://en.cppreference.com/w/cpp/types/decay
template <class T>
using decay_t = typename std::decay<T>::type;

// remove_cvref is an implementation of std::remove_cvref from
// C++20.
//
// Specification:
// https://en.cppreference.com/w/cpp/types/remove_cvref

template <class T>
struct remove_cvref {
  using type = typename std::remove_cv<typename std::remove_cv<
      typename std::remove_reference<T>::type>::type>::type;
};
template <class T>
using remove_cvref_t = typename remove_cvref<T>::type;

// Check if a given type is a specialization of a given template:
// is_specialization<T, std::vector>::value.

template <typename Type, template <typename...> class Template>
struct is_specialization : std::false_type {};

template <template <typename...> class Ref, typename... Args>
struct is_specialization<Ref<Args...>, Ref> : std::true_type {};

}  // namespace base
}  // namespace perfetto

#endif  // INCLUDE_PERFETTO_BASE_TEMPLATE_UTIL_H_
// gen_amalgamated begin header: include/perfetto/base/thread_annotations.h
/*
 * Copyright (C) 2024 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.
 */


#ifndef INCLUDE_PERFETTO_BASE_THREAD_ANNOTATIONS_H_
#define INCLUDE_PERFETTO_BASE_THREAD_ANNOTATIONS_H_

// This header file contains macro definitions for thread safety annotations
// that allow developers to document the locking policies of multi-threaded
// code. The annotations can also help program analysis tools to identify
// potential thread safety issues.
//
// These macro definitions are copied from the Chromium code base:
// https://source.chromium.org/chromium/chromium/src/+/main:base/thread_annotations.h;drc=10d865767e72f494da1e4e868eb6ae9befe87422
// with the 'PERFETTO_' prefix added.
//
// Note that no analysis is done inside constructors and destructors,
// regardless of what attributes are used. See
// https://clang.llvm.org/docs/ThreadSafetyAnalysis.html#no-checking-inside-constructors-and-destructors
// for details.
//
// Note that the annotations we use are described as deprecated in the Clang
// documentation, linked below. E.g. we use PERFETTO_EXCLUSIVE_LOCKS_REQUIRED
// where the Clang docs use REQUIRES.
//
// http://clang.llvm.org/docs/ThreadSafetyAnalysis.html
//
// We use the deprecated Clang annotations to match Abseil (relevant header
// linked below) and its ecosystem of libraries. We will follow Abseil with
// respect to upgrading to more modern annotations.
//
// https://github.com/abseil/abseil-cpp/blob/master/absl/base/thread_annotations.h
//
// These annotations are implemented using compiler attributes. Using the macros
// defined here instead of raw attributes allow for portability and future
// compatibility.
//
// When referring to mutexes in the arguments of the attributes, you should
// use variable names or more complex expressions (e.g. my_object->mutex_)
// that evaluate to a concrete mutex object whenever possible. If the mutex
// you want to refer to is not in scope, you may use a member pointer
// (e.g. &MyClass::mutex_) to refer to a mutex in some (unknown) object.

// gen_amalgamated expanded: #include "perfetto/base/build_config.h"

#if defined(__clang__) && PERFETTO_BUILDFLAG(PERFETTO_THREAD_SAFETY_ANNOTATIONS)
#define PERFETTO_THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x))
#else
#define PERFETTO_THREAD_ANNOTATION_ATTRIBUTE__(x)  // no-op
#endif

// PERFETTO_GUARDED_BY()
//
// Documents if a shared field or global variable needs to be protected by a
// mutex. PERFETTO_GUARDED_BY() allows the user to specify a particular mutex
// that should be held when accessing the annotated variable.
//
// Example:
//
//   Mutex mu;
//   int p1 PERFETTO_GUARDED_BY(mu);
#define PERFETTO_GUARDED_BY(x) \
  PERFETTO_THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x))

// PERFETTO_PT_GUARDED_BY()
//
// Documents if the memory location pointed to by a pointer should be guarded
// by a mutex when dereferencing the pointer.
//
// Example:
//   Mutex mu;
//   int *p1 PERFETTO_PT_GUARDED_BY(mu);
//
// Note that a pointer variable to a shared memory location could itself be a
// shared variable.
//
// Example:
//
//     // `q`, guarded by `mu1`, points to a shared memory location that is
//     // guarded by `mu2`:
//     int *q PERFETTO_GUARDED_BY(mu1) PERFETTO_PT_GUARDED_BY(mu2);
#define PERFETTO_PT_GUARDED_BY(x) \
  PERFETTO_THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x))

// PERFETTO_ACQUIRED_AFTER() / PERFETTO_ACQUIRED_BEFORE()
//
// Documents the acquisition order between locks that can be held
// simultaneously by a thread. For any two locks that need to be annotated
// to establish an acquisition order, only one of them needs the annotation.
// (i.e. You don't have to annotate both locks with both PERFETTO_ACQUIRED_AFTER
// and PERFETTO_ACQUIRED_BEFORE.)
//
// Example:
//
//   Mutex m1;
//   Mutex m2 PERFETTO_ACQUIRED_AFTER(m1);
#define PERFETTO_ACQUIRED_AFTER(...) \
  PERFETTO_THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__))

#define PERFETTO_ACQUIRED_BEFORE(...) \
  PERFETTO_THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__))

// PERFETTO_EXCLUSIVE_LOCKS_REQUIRED() / PERFETTO_SHARED_LOCKS_REQUIRED()
//
// Documents a function that expects a mutex to be held prior to entry.
// The mutex is expected to be held both on entry to, and exit from, the
// function.
//
// Example:
//
//   Mutex mu1, mu2;
//   int a PERFETTO_GUARDED_BY(mu1);
//   int b PERFETTO_GUARDED_BY(mu2);
//
//   void foo() PERFETTO_EXCLUSIVE_LOCKS_REQUIRED(mu1, mu2) { ... };
#define PERFETTO_EXCLUSIVE_LOCKS_REQUIRED(...) \
  PERFETTO_THREAD_ANNOTATION_ATTRIBUTE__(exclusive_locks_required(__VA_ARGS__))

#define PERFETTO_SHARED_LOCKS_REQUIRED(...) \
  PERFETTO_THREAD_ANNOTATION_ATTRIBUTE__(shared_locks_required(__VA_ARGS__))

// PERFETTO_LOCKS_EXCLUDED()
//
// Documents the locks acquired in the body of the function. These locks
// cannot be held when calling this function (as Abseil's `Mutex` locks are
// non-reentrant).
#define PERFETTO_LOCKS_EXCLUDED(...) \
  PERFETTO_THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__))

// PERFETTO_LOCK_RETURNED()
//
// Documents a function that returns a mutex without acquiring it.  For example,
// a public getter method that returns a pointer to a private mutex should
// be annotated with PERFETTO_LOCK_RETURNED.
#define PERFETTO_LOCK_RETURNED(x) \
  PERFETTO_THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x))

// PERFETTO_LOCKABLE
//
// Documents if a class/type is a lockable type (such as the `Mutex` class).
#define PERFETTO_LOCKABLE PERFETTO_THREAD_ANNOTATION_ATTRIBUTE__(lockable)

// PERFETTO_SCOPED_LOCKABLE
//
// Documents if a class does RAII locking (such as the `MutexLock` class).
// The constructor should use `LOCK_FUNCTION()` to specify the mutex that is
// acquired, and the destructor should use `PERFETTO_UNLOCK_FUNCTION()` with no
// arguments; the analysis will assume that the destructor unlocks whatever the
// constructor locked.
#define PERFETTO_SCOPED_LOCKABLE \
  PERFETTO_THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable)

// PERFETTO_EXCLUSIVE_LOCK_FUNCTION()
//
// Documents functions that acquire a lock in the body of a function, and do
// not release it.
#define PERFETTO_EXCLUSIVE_LOCK_FUNCTION(...) \
  PERFETTO_THREAD_ANNOTATION_ATTRIBUTE__(exclusive_lock_function(__VA_ARGS__))

// PERFETTO_SHARED_LOCK_FUNCTION()
//
// Documents functions that acquire a shared (reader) lock in the body of a
// function, and do not release it.
#define PERFETTO_SHARED_LOCK_FUNCTION(...) \
  PERFETTO_THREAD_ANNOTATION_ATTRIBUTE__(shared_lock_function(__VA_ARGS__))

// PERFETTO_UNLOCK_FUNCTION()
//
// Documents functions that expect a lock to be held on entry to the function,
// and release it in the body of the function.
#define PERFETTO_UNLOCK_FUNCTION(...) \
  PERFETTO_THREAD_ANNOTATION_ATTRIBUTE__(unlock_function(__VA_ARGS__))

// PERFETTO_EXCLUSIVE_TRYLOCK_FUNCTION() / PERFETTO_SHARED_TRYLOCK_FUNCTION()
//
// Documents functions that try to acquire a lock, and return success or failure
// (or a non-boolean value that can be interpreted as a boolean).
// The first argument should be `true` for functions that return `true` on
// success, or `false` for functions that return `false` on success. The second
// argument specifies the mutex that is locked on success. If unspecified, this
// mutex is assumed to be `this`.
#define PERFETTO_EXCLUSIVE_TRYLOCK_FUNCTION(...) \
  PERFETTO_THREAD_ANNOTATION_ATTRIBUTE__(        \
      exclusive_trylock_function(__VA_ARGS__))

#define PERFETTO_SHARED_TRYLOCK_FUNCTION(...) \
  PERFETTO_THREAD_ANNOTATION_ATTRIBUTE__(shared_trylock_function(__VA_ARGS__))

// PERFETTO_ASSERT_EXCLUSIVE_LOCK() / PERFETTO_ASSERT_SHARED_LOCK()
//
// Documents functions that dynamically check to see if a lock is held, and fail
// if it is not held.
#define PERFETTO_ASSERT_EXCLUSIVE_LOCK(...) \
  PERFETTO_THREAD_ANNOTATION_ATTRIBUTE__(assert_exclusive_lock(__VA_ARGS__))

#define PERFETTO_ASSERT_SHARED_LOCK(...) \
  PERFETTO_THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_lock(__VA_ARGS__))

// PERFETTO_NO_THREAD_SAFETY_ANALYSIS is special and differs from other
// macros defined in this file, it was defined in `compiler.h` and used before
// we introduce Thread Safety Analysis. Therefore, we define it here even if
// 'PERFETTO_ENABLE_THREAD_SAFETY_ANNOTATIONS' macro is not defined.

#if defined(__clang__)
// PERFETTO_NO_THREAD_SAFETY_ANALYSIS
//
// Turns off thread safety checking within the body of a particular function.
// This annotation is used to mark functions that are known to be correct, but
// the locking behavior is more complicated than the analyzer can handle.
#define PERFETTO_NO_THREAD_SAFETY_ANALYSIS \
  __attribute__((no_thread_safety_analysis))
#else
#define PERFETTO_NO_THREAD_SAFETY_ANALYSIS
#endif

//------------------------------------------------------------------------------
// Tool-Supplied Annotations
//------------------------------------------------------------------------------

// PERFETTO_TS_UNCHECKED should be placed around lock expressions that are not
// valid C++ syntax, but which are present for documentation purposes.  These
// annotations will be ignored by the analysis.
#define PERFETTO_TS_UNCHECKED(x) ""

// TS_FIXME is used to mark lock expressions that are not valid C++ syntax.
// It is used by automated tools to mark and disable invalid expressions.
// The annotation should either be fixed, or changed to PERFETTO_TS_UNCHECKED.
#define PERFETTO_TS_FIXME(x) ""

// Like NO_THREAD_SAFETY_ANALYSIS, this turns off checking within the body of
// a particular function.  However, this attribute is used to mark functions
// that are incorrect and need to be fixed.  It is used by automated tools to
// avoid breaking the build when the analysis is updated.
// Code owners are expected to eventually fix the routine.
#define PERFETTO_NO_THREAD_SAFETY_ANALYSIS_FIXME \
  PERFETTO_NO_THREAD_SAFETY_ANALYSIS

// Similar to NO_THREAD_SAFETY_ANALYSIS_FIXME, this macro marks a
// PERFETTO_GUARDED_BY annotation that needs to be fixed, because it is
// producing thread safety warning.  It disables the PERFETTO_GUARDED_BY.
#define PERFETTO_PERFETTO_GUARDED_BY_FIXME(x)

// Disables warnings for a single read operation.  This can be used to avoid
// warnings when it is known that the read is not actually involved in a race,
// but the compiler cannot confirm that.
#define PERFETTO_TS_UNCHECKED_READ(x) \
  perfetto::thread_safety_analysis::ts_unchecked_read(x)

namespace perfetto {
namespace thread_safety_analysis {

// Takes a reference to a guarded data member, and returns an unguarded
// reference.
template <typename T>
inline const T& ts_unchecked_read(const T& v)
    PERFETTO_NO_THREAD_SAFETY_ANALYSIS {
  return v;
}

template <typename T>
inline T& ts_unchecked_read(T& v) PERFETTO_NO_THREAD_SAFETY_ANALYSIS {
  return v;
}

}  // namespace thread_safety_analysis
}  // namespace perfetto

#endif  // INCLUDE_PERFETTO_BASE_THREAD_ANNOTATIONS_H_
// gen_amalgamated begin header: include/perfetto/tracing/event_context.h
// gen_amalgamated begin header: include/perfetto/tracing/internal/track_event_internal.h
// gen_amalgamated begin header: include/perfetto/base/flat_set.h
/*
 * Copyright (C) 2019 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.
 */


#ifndef INCLUDE_PERFETTO_BASE_FLAT_SET_H_
#define INCLUDE_PERFETTO_BASE_FLAT_SET_H_

#include <stddef.h>

#include <algorithm>
#include <utility>
#include <vector>

// A vector-based set::set-like container.
// It's more cache friendly than std::*set and performs for cases where:
// 1. A high number of dupes is expected (e.g. pid tracking in ftrace).
// 2. The working set is small (hundreds of elements).

// Performance characteristics (for uniformly random insertion order):
// - For smaller insertions (up to ~500), it outperforms both std::set<int> and
//   std::unordered_set<int> by ~3x.
// - Up until 4k insertions, it is always faster than std::set<int>.
// - unordered_set<int> is faster with more than 2k insertions.
// - unordered_set, however, it's less memory efficient and has more caveats
//   (see chromium's base/containers/README.md).
//
// See flat_set_benchmark.cc and the charts in go/perfetto-int-set-benchmark.

namespace perfetto {
namespace base {

template <typename T>
class FlatSet {
 public:
  using value_type = T;
  using const_pointer = const T*;
  using iterator = typename std::vector<T>::iterator;
  using const_iterator = typename std::vector<T>::const_iterator;

  FlatSet() = default;

  // Mainly for tests. Deliberately not marked as "explicit".
  FlatSet(std::initializer_list<T> initial) : entries_(initial) {
    std::sort(entries_.begin(), entries_.end());
    entries_.erase(std::unique(entries_.begin(), entries_.end()),
                   entries_.end());
  }

  const_iterator find(T value) const {
    auto entries_end = entries_.end();
    auto it = std::lower_bound(entries_.begin(), entries_end, value);
    return (it != entries_end && *it == value) ? it : entries_end;
  }

  size_t count(T value) const { return find(value) == entries_.end() ? 0 : 1; }

  std::pair<iterator, bool> insert(T value) {
    auto entries_end = entries_.end();
    auto it = std::lower_bound(entries_.begin(), entries_end, value);
    if (it != entries_end && *it == value)
      return std::make_pair(it, false);
    // If the value is not found |it| is either end() or the next item strictly
    // greater than |value|. In both cases we want to insert just before that.
    it = entries_.insert(it, std::move(value));
    return std::make_pair(it, true);
  }

  size_t erase(T value) {
    auto it = find(value);
    if (it == entries_.end())
      return 0;
    entries_.erase(it);
    return 1;
  }

  void clear() { entries_.clear(); }

  bool empty() const { return entries_.empty(); }
  void reserve(size_t n) { entries_.reserve(n); }
  size_t size() const { return entries_.size(); }
  const_iterator begin() const { return entries_.begin(); }
  const_iterator end() const { return entries_.end(); }

 private:
  std::vector<T> entries_;
};

}  // namespace base
}  // namespace perfetto

#endif  // INCLUDE_PERFETTO_BASE_FLAT_SET_H_
// gen_amalgamated begin header: include/perfetto/protozero/scattered_heap_buffer.h
// gen_amalgamated begin header: include/perfetto/protozero/root_message.h
// gen_amalgamated begin header: include/perfetto/protozero/message_arena.h
/*
 * Copyright (C) 2020 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.
 */


#ifndef INCLUDE_PERFETTO_PROTOZERO_MESSAGE_ARENA_H_
#define INCLUDE_PERFETTO_PROTOZERO_MESSAGE_ARENA_H_

#include <stdint.h>

#include <forward_list>
#include <type_traits>

// gen_amalgamated expanded: #include "perfetto/base/export.h"
// gen_amalgamated expanded: #include "perfetto/base/logging.h"
// gen_amalgamated expanded: #include "perfetto/protozero/message.h"

namespace protozero {

class Message;

// Object allocator for fixed-sized protozero::Message objects.
// It's a simple bump-pointer allocator which leverages the stack-alike
// usage pattern of protozero nested messages. It avoids hitting the system
// allocator in most cases, by reusing the same block, and falls back on
// allocating new blocks only when using deeply nested messages (which are
// extremely rare).
// This is used by RootMessage<T> to handle the storage for root-level messages.
class PERFETTO_EXPORT_COMPONENT MessageArena {
 public:
  MessageArena();
  ~MessageArena();

  // Strictly no copies or moves as this is used to hand out pointers.
  MessageArena(const MessageArena&) = delete;
  MessageArena& operator=(const MessageArena&) = delete;
  MessageArena(MessageArena&&) = delete;
  MessageArena& operator=(MessageArena&&) = delete;

  // Allocates a new Message object.
  Message* NewMessage();

  // Deletes the last message allocated. The |msg| argument is used only for
  // DCHECKs, it MUST be the pointer obtained by the last NewMessage() call.
  void DeleteLastMessage(Message* msg) {
    PERFETTO_DCHECK(!blocks_.empty() && blocks_.front().entries > 0);
    PERFETTO_DCHECK(&blocks_.front().storage[blocks_.front().entries - 1] ==
                    static_cast<void*>(msg));
    DeleteLastMessageInternal();
  }

  // Resets the state of the arena, clearing up all but one block. This is used
  // to avoid leaking outstanding unfinished sub-messages while recycling the
  // RootMessage object (this is extremely rare due to the RAII scoped handles
  // but could happen if some client does some overly clever std::move() trick).
  void Reset() {
    PERFETTO_DCHECK(!blocks_.empty());
    blocks_.resize(1);
    auto& block = blocks_.front();
    block.entries = 0;
    PERFETTO_ASAN_POISON(block.storage, sizeof(block.storage));
  }

 private:
  void DeleteLastMessageInternal();

  struct Block {
    static constexpr size_t kCapacity = 16;

    Block() { PERFETTO_ASAN_POISON(storage, sizeof(storage)); }

    std::aligned_storage<sizeof(Message), alignof(Message)>::type
        storage[kCapacity];
    uint32_t entries = 0;  // # Message entries used (<= kCapacity).
  };

  // blocks are used to hand out pointers and must not be moved. Hence why
  // std::list rather than std::vector.
  std::forward_list<Block> blocks_;
};

}  // namespace protozero

#endif  // INCLUDE_PERFETTO_PROTOZERO_MESSAGE_ARENA_H_
/*
 * Copyright (C) 2020 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.
 */


#ifndef INCLUDE_PERFETTO_PROTOZERO_ROOT_MESSAGE_H_
#define INCLUDE_PERFETTO_PROTOZERO_ROOT_MESSAGE_H_

// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
// gen_amalgamated expanded: #include "perfetto/protozero/message_arena.h"

namespace protozero {

// Helper class to hand out messages using the default MessageArena.
// Usage:
// RootMessage<perfetto::protos::zero::MyMessage> msg;
// msg.Reset(stream_writer);
// msg.set_foo(...);
// auto* nested = msg.set_nested();
template <typename T = Message>
class RootMessage : public T {
 public:
  RootMessage() { T::Reset(nullptr, &root_arena_); }

  // Disallow copy and move.
  RootMessage(const RootMessage&) = delete;
  RootMessage& operator=(const RootMessage&) = delete;
  RootMessage(RootMessage&&) = delete;
  RootMessage& operator=(RootMessage&&) = delete;

  void Reset(ScatteredStreamWriter* writer) {
    root_arena_.Reset();
    Message::Reset(writer, &root_arena_);
  }

 private:
  MessageArena root_arena_;
};

}  // namespace protozero

#endif  // INCLUDE_PERFETTO_PROTOZERO_ROOT_MESSAGE_H_
/*
 * 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.
 */


#ifndef INCLUDE_PERFETTO_PROTOZERO_SCATTERED_HEAP_BUFFER_H_
#define INCLUDE_PERFETTO_PROTOZERO_SCATTERED_HEAP_BUFFER_H_

#include <memory>
#include <string>
#include <vector>

// gen_amalgamated expanded: #include "perfetto/base/export.h"
// gen_amalgamated expanded: #include "perfetto/base/logging.h"
// gen_amalgamated expanded: #include "perfetto/protozero/root_message.h"
// gen_amalgamated expanded: #include "perfetto/protozero/scattered_stream_writer.h"

namespace protozero {

class Message;

class PERFETTO_EXPORT_COMPONENT ScatteredHeapBuffer
    : public protozero::ScatteredStreamWriter::Delegate {
 public:
  class PERFETTO_EXPORT_COMPONENT Slice {
   public:
    Slice();
    explicit Slice(size_t size);
    Slice(Slice&& slice) noexcept;
    ~Slice();
    Slice& operator=(Slice&&);

    inline protozero::ContiguousMemoryRange GetTotalRange() const {
      return {buffer_.get(), buffer_.get() + size_};
    }

    inline protozero::ContiguousMemoryRange GetUsedRange() const {
      return {buffer_.get(), buffer_.get() + size_ - unused_bytes_};
    }

    uint8_t* start() const { return buffer_.get(); }
    size_t size() const { return size_; }
    size_t unused_bytes() const { return unused_bytes_; }
    void set_unused_bytes(size_t unused_bytes) {
      PERFETTO_DCHECK(unused_bytes_ <= size_);
      unused_bytes_ = unused_bytes;
    }

    void Clear();

   private:
    std::unique_ptr<uint8_t[]> buffer_;
    size_t size_;
    size_t unused_bytes_;
  };

  ScatteredHeapBuffer(size_t initial_slice_size_bytes = 128,
                      size_t maximum_slice_size_bytes = 128 * 1024);
  ~ScatteredHeapBuffer() override;

  // protozero::ScatteredStreamWriter::Delegate implementation.
  protozero::ContiguousMemoryRange GetNewBuffer() override;

  // Return the slices backing this buffer, adjusted for the number of bytes the
  // writer has written.
  const std::vector<Slice>& GetSlices();

  // Stitch all the slices into a single contiguous buffer.
  std::vector<uint8_t> StitchSlices();

  // Note that the returned ranges point back to this buffer and thus cannot
  // outlive it.
  std::vector<protozero::ContiguousMemoryRange> GetRanges();

  // Note that size of the last slice isn't updated to reflect the number of
  // bytes written by the trace writer.
  const std::vector<Slice>& slices() const { return slices_; }

  void set_writer(protozero::ScatteredStreamWriter* writer) {
    writer_ = writer;
  }

  // Update unused_bytes() of the current |Slice| based on the writer's state.
  void AdjustUsedSizeOfCurrentSlice();

  // Returns the total size the slices occupy in heap memory (including unused).
  size_t GetTotalSize();

  // Reset the contents of this buffer but retain one slice allocation (if it
  // exists) to be reused for future writes.
  void Reset();

 private:
  size_t next_slice_size_;
  const size_t maximum_slice_size_;
  protozero::ScatteredStreamWriter* writer_ = nullptr;
  std::vector<Slice> slices_;

  // Used to keep an allocated slice around after this buffer is reset.
  Slice cached_slice_;
};

// Helper function to create heap-based protozero messages in one line.
// Useful when manually serializing a protozero message (primarily in
// tests/utilities). So instead of the following:
//   protozero::MyMessage msg;
//   protozero::ScatteredHeapBuffer shb;
//   protozero::ScatteredStreamWriter writer(&shb);
//   shb.set_writer(&writer);
//   msg.Reset(&writer);
//   ...
// You can write:
//   protozero::HeapBuffered<protozero::MyMessage> msg;
//   msg->set_stuff(...);
//   msg.SerializeAsString();
template <typename T = ::protozero::Message>
class HeapBuffered {
 public:
  HeapBuffered() : HeapBuffered(4096, 4096) {}
  HeapBuffered(size_t initial_slice_size_bytes, size_t maximum_slice_size_bytes)
      : shb_(initial_slice_size_bytes, maximum_slice_size_bytes),
        writer_(&shb_) {
    shb_.set_writer(&writer_);
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5 in Prozent
C=80 H=100 G=90

¤ Dauer der Verarbeitung: 0.548 Sekunden  (vorverarbeitet am  2026-04-25) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.