xref: /aosp_15_r20/system/core/libcutils/trace-dev.inc (revision 00c7fec1bb09f3284aad6a6f96d2f63dfc3650ad)
1*00c7fec1SAndroid Build Coastguard Worker/*
2*00c7fec1SAndroid Build Coastguard Worker * Copyright (C) 2017 The Android Open Source Project
3*00c7fec1SAndroid Build Coastguard Worker *
4*00c7fec1SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*00c7fec1SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*00c7fec1SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*00c7fec1SAndroid Build Coastguard Worker *
8*00c7fec1SAndroid Build Coastguard Worker *      http://www.apache.org/licenses/LICENSE-2.0
9*00c7fec1SAndroid Build Coastguard Worker *
10*00c7fec1SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*00c7fec1SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*00c7fec1SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*00c7fec1SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*00c7fec1SAndroid Build Coastguard Worker * limitations under the License.
15*00c7fec1SAndroid Build Coastguard Worker */
16*00c7fec1SAndroid Build Coastguard Worker
17*00c7fec1SAndroid Build Coastguard Worker#ifndef __TRACE_DEV_INC
18*00c7fec1SAndroid Build Coastguard Worker#define __TRACE_DEV_INC
19*00c7fec1SAndroid Build Coastguard Worker
20*00c7fec1SAndroid Build Coastguard Worker#define LOG_TAG "cutils-trace"
21*00c7fec1SAndroid Build Coastguard Worker
22*00c7fec1SAndroid Build Coastguard Worker#include <errno.h>
23*00c7fec1SAndroid Build Coastguard Worker#include <fcntl.h>
24*00c7fec1SAndroid Build Coastguard Worker#include <fnmatch.h>
25*00c7fec1SAndroid Build Coastguard Worker#include <limits.h>
26*00c7fec1SAndroid Build Coastguard Worker#include <pthread.h>
27*00c7fec1SAndroid Build Coastguard Worker#include <stdatomic.h>
28*00c7fec1SAndroid Build Coastguard Worker#include <stdlib.h>
29*00c7fec1SAndroid Build Coastguard Worker#include <string.h>
30*00c7fec1SAndroid Build Coastguard Worker#include <sys/types.h>
31*00c7fec1SAndroid Build Coastguard Worker
32*00c7fec1SAndroid Build Coastguard Worker#include <cutils/compiler.h>
33*00c7fec1SAndroid Build Coastguard Worker#include <cutils/properties.h>
34*00c7fec1SAndroid Build Coastguard Worker#include <cutils/trace.h>
35*00c7fec1SAndroid Build Coastguard Worker#include <log/log.h>
36*00c7fec1SAndroid Build Coastguard Worker#include <log/log_properties.h>
37*00c7fec1SAndroid Build Coastguard Worker
38*00c7fec1SAndroid Build Coastguard Worker#if defined(__BIONIC__)
39*00c7fec1SAndroid Build Coastguard Worker#include <sys/system_properties.h>
40*00c7fec1SAndroid Build Coastguard Worker#endif
41*00c7fec1SAndroid Build Coastguard Worker
42*00c7fec1SAndroid Build Coastguard Worker/**
43*00c7fec1SAndroid Build Coastguard Worker * Maximum size of a message that can be logged to the trace buffer.
44*00c7fec1SAndroid Build Coastguard Worker * Note this message includes a tag, the pid, and the string given as the name.
45*00c7fec1SAndroid Build Coastguard Worker * Names should be kept short to get the most use of the trace buffer.
46*00c7fec1SAndroid Build Coastguard Worker */
47*00c7fec1SAndroid Build Coastguard Worker#define ATRACE_MESSAGE_LENGTH 1024
48*00c7fec1SAndroid Build Coastguard Worker
49*00c7fec1SAndroid Build Coastguard Workerconstexpr uint32_t kSeqNoNotInit = static_cast<uint32_t>(-1);
50*00c7fec1SAndroid Build Coastguard Worker
51*00c7fec1SAndroid Build Coastguard Workeratomic_bool              atrace_is_ready      = false;
52*00c7fec1SAndroid Build Coastguard Workerint                      atrace_marker_fd     = -1;
53*00c7fec1SAndroid Build Coastguard Workeruint64_t                 atrace_enabled_tags  = ATRACE_TAG_NOT_READY;
54*00c7fec1SAndroid Build Coastguard Workerstatic atomic_bool       atrace_is_enabled    = true;
55*00c7fec1SAndroid Build Coastguard Workerstatic pthread_mutex_t   atrace_tags_mutex    = PTHREAD_MUTEX_INITIALIZER;
56*00c7fec1SAndroid Build Coastguard Worker
57*00c7fec1SAndroid Build Coastguard Worker/**
58*00c7fec1SAndroid Build Coastguard Worker * Sequence number of debug.atrace.tags.enableflags the last time the enabled
59*00c7fec1SAndroid Build Coastguard Worker * tags were reloaded.
60*00c7fec1SAndroid Build Coastguard Worker **/
61*00c7fec1SAndroid Build Coastguard Workerstatic _Atomic(uint32_t) last_sequence_number = kSeqNoNotInit;
62*00c7fec1SAndroid Build Coastguard Worker
63*00c7fec1SAndroid Build Coastguard Worker#if defined(__BIONIC__)
64*00c7fec1SAndroid Build Coastguard Worker// All zero prop_info that has a sequence number of 0. This is easier than
65*00c7fec1SAndroid Build Coastguard Worker// depending on implementation details of the property implementation.
66*00c7fec1SAndroid Build Coastguard Worker//
67*00c7fec1SAndroid Build Coastguard Worker// prop_info is static_assert-ed to be 96 bytes, which cannot change due to
68*00c7fec1SAndroid Build Coastguard Worker// ABI compatibility.
69*00c7fec1SAndroid Build Coastguard Workeralignas(uint64_t) static char empty_pi[96];
70*00c7fec1SAndroid Build Coastguard Workerstatic const prop_info* atrace_property_info = reinterpret_cast<const prop_info*>(empty_pi);
71*00c7fec1SAndroid Build Coastguard Worker#endif
72*00c7fec1SAndroid Build Coastguard Worker
73*00c7fec1SAndroid Build Coastguard Worker/**
74*00c7fec1SAndroid Build Coastguard Worker * This is called when the sequence number of debug.atrace.tags.enableflags
75*00c7fec1SAndroid Build Coastguard Worker * changes and we need to reload the enabled tags.
76*00c7fec1SAndroid Build Coastguard Worker **/
77*00c7fec1SAndroid Build Coastguard Workerstatic void atrace_seq_number_changed(uint32_t prev_seq_no, uint32_t seq_no);
78*00c7fec1SAndroid Build Coastguard Worker
79*00c7fec1SAndroid Build Coastguard Workervoid atrace_init() {
80*00c7fec1SAndroid Build Coastguard Worker#if defined(__BIONIC__)
81*00c7fec1SAndroid Build Coastguard Worker    uint32_t seq_no = __system_property_serial(atrace_property_info);  // Acquire semantics.
82*00c7fec1SAndroid Build Coastguard Worker#else
83*00c7fec1SAndroid Build Coastguard Worker    uint32_t seq_no = 0;
84*00c7fec1SAndroid Build Coastguard Worker#endif
85*00c7fec1SAndroid Build Coastguard Worker    uint32_t prev_seq_no = atomic_load_explicit(&last_sequence_number, memory_order_relaxed);
86*00c7fec1SAndroid Build Coastguard Worker    if (CC_UNLIKELY(seq_no != prev_seq_no)) {
87*00c7fec1SAndroid Build Coastguard Worker        atrace_seq_number_changed(prev_seq_no, seq_no);
88*00c7fec1SAndroid Build Coastguard Worker    }
89*00c7fec1SAndroid Build Coastguard Worker}
90*00c7fec1SAndroid Build Coastguard Worker
91*00c7fec1SAndroid Build Coastguard Workeruint64_t atrace_get_enabled_tags()
92*00c7fec1SAndroid Build Coastguard Worker{
93*00c7fec1SAndroid Build Coastguard Worker    atrace_init();
94*00c7fec1SAndroid Build Coastguard Worker    return atrace_enabled_tags;
95*00c7fec1SAndroid Build Coastguard Worker}
96*00c7fec1SAndroid Build Coastguard Worker
97*00c7fec1SAndroid Build Coastguard Worker// Check whether the given command line matches one of the comma-separated
98*00c7fec1SAndroid Build Coastguard Worker// values listed in the app_cmdlines property.
99*00c7fec1SAndroid Build Coastguard Workerstatic bool atrace_is_cmdline_match(const char* cmdline)
100*00c7fec1SAndroid Build Coastguard Worker{
101*00c7fec1SAndroid Build Coastguard Worker    int count = property_get_int32("debug.atrace.app_number", 0);
102*00c7fec1SAndroid Build Coastguard Worker
103*00c7fec1SAndroid Build Coastguard Worker    char buf[PROPERTY_KEY_MAX];
104*00c7fec1SAndroid Build Coastguard Worker    char value[PROPERTY_VALUE_MAX];
105*00c7fec1SAndroid Build Coastguard Worker
106*00c7fec1SAndroid Build Coastguard Worker    for (int i = 0; i < count; i++) {
107*00c7fec1SAndroid Build Coastguard Worker        snprintf(buf, sizeof(buf), "debug.atrace.app_%d", i);
108*00c7fec1SAndroid Build Coastguard Worker        property_get(buf, value, "");
109*00c7fec1SAndroid Build Coastguard Worker        if (fnmatch(value, cmdline, FNM_NOESCAPE) == 0) {
110*00c7fec1SAndroid Build Coastguard Worker            return true;
111*00c7fec1SAndroid Build Coastguard Worker        }
112*00c7fec1SAndroid Build Coastguard Worker    }
113*00c7fec1SAndroid Build Coastguard Worker
114*00c7fec1SAndroid Build Coastguard Worker    return false;
115*00c7fec1SAndroid Build Coastguard Worker}
116*00c7fec1SAndroid Build Coastguard Worker
117*00c7fec1SAndroid Build Coastguard Worker// Determine whether application-level tracing is enabled for this process.
118*00c7fec1SAndroid Build Coastguard Workerstatic bool atrace_is_app_tracing_enabled()
119*00c7fec1SAndroid Build Coastguard Worker{
120*00c7fec1SAndroid Build Coastguard Worker    bool result = false;
121*00c7fec1SAndroid Build Coastguard Worker
122*00c7fec1SAndroid Build Coastguard Worker    // Check whether tracing is enabled for this process.
123*00c7fec1SAndroid Build Coastguard Worker    FILE * file = fopen("/proc/self/cmdline", "re");
124*00c7fec1SAndroid Build Coastguard Worker    if (file) {
125*00c7fec1SAndroid Build Coastguard Worker        char cmdline[4096];
126*00c7fec1SAndroid Build Coastguard Worker        if (fgets(cmdline, sizeof(cmdline), file)) {
127*00c7fec1SAndroid Build Coastguard Worker            result = atrace_is_cmdline_match(cmdline);
128*00c7fec1SAndroid Build Coastguard Worker        } else {
129*00c7fec1SAndroid Build Coastguard Worker            ALOGE("Error reading cmdline: %s (%d)", strerror(errno), errno);
130*00c7fec1SAndroid Build Coastguard Worker        }
131*00c7fec1SAndroid Build Coastguard Worker        fclose(file);
132*00c7fec1SAndroid Build Coastguard Worker    } else {
133*00c7fec1SAndroid Build Coastguard Worker        ALOGE("Error opening /proc/self/cmdline: %s (%d)", strerror(errno),
134*00c7fec1SAndroid Build Coastguard Worker                errno);
135*00c7fec1SAndroid Build Coastguard Worker    }
136*00c7fec1SAndroid Build Coastguard Worker
137*00c7fec1SAndroid Build Coastguard Worker    return result;
138*00c7fec1SAndroid Build Coastguard Worker}
139*00c7fec1SAndroid Build Coastguard Worker
140*00c7fec1SAndroid Build Coastguard Worker// Read the sysprop and return the value tags should be set to
141*00c7fec1SAndroid Build Coastguard Workerstatic uint64_t atrace_get_property()
142*00c7fec1SAndroid Build Coastguard Worker{
143*00c7fec1SAndroid Build Coastguard Worker    char value[PROPERTY_VALUE_MAX];
144*00c7fec1SAndroid Build Coastguard Worker    char *endptr;
145*00c7fec1SAndroid Build Coastguard Worker    uint64_t tags;
146*00c7fec1SAndroid Build Coastguard Worker
147*00c7fec1SAndroid Build Coastguard Worker    property_get("debug.atrace.tags.enableflags", value, "0");
148*00c7fec1SAndroid Build Coastguard Worker    errno = 0;
149*00c7fec1SAndroid Build Coastguard Worker    tags = strtoull(value, &endptr, 0);
150*00c7fec1SAndroid Build Coastguard Worker    if (value[0] == '\0' || *endptr != '\0') {
151*00c7fec1SAndroid Build Coastguard Worker        ALOGE("Error parsing trace property: Not a number: %s", value);
152*00c7fec1SAndroid Build Coastguard Worker        return 0;
153*00c7fec1SAndroid Build Coastguard Worker    } else if (errno == ERANGE || tags == ULLONG_MAX) {
154*00c7fec1SAndroid Build Coastguard Worker        ALOGE("Error parsing trace property: Number too large: %s", value);
155*00c7fec1SAndroid Build Coastguard Worker        return 0;
156*00c7fec1SAndroid Build Coastguard Worker    }
157*00c7fec1SAndroid Build Coastguard Worker
158*00c7fec1SAndroid Build Coastguard Worker    // Only set the "app" tag if this process was selected for app-level debug
159*00c7fec1SAndroid Build Coastguard Worker    // tracing.
160*00c7fec1SAndroid Build Coastguard Worker    if (atrace_is_app_tracing_enabled()) {
161*00c7fec1SAndroid Build Coastguard Worker        tags |= ATRACE_TAG_APP;
162*00c7fec1SAndroid Build Coastguard Worker    } else {
163*00c7fec1SAndroid Build Coastguard Worker        tags &= ~ATRACE_TAG_APP;
164*00c7fec1SAndroid Build Coastguard Worker    }
165*00c7fec1SAndroid Build Coastguard Worker
166*00c7fec1SAndroid Build Coastguard Worker    return (tags | ATRACE_TAG_ALWAYS) & ATRACE_TAG_VALID_MASK;
167*00c7fec1SAndroid Build Coastguard Worker}
168*00c7fec1SAndroid Build Coastguard Worker
169*00c7fec1SAndroid Build Coastguard Worker// Update tags if tracing is ready. Useful as a sysprop change callback.
170*00c7fec1SAndroid Build Coastguard Workervoid atrace_update_tags()
171*00c7fec1SAndroid Build Coastguard Worker{
172*00c7fec1SAndroid Build Coastguard Worker    uint64_t tags;
173*00c7fec1SAndroid Build Coastguard Worker    if (atomic_load_explicit(&atrace_is_enabled, memory_order_acquire)) {
174*00c7fec1SAndroid Build Coastguard Worker        tags = atrace_get_property();
175*00c7fec1SAndroid Build Coastguard Worker        pthread_mutex_lock(&atrace_tags_mutex);
176*00c7fec1SAndroid Build Coastguard Worker        atrace_enabled_tags = tags;
177*00c7fec1SAndroid Build Coastguard Worker        pthread_mutex_unlock(&atrace_tags_mutex);
178*00c7fec1SAndroid Build Coastguard Worker    } else {
179*00c7fec1SAndroid Build Coastguard Worker        // Tracing is disabled for this process, so we simply don't
180*00c7fec1SAndroid Build Coastguard Worker        // initialize the tags.
181*00c7fec1SAndroid Build Coastguard Worker        pthread_mutex_lock(&atrace_tags_mutex);
182*00c7fec1SAndroid Build Coastguard Worker        atrace_enabled_tags = ATRACE_TAG_NOT_READY;
183*00c7fec1SAndroid Build Coastguard Worker        pthread_mutex_unlock(&atrace_tags_mutex);
184*00c7fec1SAndroid Build Coastguard Worker    }
185*00c7fec1SAndroid Build Coastguard Worker}
186*00c7fec1SAndroid Build Coastguard Worker
187*00c7fec1SAndroid Build Coastguard Worker#define WRITE_MSG(format_begin, format_end, track_name, name, value) { \
188*00c7fec1SAndroid Build Coastguard Worker    char buf[ATRACE_MESSAGE_LENGTH] __attribute__((uninitialized));     \
189*00c7fec1SAndroid Build Coastguard Worker    const char* track_name_sep = track_name[0] != '\0' ? "|" : ""; \
190*00c7fec1SAndroid Build Coastguard Worker    int pid = getpid(); \
191*00c7fec1SAndroid Build Coastguard Worker    int len = snprintf(buf, sizeof(buf), format_begin "%s%s%s" format_end, pid, \
192*00c7fec1SAndroid Build Coastguard Worker        track_name, track_name_sep, name, value); \
193*00c7fec1SAndroid Build Coastguard Worker    if (len >= (int) sizeof(buf)) { \
194*00c7fec1SAndroid Build Coastguard Worker        int name_len = strlen(name) - (len - sizeof(buf)) - 1; \
195*00c7fec1SAndroid Build Coastguard Worker        /* Truncate the name to make the message fit. */ \
196*00c7fec1SAndroid Build Coastguard Worker        if (name_len > 0) { \
197*00c7fec1SAndroid Build Coastguard Worker            len = snprintf(buf, sizeof(buf), format_begin "%s%s%.*s" format_end, pid, \
198*00c7fec1SAndroid Build Coastguard Worker                track_name, track_name_sep, name_len, name, value); \
199*00c7fec1SAndroid Build Coastguard Worker        } else { \
200*00c7fec1SAndroid Build Coastguard Worker            int track_name_len = 0; \
201*00c7fec1SAndroid Build Coastguard Worker            if (track_name[0] != '\0') { \
202*00c7fec1SAndroid Build Coastguard Worker                track_name_len = strlen(track_name) - (len - strlen(name) - sizeof(buf)) - 2; \
203*00c7fec1SAndroid Build Coastguard Worker            } \
204*00c7fec1SAndroid Build Coastguard Worker            if (track_name_len <= 0) { \
205*00c7fec1SAndroid Build Coastguard Worker                /* Data is still too long. Drop it. */ \
206*00c7fec1SAndroid Build Coastguard Worker                len = 0; \
207*00c7fec1SAndroid Build Coastguard Worker            } else { \
208*00c7fec1SAndroid Build Coastguard Worker                /* Truncate the trackName and name to make the message fit */ \
209*00c7fec1SAndroid Build Coastguard Worker                len = snprintf(buf, sizeof(buf), format_begin "%.*s|%.1s" format_end, pid, \
210*00c7fec1SAndroid Build Coastguard Worker                    track_name_len, track_name, name, value); \
211*00c7fec1SAndroid Build Coastguard Worker            } \
212*00c7fec1SAndroid Build Coastguard Worker        } \
213*00c7fec1SAndroid Build Coastguard Worker    } \
214*00c7fec1SAndroid Build Coastguard Worker    if (len > 0) { \
215*00c7fec1SAndroid Build Coastguard Worker        write(atrace_marker_fd, buf, len); \
216*00c7fec1SAndroid Build Coastguard Worker    } \
217*00c7fec1SAndroid Build Coastguard Worker}
218*00c7fec1SAndroid Build Coastguard Worker
219*00c7fec1SAndroid Build Coastguard Worker#endif  // __TRACE_DEV_INC
220