// 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_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_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) // 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_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 #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_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 // Include TARGET_OS_IPHONE when on __APPLE__ systems. #include #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_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 #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_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 #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_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 #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_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 #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_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 #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 // 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 #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(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(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 #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 #include // 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(__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 #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 #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 thread safety analysis for functions where the compiler can't // accurate figure out which locks are being held. #if defined(__clang__) #define PERFETTO_NO_THREAD_SAFETY_ANALYSIS \ __attribute__((no_thread_safety_analysis)) #else #define PERFETTO_NO_THREAD_SAFETY_ANALYSIS #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]] namespace perfetto { namespace base { template inline void ignore_result(const T&...) {} } // namespace base } // namespace perfetto #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 #include // 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 #elif PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) // Normal android logging. #include #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 #include #include #include // gen_amalgamated expanded: #include "perfetto/base/build_config.h" // gen_amalgamated expanded: #include "perfetto/base/logging.h" #if PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE) #include #include #include #include #endif #if PERFETTO_BUILDFLAG(PERFETTO_OS_WASM) #include #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(&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(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); } #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(GetBootTimeNs()); } inline TimeMillis GetBootTimeMs() { return std::chrono::duration_cast(GetBootTimeNs()); } inline TimeMillis GetWallTimeMs() { return std::chrono::duration_cast(GetWallTimeNs()); } inline TimeSeconds GetWallTimeS() { return std::chrono::duration_cast(GetWallTimeNs()); } inline struct timespec ToPosixTimespec(TimeMillis time) { struct timespec ts {}; const long time_s = static_cast(time.count() / 1000); ts.tv_sec = time_s; ts.tv_nsec = (static_cast(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(_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(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); } std::optional 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 #include #include 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(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 #include // 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)); } #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 #include #include // 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(ProtoWireType::kVarInt); } // Proto types: fixed64, sfixed64, fixed32, sfixed32, double, float. template 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((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(ProtoWireType::kLengthDelimited); } // Proto types: sint64, sint32. template inline typename std::make_unsigned::type ZigZagEncode(T value) { using UnsignedType = typename std::make_unsigned::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(kNegativeOne >> 63) == ~kUnsignedZero, "implementation does not support assumed rightshift"); static_assert(static_cast(kPositiveOne >> 63) == kUnsignedZero, "implementation does not support assumed rightshift"); return (static_cast(value) << 1) ^ static_cast(value >> (sizeof(T) * 8 - 1)); } // Proto types: sint64, sint32. template inline typename std::make_signed::type ZigZagDecode(T value) { using UnsignedType = typename std::make_unsigned::type; using SignedType = typename std::make_signed::type; auto u_value = static_cast(value); auto mask = static_cast(-static_cast(u_value & 1)); return static_cast((u_value >> 1) ^ mask); } template auto ExtendValueForVarIntSerialization(T value) -> typename std::make_unsigned< typename std::conditional::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::value, T, int64_t>::type; using UnsignedType = typename std::make_unsigned::type; MaybeExtendedType extended_value = static_cast(value); UnsignedType unsigned_value = static_cast(extended_value); return unsigned_value; } template inline uint8_t* WriteVarInt(T value, uint8_t* target) { auto unsigned_value = ExtendValueForVarIntSerialization(value); while (unsigned_value >= 0x80) { *target++ = static_cast(unsigned_value) | 0x80; unsigned_value >>= 7; } *target = static_cast(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(value) | msb; value >>= 7; } } template 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 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 #include #include // 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(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; std::string ToStdString() const { return std::string(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(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(int_value_); } uint32_t as_uint32() const { PERFETTO_DCHECK(!valid() || type() == proto_utils::ProtoWireType::kVarInt || type() == proto_utils::ProtoWireType::kFixed32); return static_cast(int_value_); } int32_t as_int32() const { PERFETTO_DCHECK(!valid() || type() == proto_utils::ProtoWireType::kVarInt || type() == proto_utils::ProtoWireType::kFixed32); return static_cast(int_value_); } int32_t as_sint32() const { PERFETTO_DCHECK(!valid() || type() == proto_utils::ProtoWireType::kVarInt); return proto_utils::ZigZagDecode(static_cast(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(int_value_); } int64_t as_sint64() const { PERFETTO_DCHECK(!valid() || type() == proto_utils::ProtoWireType::kVarInt); return proto_utils::ZigZagDecode(static_cast(int_value_)); } float as_float() const { PERFETTO_DCHECK(!valid() || type() == proto_utils::ProtoWireType::kFixed32); float res; uint32_t value32 = static_cast(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(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(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 ::value, T>::type> void get(T* val) const { *val = static_cast(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* dst) const; static constexpr uint32_t kMaxId = (1 << 24) - 1; // See id_ : 24 below. private: template 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 #include 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 #include #include // 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 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 namespace protozero { // This class is essentially a std::vector 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 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 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 #include #include #include #include // 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, 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 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); } 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 system_info_config_; ::protozero::CopyablePtr chrome_config_; std::string v8_config_; // [lazy=true] ::protozero::CopyablePtr 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 legacy_config_{}; ::protozero::CopyablePtr 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 #include #include #include #include // 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(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(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 #include #include #include #include // 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 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 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(value); WriteToStream(buffer, pos); } // Proto types: fixed64, sfixed64, fixed32, sfixed32, double, float. template 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(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 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::value, "T must be a subclass of Message"); static_assert(sizeof(T) == sizeof(Message), "Message subclasses cannot introduce extra state."); return static_cast(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(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(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. 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 // 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 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 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(MessageHandleBase::operator*()); } T* operator->() const { return static_cast(MessageHandleBase::operator->()); } T* get() const { return static_cast(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/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 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 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 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 #include #include #include #include #include #include // 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 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 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 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; // 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 data_source; std::unique_ptr 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 valid_instances{}; std::array instances{}; // Incremented whenever incremental state should be reset for any instance of // this data source. std::atomic incremental_state_generation{}; // Can be used with a cached |valid_instances| bitmap. DataSourceState* TryGetCached(uint32_t cached_bitmap, size_t n) { return cached_bitmap & (1 << n) ? reinterpret_cast(&instances[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 = {}; incremental_state_generation.store(0, std::memory_order_release); } }; // Per-DataSource-instance thread-local state. struct DataSourceInstanceThreadLocalState { void Reset() { *this = DataSourceInstanceThreadLocalState{}; } std::unique_ptr trace_writer; using ObjectWithDeleter = std::unique_ptr; 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 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 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 class LockedHandle { public: LockedHandle(std::unique_lock 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 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 { // 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 { // 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 { // ... // 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 { // public: // struct ThreadLocalState // : public perfetto::InterceptorBase::ThreadLocalState { // ThreadLocalState(ThreadLocalStateArgs&) override = default; // ~ThreadLocalState() override = default; // // std::map event_names; // }; // }; // // This per-thread state can then be accessed and maintained in // |OnTracePacket| like this: // // class MyInterceptor : public perfetto::Interceptor { // ... // 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 // 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 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 (*)( internal::DataSourceStaticState*, uint32_t data_source_instance_index); using TracePacketCallback = void (*)(TracePacketCallbackArgs); static void RegisterImpl( const InterceptorDescriptor& descriptor, std::function()> factory, InterceptorBase::TLSFactory tls_factory, InterceptorBase::TracePacketCallback on_trace_packet); }; // Templated interceptor instantiation. See above for usage. template 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 GetInterceptorLocked() { auto* internal_state = static_state_->TryGet(data_source_instance_index_); if (!internal_state) return LockedHandle(); std::unique_lock lock(internal_state->lock); return LockedHandle( std::move(lock), static_cast(internal_state->interceptor.get())); } private: friend class Interceptor; 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 GetInterceptorLocked() { return tls_args_.GetInterceptorLocked(); } // Return the thread-local state for this interceptor. See // InterceptorBase::ThreadLocalState. typename InterceptorType::ThreadLocalState& GetThreadLocalState() { return static_cast(*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; 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 static void Register(const InterceptorDescriptor& descriptor, const Args&... constructor_args) { auto factory = [constructor_args...]() { return std::unique_ptr( 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::value) { return std::unique_ptr(nullptr); } ThreadLocalStateArgs args(static_state, data_source_instance_index); return std::unique_ptr( 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 struct FieldWriter { static_assert(proto_schema_type != proto_utils::ProtoSchemaType::kMessage, "FieldWriter can't be used with nested messages"); }; template <> struct FieldWriter { inline static void Append(Message& message, uint32_t field_id, double value) { message.AppendFixed(field_id, value); } }; template <> struct FieldWriter { inline static void Append(Message& message, uint32_t field_id, float value) { message.AppendFixed(field_id, value); } }; template <> struct FieldWriter { inline static void Append(Message& message, uint32_t field_id, bool value) { message.AppendTinyVarInt(field_id, value); } }; template <> struct FieldWriter { inline static void Append(Message& message, uint32_t field_id, int32_t value) { message.AppendVarInt(field_id, value); } }; template <> struct FieldWriter { inline static void Append(Message& message, uint32_t field_id, int64_t value) { message.AppendVarInt(field_id, value); } }; template <> struct FieldWriter { inline static void Append(Message& message, uint32_t field_id, uint32_t value) { message.AppendVarInt(field_id, value); } }; template <> struct FieldWriter { inline static void Append(Message& message, uint32_t field_id, uint64_t value) { message.AppendVarInt(field_id, value); } }; template <> struct FieldWriter { inline static void Append(Message& message, uint32_t field_id, int32_t value) { message.AppendSignedVarInt(field_id, value); } }; template <> struct FieldWriter { inline static void Append(Message& message, uint32_t field_id, int64_t value) { message.AppendSignedVarInt(field_id, value); } }; template <> struct FieldWriter { inline static void Append(Message& message, uint32_t field_id, uint32_t value) { message.AppendFixed(field_id, value); } }; template <> struct FieldWriter { inline static void Append(Message& message, uint32_t field_id, uint64_t value) { message.AppendFixed(field_id, value); } }; template <> struct FieldWriter { inline static void Append(Message& message, uint32_t field_id, int32_t value) { message.AppendFixed(field_id, value); } }; template <> struct FieldWriter { inline static void Append(Message& message, uint32_t field_id, int64_t value) { message.AppendFixed(field_id, value); } }; template <> struct FieldWriter { template inline static void Append(Message& message, uint32_t field_id, EnumType value) { message.AppendVarInt(field_id, value); } }; template <> struct FieldWriter { 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 { 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 #include #include #include // 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 // 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 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(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 heap_buf_; alignas(uint64_t) uint8_t stack_buf_[kOnStackStorageSize]; }; class PackedVarInt : public PackedBufferBase { public: template void Append(T value) { GrowIfNeeded(); write_ptr_ = proto_utils::WriteVarInt(value, write_ptr_); } }; template 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(write_ptr_) % alignof(T) == 0); memcpy(reinterpret_cast(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 #include #include #include // 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(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(read_ptr_ - begin_); } size_t bytes_left() const { PERFETTO_DCHECK(read_ptr_ <= end_); return static_cast(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 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 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(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. bool* const 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(). 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(N); it; ++it) { ... } template RepeatedFieldIterator 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(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 PackedRepeatedFieldIterator 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( field.data(), field.size(), parse_error_location); } return PackedRepeatedFieldIterator( 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::value && std::is_trivially_destructible::value && std::is_trivial::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 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 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 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 #include // 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 PixelModemEventInsight; 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 { public: EventName_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {} explicit EventName_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast(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 { public: EventCategory_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {} explicit EventCategory_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast(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 { public: TrackEventDefaults_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {} explicit TrackEventDefaults_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast(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 extra_counter_track_uuids() const { return GetRepeated(31); } bool has_extra_double_counter_track_uuids() const { return at<45>().valid(); } ::protozero::RepeatedFieldIterator extra_double_counter_track_uuids() const { return GetRepeated(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 { public: TrackEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {} explicit TrackEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast(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 category_iids() const { return GetRepeated(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 extra_counter_track_uuids() const { return GetRepeated(31); } bool has_extra_counter_values() const { return at<12>().valid(); } ::protozero::RepeatedFieldIterator extra_counter_values() const { return GetRepeated(12); } bool has_extra_double_counter_track_uuids() const { return at<45>().valid(); } ::protozero::RepeatedFieldIterator extra_double_counter_track_uuids() const { return GetRepeated(45); } bool has_extra_double_counter_values() const { return at<46>().valid(); } ::protozero::RepeatedFieldIterator extra_double_counter_values() const { return GetRepeated(46); } bool has_flow_ids_old() const { return at<36>().valid(); } ::protozero::RepeatedFieldIterator flow_ids_old() const { return GetRepeated(36); } bool has_flow_ids() const { return at<47>().valid(); } ::protozero::RepeatedFieldIterator flow_ids() const { return GetRepeated(47); } bool has_terminating_flow_ids_old() const { return at<42>().valid(); } ::protozero::RepeatedFieldIterator terminating_flow_ids_old() const { return GetRepeated(42); } bool has_terminating_flow_ids() const { return at<48>().valid(); } ::protozero::RepeatedFieldIterator terminating_flow_ids() const { return GetRepeated(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_pixel_modem_event_insight() const { return at<51>().valid(); } ::protozero::ConstBytes pixel_modem_event_insight() const { return at<51>().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, kPixelModemEventInsightFieldNumber = 51, 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 T* add_debug_annotations() { return BeginNestedMessage(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 T* set_task_execution() { return BeginNestedMessage(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 T* set_log_message() { return BeginNestedMessage(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 T* set_cc_scheduler_state() { return BeginNestedMessage(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 T* set_chrome_user_event() { return BeginNestedMessage(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 T* set_chrome_keyed_service() { return BeginNestedMessage(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 T* set_chrome_legacy_ipc() { return BeginNestedMessage(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 T* set_chrome_histogram_sample() { return BeginNestedMessage(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 T* set_chrome_latency_info() { return BeginNestedMessage(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 T* set_chrome_frame_reporter() { return BeginNestedMessage(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 T* set_chrome_application_state_info() { return BeginNestedMessage(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 T* set_chrome_renderer_scheduler_state() { return BeginNestedMessage(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 T* set_chrome_window_handle_event_info() { return BeginNestedMessage(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 T* set_chrome_content_settings_event_info() { return BeginNestedMessage(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 T* set_chrome_active_processes() { return BeginNestedMessage(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 T* set_screenshot() { return BeginNestedMessage(50); } using FieldMetadata_PixelModemEventInsight = ::protozero::proto_utils::FieldMetadata< 51, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, PixelModemEventInsight, TrackEvent>; static constexpr FieldMetadata_PixelModemEventInsight kPixelModemEventInsight{}; template T* set_pixel_modem_event_insight() { return BeginNestedMessage(51); } 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 T* set_source_location() { return BeginNestedMessage(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 T* set_chrome_message_pump() { return BeginNestedMessage(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 T* set_chrome_mojo_event_info() { return BeginNestedMessage(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 T* set_legacy_event() { return BeginNestedMessage(6); } }; class TrackEvent_LegacyEvent_Decoder : public ::protozero::TypedProtoDecoder { 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(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 #include #include 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 user_data; // Stack of opened slices on this track. std::vector 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 event_names; std::map event_categories; std::map 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 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 #include #include #include #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) #include #else #include #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 { 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 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 #include #include #include #include // 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 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 #include #include #include #include // 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_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 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, }; 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 SerializeAsArray() const override; void Serialize(::protozero::Message*) const; const std::vector& buffers() const { return buffers_; } std::vector* mutable_buffers() { return &buffers_; } int buffers_size() const; void clear_buffers(); TraceConfig_BufferConfig* add_buffers(); const std::vector& data_sources() const { return data_sources_; } std::vector* 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& producers() const { return producers_; } std::vector* 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& activate_triggers() const { return activate_triggers_; } std::vector* mutable_activate_triggers() { return &activate_triggers_; } int activate_triggers_size() const { return static_cast(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(); } private: std::vector buffers_; std::vector data_sources_; ::protozero::CopyablePtr builtin_data_sources_; uint32_t duration_ms_{}; bool prefer_suspend_clock_for_duration_{}; bool enable_extra_guardrails_{}; TraceConfig_LockdownModeOperation lockdown_mode_{}; std::vector producers_; ::protozero::CopyablePtr statsd_metadata_; bool write_into_file_{}; std::string output_path_{}; uint32_t file_write_period_ms_{}; uint64_t max_file_size_bytes_{}; ::protozero::CopyablePtr 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 trigger_config_; std::vector activate_triggers_; ::protozero::CopyablePtr incremental_state_config_; bool allow_user_build_tracing_{}; std::string unique_session_name_{}; TraceConfig_CompressionType compression_type_{}; ::protozero::CopyablePtr incident_report_config_; TraceConfig_StatsdLogging statsd_logging_{}; int64_t trace_uuid_msb_{}; int64_t trace_uuid_lsb_{}; ::protozero::CopyablePtr trace_filter_; ::protozero::CopyablePtr android_report_config_; ::protozero::CopyablePtr cmd_trace_start_delay_; // Allows to preserve unknown protobuf fields for compatibility // with future versions of .proto files. std::string unknown_fields_; std::bitset<39> _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 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 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 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(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(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 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 SerializeAsArray() const override; void Serialize(::protozero::Message*) const; const std::vector& rules() const { return rules_; } std::vector* mutable_rules() { return &rules_; } int rules_size() const; void clear_rules(); TraceConfig_TraceFilter_StringFilterRule* add_rules(); private: std::vector 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 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 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 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 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& triggers() const { return triggers_; } std::vector* 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 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 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 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 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 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 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 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& producer_name_filter() const { return producer_name_filter_; } std::vector* mutable_producer_name_filter() { return &producer_name_filter_; } int producer_name_filter_size() const { return static_cast(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& producer_name_regex_filter() const { return producer_name_regex_filter_; } std::vector* mutable_producer_name_regex_filter() { return &producer_name_regex_filter_; } int producer_name_regex_filter_size() const { return static_cast(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 config_; std::vector producer_name_filter_; std::vector 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 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 #include 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(i) << kInitiatorShift) | (static_cast(r) << kReasonShift) | (static_cast(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 // 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 #include #else #include #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(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 // 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 #elif PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \ PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) #include #include #include #else #include #endif namespace perfetto { namespace base { #if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) 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(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(GetCurrentThreadId()); } #elif PERFETTO_BUILDFLAG(PERFETTO_OS_NACL) using PlatformThreadId = pid_t; inline PlatformThreadId GetThreadId() { return reinterpret_cast(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 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 // 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(-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 #include #include // 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; 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 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 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 ConnectProducer( const ConnectProducerArgs&) override; std::unique_ptr ConnectConsumer( const ConnectConsumerArgs&) override; private: InProcessTracingBackend(); TracingService* GetOrCreateService(base::TaskRunner*); std::unique_ptr 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 #include // 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 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 ConnectProducer( const ConnectProducerArgs&) override; private: SystemProducerTracingBackend(); }; // Consumer backend class PERFETTO_EXPORT_COMPONENT SystemConsumerTracingBackend : public TracingConsumerBackend { public: static TracingConsumerBackend* GetInstance(); std::unique_ptr 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 // 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 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 #include #include #include #include #include #include #include // 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 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 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 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 on_adopted; }; static std::unique_ptr 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 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& triggers, uint32_t ttl_ms); private: static void InitializeInternal(const TracingInitArgs&); static std::unique_ptr 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; // 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) = 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) = 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, 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) = 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; 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 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 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; 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 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; 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 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 #include #include #include #include // 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 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 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 #include // 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 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 #include // 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(platform_->GetOrCreateThreadLocalObject()); } // This method can fail and return false if trying to register more than // kMaxDataSources types. using DataSourceFactory = std::function()>; 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 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()>; 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&, 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 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 lives here (including // DataSourceStaticState). // // The C shared library API wrapper cannot use DataSource, 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. 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 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(); // 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 InstancesIterator BeginIteration( uint32_t cached_instances, DataSourceThreadLocalState* tls_state, typename TracePointTraits::TracePointData trace_point_data) { InstancesIterator it{}; it.cached_instances = cached_instances; FirstActiveInstance(&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 void NextIteration( InstancesIterator* iterator, DataSourceThreadLocalState* tls_state, typename TracePointTraits::TracePointData trace_point_data) { iterator->i++; FirstActiveInstance(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()->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* 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()->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 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 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 #include // 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 AndroidInputEvent; class AndroidLogPacket; class AndroidSystemProperty; class BatteryCounters; class ChromeBenchmarkMetadata; class ChromeEventBundle; class ChromeMetadataPacket; 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 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; } // 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 { public: TracePacket_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {} explicit TracePacket_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast(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_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_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_android_input_event() const { return at<106>().valid(); } ::protozero::ConstBytes android_input_event() const { return at<106>().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_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, 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, kEtwEventsFieldNumber = 95, kV8JsCodeFieldNumber = 99, kV8InternalCodeFieldNumber = 100, kV8WasmCodeFieldNumber = 101, kV8RegExpCodeFieldNumber = 102, kV8CodeMoveFieldNumber = 103, kAndroidInputEventFieldNumber = 106, kRemoteClockSyncFieldNumber = 107, 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 T* set_process_tree() { return BeginNestedMessage(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 T* set_process_stats() { return BeginNestedMessage(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 T* set_inode_file_map() { return BeginNestedMessage(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 T* set_chrome_events() { return BeginNestedMessage(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 T* set_clock_snapshot() { return BeginNestedMessage(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 T* set_sys_stats() { return BeginNestedMessage(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 T* set_track_event() { return BeginNestedMessage(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 T* set_trace_uuid() { return BeginNestedMessage(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 T* set_trace_config() { return BeginNestedMessage(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 T* set_ftrace_stats() { return BeginNestedMessage(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 T* set_trace_stats() { return BeginNestedMessage(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 T* set_profile_packet() { return BeginNestedMessage(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 T* set_streaming_allocation() { return BeginNestedMessage(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 T* set_streaming_free() { return BeginNestedMessage(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 T* set_battery() { return BeginNestedMessage(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 T* set_power_rails() { return BeginNestedMessage(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 T* set_android_log() { return BeginNestedMessage(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 T* set_system_info() { return BeginNestedMessage(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 T* set_trigger() { return BeginNestedMessage(46); } 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 T* set_packages_list() { return BeginNestedMessage(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 T* set_chrome_benchmark_metadata() { return BeginNestedMessage(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 T* set_perfetto_metatrace() { return BeginNestedMessage(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 T* set_chrome_metadata() { return BeginNestedMessage(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 T* set_gpu_counter_event() { return BeginNestedMessage(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 T* set_gpu_render_stage_event() { return BeginNestedMessage(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 T* set_streaming_profile_packet() { return BeginNestedMessage(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 T* set_heap_graph() { return BeginNestedMessage(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 T* set_graphics_frame_event() { return BeginNestedMessage(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 T* set_vulkan_memory_event() { return BeginNestedMessage(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 T* set_gpu_log() { return BeginNestedMessage(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 T* set_vulkan_api_event() { return BeginNestedMessage(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 T* set_perf_sample() { return BeginNestedMessage(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 T* set_cpu_info() { return BeginNestedMessage(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 T* set_smaps_packet() { return BeginNestedMessage(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 T* set_service_event() { return BeginNestedMessage(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 T* set_initial_display_state() { return BeginNestedMessage(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 T* set_gpu_mem_total_event() { return BeginNestedMessage(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 T* set_memory_tracker_snapshot() { return BeginNestedMessage(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 T* set_frame_timeline_event() { return BeginNestedMessage(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 T* set_android_energy_estimation_breakdown() { return BeginNestedMessage(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 T* set_ui_state() { return BeginNestedMessage(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 T* set_android_camera_frame_event() { return BeginNestedMessage(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 T* set_android_camera_session_stats() { return BeginNestedMessage(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 T* set_translation_table() { return BeginNestedMessage(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 T* set_android_game_intervention_list() { return BeginNestedMessage(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 T* set_statsd_atom() { return BeginNestedMessage(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 T* set_android_system_property() { return BeginNestedMessage(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 T* set_entity_state_residency() { return BeginNestedMessage(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 T* set_profiled_frame_symbols() { return BeginNestedMessage(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 T* set_module_symbols() { return BeginNestedMessage(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 T* set_deobfuscation_mapping() { return BeginNestedMessage(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 T* set_track_descriptor() { return BeginNestedMessage(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 T* set_process_descriptor() { return BeginNestedMessage(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 T* set_thread_descriptor() { return BeginNestedMessage(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 T* set_ftrace_events() { return BeginNestedMessage(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 T* set_extension_descriptor() { return BeginNestedMessage(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 T* set_network_packet() { return BeginNestedMessage(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 T* set_network_packet_bundle() { return BeginNestedMessage(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 T* set_track_event_range_of_interest() { return BeginNestedMessage(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 T* set_surfaceflinger_layers_snapshot() { return BeginNestedMessage(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 T* set_surfaceflinger_transactions() { return BeginNestedMessage(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 T* set_shell_transition() { return BeginNestedMessage(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 T* set_shell_handler_mappings() { return BeginNestedMessage(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 T* set_protolog_message() { return BeginNestedMessage(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 T* set_protolog_viewer_config() { return BeginNestedMessage(105); } 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 T* set_etw_events() { return BeginNestedMessage(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 T* set_v8_js_code() { return BeginNestedMessage(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 T* set_v8_internal_code() { return BeginNestedMessage(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 T* set_v8_wasm_code() { return BeginNestedMessage(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 T* set_v8_reg_exp_code() { return BeginNestedMessage(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 T* set_v8_code_move() { return BeginNestedMessage(103); } using FieldMetadata_AndroidInputEvent = ::protozero::proto_utils::FieldMetadata< 106, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, AndroidInputEvent, TracePacket>; static constexpr FieldMetadata_AndroidInputEvent kAndroidInputEvent{}; template T* set_android_input_event() { return BeginNestedMessage(106); } 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 T* set_remote_clock_sync() { return BeginNestedMessage(107); } 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 T* set_for_testing() { return BeginNestedMessage(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 T* set_interned_data() { return BeginNestedMessage(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 T* set_trace_packet_defaults() { return BeginNestedMessage(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 #include #include #include #include #include #include #include // 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 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 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 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 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 {...}. // // |DataSourceTraits| allows customizing the behavior of the data source. See // |DefaultDataSourceTraits|. template class DataSource : public DataSourceBase { struct DefaultTracePointTraits; using Helper = DataSourceHelper; 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 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 GetDataSourceLocked() const { auto* internal_state = Helper::type().static_state()->TryGet(instance_index_); if (!internal_state) return LockedHandle(); std::unique_lock lock(internal_state->lock); return LockedHandle( std::move(lock), static_cast(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( tls_inst_->data_source_custom_tls.get()); } typename DataSourceTraits::IncrementalStateType* GetIncrementalState() { return static_cast( Helper::type().GetIncrementalState(tls_inst_, instance_index_)); } private: friend class DataSource; template 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 static void Trace(Lambda tracing_fn) { CallIfEnabled([&tracing_fn](uint32_t instances) { TraceWithInstances(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 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 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( &tls_state_, &cached_instances, trace_point_data)) { return; } for (internal::DataSourceType::InstancesIterator it = Helper::type().template BeginIteration( cached_instances, tls_state_, trace_point_data); it.instance; Helper::type().template NextIteration( &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 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( new DerivedDataSource(constructor_args...)); }; constexpr bool no_flush = std::is_same_v; internal::DataSourceParams params{ DerivedDataSource::kSupportsMultipleInstances, DerivedDataSource::kRequiresCallbacksUnderLock}; return Helper::type().Register( descriptor, factory, params, DerivedDataSource::kBufferExhaustedPolicy, no_flush, GetCreateTlsFn( static_cast(nullptr)), GetCreateIncrementalStateFn( static_cast( 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* GetActiveInstances(TracePointData) { return Helper::type().valid_instances(); } }; template static internal::DataSourceInstanceThreadLocalState::ObjectWithDeleter CreateIncrementalState(internal::DataSourceInstanceThreadLocalState*, uint32_t, void*) { return internal::DataSourceInstanceThreadLocalState::ObjectWithDeleter( reinterpret_cast(new T()), [](void* p) { delete reinterpret_cast(p); }); } // The second parameter here is used to specialize the case where there is no // incremental state type. template static internal::DataSourceType::CreateIncrementalStateFn GetCreateIncrementalStateFn(const T*) { return &CreateIncrementalState; } static internal::DataSourceType::CreateIncrementalStateFn GetCreateIncrementalStateFn(const void*) { return nullptr; } template static internal::DataSourceInstanceThreadLocalState::ObjectWithDeleter CreateDataSourceCustomTls( internal::DataSourceInstanceThreadLocalState* tls_inst, uint32_t instance_index, void*) { return internal::DataSourceInstanceThreadLocalState::ObjectWithDeleter( reinterpret_cast(new T(TraceContext(tls_inst, instance_index))), [](void* p) { delete reinterpret_cast(p); }); } // The second parameter here is used to specialize the case where there is no // tls state type. template static internal::DataSourceType::CreateCustomTlsFn GetCreateTlsFn(const T*) { return &CreateDataSourceCustomTls; } 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 thread_local internal::DataSourceThreadLocalState* DataSource::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 #include 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 struct priority_tag : priority_tag {}; 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 using enable_if_t = typename std::enable_if::type; // decay_t is an implementation of std::decay_t from C++14. // // Specification: // https://en.cppreference.com/w/cpp/types/decay template using decay_t = typename std::decay::type; // remove_cvref is an implementation of std::remove_cvref from // C++20. // // Specification: // https://en.cppreference.com/w/cpp/types/remove_cvref template struct remove_cvref { using type = typename std::remove_cv::type>::type>::type; }; template using remove_cvref_t = typename remove_cvref::type; // Check if a given type is a specialization of a given template: // is_specialization::value. template class Template> struct is_specialization : std::false_type {}; template