blob: 9a0042aee5b428a1d13edf2e16244cf1b8fa736b [file] [log] [blame] [edit]
/*
* Copyright 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define FRAMEWORK_CATEGORIES(C) \
C(always, "always", "Always category") \
C(graphics, "graphics", "Graphics category") \
C(input, "input", "Input category") \
C(view, "view", "View category") \
C(webview, "webview", "WebView category") \
C(windowmanager, "wm", "WindowManager category") \
C(activitymanager, "am", "ActivityManager category") \
C(syncmanager, "syncmanager", "SyncManager category") \
C(audio, "audio", "Audio category") \
C(video, "video", "Video category") \
C(camera, "camera", "Camera category") \
C(hal, "hal", "HAL category") \
C(app, "app", "App category") \
C(resources, "res", "Resources category") \
C(dalvik, "dalvik", "Dalvik category") \
C(rs, "rs", "RS category") \
C(bionic, "bionic", "Bionic category") \
C(power, "power", "Power category") \
C(packagemanager, "packagemanager", "PackageManager category") \
C(systemserver, "ss", "System Server category") \
C(database, "database", "Database category") \
C(network, "network", "Network category") \
C(adb, "adb", "ADB category") \
C(vibrator, "vibrator", "Vibrator category") \
C(aidl, "aidl", "AIDL category") \
C(nnapi, "nnapi", "NNAPI category") \
C(rro, "rro", "RRO category") \
C(thermal, "thermal", "Thermal category")
#include <atomic>
#include <mutex>
#include <android_os.h>
#include <android-base/properties.h>
#include <cutils/trace.h>
#include <inttypes.h>
#include "perfetto/public/compiler.h"
#include "perfetto/public/producer.h"
#include "perfetto/public/te_category_macros.h"
#include "perfetto/public/te_macros.h"
#include "perfetto/public/track_event.h"
#include "trace_categories.h"
#include "tracing_perfetto_internal.h"
#ifdef __BIONIC__
#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
#include <sys/_system_properties.h>
#endif
namespace tracing_perfetto {
namespace internal {
namespace {
PERFETTO_TE_CATEGORIES_DECLARE(FRAMEWORK_CATEGORIES);
PERFETTO_TE_CATEGORIES_DEFINE(FRAMEWORK_CATEGORIES);
static constexpr char kPreferFlagProperty[] = "debug.atrace.prefer_sdk";
static std::atomic<const prop_info*> prefer_property_info = nullptr;
static std::atomic_uint32_t last_prefer_seq_num = 0;
static std::atomic_uint64_t prefer_flags = 0;
static const prop_info* system_property_find(const char* name [[maybe_unused]]) {
#ifdef __BIONIC__
return __system_property_find(name);
#endif
return nullptr;
}
static uint32_t system_property_serial(const prop_info* pi [[maybe_unused]]) {
#ifdef __BIONIC__
return __system_property_serial(pi);
#endif
return last_prefer_seq_num;
}
struct PerfettoTeCategory* toCategory(uint64_t inCategory) {
switch (inCategory) {
case TRACE_CATEGORY_ALWAYS:
return &always;
case TRACE_CATEGORY_GRAPHICS:
return &graphics;
case TRACE_CATEGORY_INPUT:
return &input;
case TRACE_CATEGORY_VIEW:
return &view;
case TRACE_CATEGORY_WEBVIEW:
return &webview;
case TRACE_CATEGORY_WINDOW_MANAGER:
return &windowmanager;
case TRACE_CATEGORY_ACTIVITY_MANAGER:
return &activitymanager;
case TRACE_CATEGORY_SYNC_MANAGER:
return &syncmanager;
case TRACE_CATEGORY_AUDIO:
return &audio;
case TRACE_CATEGORY_VIDEO:
return &video;
case TRACE_CATEGORY_CAMERA:
return &camera;
case TRACE_CATEGORY_HAL:
return &hal;
case TRACE_CATEGORY_APP:
return &app;
case TRACE_CATEGORY_RESOURCES:
return &resources;
case TRACE_CATEGORY_DALVIK:
return &dalvik;
case TRACE_CATEGORY_RS:
return &rs;
case TRACE_CATEGORY_BIONIC:
return &bionic;
case TRACE_CATEGORY_POWER:
return &power;
case TRACE_CATEGORY_PACKAGE_MANAGER:
return &packagemanager;
case TRACE_CATEGORY_SYSTEM_SERVER:
return &systemserver;
case TRACE_CATEGORY_DATABASE:
return &database;
case TRACE_CATEGORY_NETWORK:
return &network;
case TRACE_CATEGORY_ADB:
return &adb;
case TRACE_CATEGORY_VIBRATOR:
return &vibrator;
case TRACE_CATEGORY_AIDL:
return &aidl;
case TRACE_CATEGORY_NNAPI:
return &nnapi;
case TRACE_CATEGORY_RRO:
return &rro;
case TRACE_CATEGORY_THERMAL:
return &thermal;
default:
return nullptr;
}
}
} // namespace
bool isPerfettoCategoryEnabled(PerfettoTeCategory* category) {
return category != nullptr;
}
/**
* Updates the cached |prefer_flags|.
*
* We cache the prefer_flags because reading it on every trace event is expensive.
* The cache is invalidated when a sys_prop sequence number changes.
*/
void updatePreferFlags() {
if (!prefer_property_info.load(std::memory_order_acquire)) {
auto* new_prefer_property_info = system_property_find(kPreferFlagProperty);
prefer_flags.store(android::base::GetIntProperty(kPreferFlagProperty, 0),
std::memory_order_relaxed);
if (!new_prefer_property_info) {
// This should never happen. If it does, we fail gracefully and end up reading the property
// traced event.
return;
}
last_prefer_seq_num = system_property_serial(new_prefer_property_info);
prefer_property_info.store(new_prefer_property_info, std::memory_order_release);
}
uint32_t prefer_seq_num = system_property_serial(prefer_property_info);
if (prefer_seq_num != last_prefer_seq_num.load(std::memory_order_acquire)) {
prefer_flags.store(android::base::GetIntProperty(kPreferFlagProperty, 0),
std::memory_order_relaxed);
last_prefer_seq_num.store(prefer_seq_num, std::memory_order_release);
}
}
bool shouldPreferAtrace(PerfettoTeCategory *perfettoCategory, uint64_t atraceCategory) {
// There are 3 cases:
// 1. Atrace is not enabled.
if (!atrace_is_tag_enabled(atraceCategory)) {
return false;
}
// 2. Atrace is enabled but perfetto is not enabled.
if (!isPerfettoCategoryEnabled(perfettoCategory)) {
return true;
}
// Update prefer_flags before checking it below
updatePreferFlags();
// 3. Atrace and perfetto are enabled.
// Even though this category is enabled for track events, the config mandates that we downgrade
// it to atrace if the same atrace category is currently enabled. This prevents missing the
// event from a concurrent session that needs the same category in atrace.
return (atraceCategory & prefer_flags.load(std::memory_order_relaxed)) == 0;
}
struct PerfettoTeCategory* toPerfettoCategory(uint64_t category) {
struct PerfettoTeCategory* perfettoCategory = toCategory(category);
if (perfettoCategory == nullptr) {
return nullptr;
}
bool enabled = PERFETTO_UNLIKELY(PERFETTO_ATOMIC_LOAD_EXPLICIT(
(*perfettoCategory).enabled, PERFETTO_MEMORY_ORDER_RELAXED));
return enabled ? perfettoCategory : nullptr;
}
void registerWithPerfetto(bool test) {
if (!android::os::perfetto_sdk_tracing()) {
return;
}
static std::once_flag registration;
std::call_once(registration, [test]() {
struct PerfettoProducerInitArgs args = PERFETTO_PRODUCER_INIT_ARGS_INIT();
args.backends = test ? PERFETTO_BACKEND_IN_PROCESS : PERFETTO_BACKEND_SYSTEM;
PerfettoProducerInit(args);
PerfettoTeInit();
PERFETTO_TE_REGISTER_CATEGORIES(FRAMEWORK_CATEGORIES);
});
}
void perfettoTraceBegin(const struct PerfettoTeCategory& category, const char* name) {
PERFETTO_TE(category, PERFETTO_TE_SLICE_BEGIN(name));
}
void perfettoTraceEnd(const struct PerfettoTeCategory& category) {
PERFETTO_TE(category, PERFETTO_TE_SLICE_END());
}
void perfettoTraceAsyncBeginForTrack(const struct PerfettoTeCategory& category, const char* name,
const char* trackName, uint64_t cookie) {
PERFETTO_TE(
category, PERFETTO_TE_SLICE_BEGIN(name),
PERFETTO_TE_NAMED_TRACK(trackName, cookie, PerfettoTeProcessTrackUuid()));
}
void perfettoTraceAsyncEndForTrack(const struct PerfettoTeCategory& category,
const char* trackName, uint64_t cookie) {
PERFETTO_TE(
category, PERFETTO_TE_SLICE_END(),
PERFETTO_TE_NAMED_TRACK(trackName, cookie, PerfettoTeProcessTrackUuid()));
}
void perfettoTraceAsyncBegin(const struct PerfettoTeCategory& category, const char* name,
uint64_t cookie) {
perfettoTraceAsyncBeginForTrack(category, name, name, cookie);
}
void perfettoTraceAsyncEnd(const struct PerfettoTeCategory& category, const char* name,
uint64_t cookie) {
perfettoTraceAsyncEndForTrack(category, name, cookie);
}
void perfettoTraceInstant(const struct PerfettoTeCategory& category, const char* name) {
PERFETTO_TE(category, PERFETTO_TE_INSTANT(name));
}
void perfettoTraceInstantForTrack(const struct PerfettoTeCategory& category,
const char* trackName, const char* name) {
PERFETTO_TE(
category, PERFETTO_TE_INSTANT(name),
PERFETTO_TE_NAMED_TRACK(trackName, 1, PerfettoTeProcessTrackUuid()));
}
void perfettoTraceCounter(const struct PerfettoTeCategory& category,
[[maybe_unused]] const char* name, int64_t value) {
PERFETTO_TE(category, PERFETTO_TE_COUNTER(),
PERFETTO_TE_INT_COUNTER(value));
}
} // namespace internal
} // namespace tracing_perfetto