Update .DEPS.git
[chromium-blink-merge.git] / base / debug / trace_event_android.cc
blobc56c3c1220d2fdbbfc7ac999bf366004fcf5704b
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/debug/trace_event_impl.h"
7 #include <fcntl.h>
9 #include "base/debug/trace_event.h"
10 #include "base/file_util.h"
11 #include "base/format_macros.h"
12 #include "base/logging.h"
13 #include "base/stringprintf.h"
15 namespace {
17 int g_atrace_fd = -1;
18 const char* kATraceMarkerFile = "/sys/kernel/debug/tracing/trace_marker";
20 } // namespace
22 namespace base {
23 namespace debug {
25 // static
26 void TraceLog::InitATrace() {
27 DCHECK(g_atrace_fd == -1);
28 g_atrace_fd = open(kATraceMarkerFile, O_WRONLY | O_APPEND);
29 if (g_atrace_fd == -1)
30 LOG(WARNING) << "Couldn't open " << kATraceMarkerFile;
33 void TraceLog::SendToATrace(char phase,
34 const char* category,
35 const char* name,
36 int num_args,
37 const char** arg_names,
38 const unsigned char* arg_types,
39 const unsigned long long* arg_values) {
40 if (g_atrace_fd == -1)
41 return;
43 switch (phase) {
44 case TRACE_EVENT_PHASE_BEGIN:
45 case TRACE_EVENT_PHASE_INSTANT: {
46 std::string out = StringPrintf("B|%d|%s-%s", getpid(), category, name);
47 for (int i = 0; i < num_args; ++i) {
48 out += (i == 0 ? '|' : ';');
49 out += arg_names[i];
50 out += '=';
51 TraceEvent::TraceValue value;
52 value.as_uint = arg_values[i];
53 std::string::size_type value_start = out.length();
54 TraceEvent::AppendValueAsJSON(arg_types[i], value, &out);
55 // Remove the quotes which may confuse the atrace script.
56 ReplaceSubstringsAfterOffset(&out, value_start, "\\\"", "'");
57 ReplaceSubstringsAfterOffset(&out, value_start, "\"", "");
58 // Replace chars used for separators with similar chars in the value.
59 std::replace(out.begin() + value_start, out.end(), ';', ',');
60 std::replace(out.begin() + value_start, out.end(), '|', '!');
62 write(g_atrace_fd, out.c_str(), out.size());
64 if (phase != TRACE_EVENT_PHASE_INSTANT)
65 break;
66 // Fall through. Simulate an instance event with a pair of begin/end.
68 case TRACE_EVENT_PHASE_END: {
69 // Though a single 'E' is enough, here append pid and name so that
70 // unpaired events can be found easily.
71 std::string out = StringPrintf("E|%d|%s-%s", getpid(), category, name);
72 write(g_atrace_fd, out.c_str(), out.size());
73 break;
75 case TRACE_EVENT_PHASE_COUNTER:
76 for (int i = 0; i < num_args; ++i) {
77 DCHECK(arg_types[i] == TRACE_VALUE_TYPE_INT);
78 std::string out = StringPrintf(
79 "C|%d|%s-%s-%s|%d",
80 getpid(), category, name,
81 arg_names[i], static_cast<int>(arg_values[i]));
82 write(g_atrace_fd, out.c_str(), out.size());
84 break;
86 default:
87 // Do nothing.
88 break;
92 void TraceLog::AddClockSyncMetadataEvents() {
93 // Since Android does not support sched_setaffinity, we cannot establish clock
94 // sync unless the scheduler clock is set to global. If the trace_clock file
95 // can't be read, we will assume the kernel doesn't support tracing and do
96 // nothing.
97 std::string clock_mode;
98 if (!file_util::ReadFileToString(
99 FilePath("/sys/kernel/debug/tracing/trace_clock"), &clock_mode))
100 return;
102 if (clock_mode != "local [global]\n") {
103 DLOG(WARNING) <<
104 "The kernel's tracing clock must be set to global in order for " <<
105 "trace_event to be synchronized with . Do this by\n" <<
106 " echo global > /sys/kerel/debug/tracing/trace_clock";
107 return;
110 int atrace_fd = g_atrace_fd;
111 if (atrace_fd == -1) {
112 // This function may be called when atrace is not enabled.
113 atrace_fd = open(kATraceMarkerFile, O_WRONLY | O_APPEND);
114 if (atrace_fd == -1) {
115 LOG(WARNING) << "Couldn't open " << kATraceMarkerFile;
116 return;
120 // Android's kernel trace system has a trace_marker feature: this is a file on
121 // debugfs that takes the written data and pushes it onto the trace
122 // buffer. So, to establish clock sync, we write our monotonic clock into that
123 // trace buffer.
124 TimeTicks now = TimeTicks::NowFromSystemTraceTime();
125 double now_in_seconds = now.ToInternalValue() / 1000000.0;
126 std::string marker = StringPrintf(
127 "trace_event_clock_sync: parent_ts=%f\n", now_in_seconds);
128 if (write(atrace_fd, marker.c_str(), marker.size()) != 0) {
129 DLOG(WARNING) << "Couldn't write to " << kATraceMarkerFile << ": "
130 << strerror(errno);
133 if (g_atrace_fd == -1)
134 close(atrace_fd);
137 // Must be called with lock_ locked.
138 void TraceLog::ApplyATraceEnabledFlag(unsigned char* category_enabled) {
139 if (g_atrace_fd != -1)
140 *category_enabled |= ATRACE_ENABLED;
143 } // namespace debug
144 } // namespace base