blob: 006dbfe67ef4915cfd248d407108b8093a34113b [file] [log] [blame]
Mikael Pessa90092f42019-08-26 17:22:04 -07001/*
2 * Copyright 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#undef LOG_TAG
18#define LOG_TAG "FrameTracer"
19#define ATRACE_TAG ATRACE_TAG_GRAPHICS
20
21#include "FrameTracer.h"
22
23#include <android-base/stringprintf.h>
24
25#include <algorithm>
Raymond Chiu27b53722019-09-03 17:55:10 -070026#include <mutex>
Mikael Pessa90092f42019-08-26 17:22:04 -070027
28PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(android::FrameTracer::FrameTracerDataSource);
29
30namespace android {
31
32void FrameTracer::initialize() {
Raymond Chiu27b53722019-09-03 17:55:10 -070033 std::call_once(mInitializationFlag, [this]() {
34 perfetto::TracingInitArgs args;
35 args.backends = perfetto::kSystemBackend;
36 perfetto::Tracing::Initialize(args);
37 registerDataSource();
38 });
Mikael Pessa90092f42019-08-26 17:22:04 -070039}
40
41void FrameTracer::registerDataSource() {
42 perfetto::DataSourceDescriptor dsd;
43 dsd.set_name(kFrameTracerDataSource);
44 FrameTracerDataSource::Register(dsd);
45}
46
47void FrameTracer::traceNewLayer(int32_t layerID, const std::string& layerName) {
48 FrameTracerDataSource::Trace([this, layerID, &layerName](FrameTracerDataSource::TraceContext) {
49 if (mTraceTracker.find(layerID) == mTraceTracker.end()) {
50 std::lock_guard<std::mutex> lock(mTraceMutex);
51 mTraceTracker[layerID].layerName = layerName;
52 }
53 });
54}
55
56void FrameTracer::traceTimestamp(int32_t layerID, uint64_t bufferID, uint64_t frameNumber,
57 nsecs_t timestamp, FrameEvent::BufferEventType type,
58 nsecs_t duration) {
59 FrameTracerDataSource::Trace([this, layerID, bufferID, frameNumber, timestamp, type,
60 duration](FrameTracerDataSource::TraceContext ctx) {
61 std::lock_guard<std::mutex> lock(mTraceMutex);
62 if (mTraceTracker.find(layerID) == mTraceTracker.end()) {
63 return;
64 }
65
66 // Handle any pending fences for this buffer.
67 tracePendingFencesLocked(ctx, layerID, bufferID);
68
69 // Complete current trace.
70 traceLocked(ctx, layerID, bufferID, frameNumber, timestamp, type, duration);
71 });
72}
73
74void FrameTracer::traceFence(int32_t layerID, uint64_t bufferID, uint64_t frameNumber,
75 const std::shared_ptr<FenceTime>& fence,
76 FrameEvent::BufferEventType type, nsecs_t startTime) {
77 FrameTracerDataSource::Trace([this, layerID, bufferID, frameNumber, &fence, type,
78 startTime](FrameTracerDataSource::TraceContext ctx) {
79 const nsecs_t signalTime = fence->getSignalTime();
80 if (signalTime != Fence::SIGNAL_TIME_INVALID) {
81 std::lock_guard<std::mutex> lock(mTraceMutex);
82 if (mTraceTracker.find(layerID) == mTraceTracker.end()) {
83 return;
84 }
85
86 // Handle any pending fences for this buffer.
87 tracePendingFencesLocked(ctx, layerID, bufferID);
88
89 if (signalTime != Fence::SIGNAL_TIME_PENDING) {
90 traceSpanLocked(ctx, layerID, bufferID, frameNumber, type, startTime, signalTime);
91 } else {
92 mTraceTracker[layerID].pendingFences[bufferID].push_back(
93 {.frameNumber = frameNumber,
94 .type = type,
95 .fence = fence,
96 .startTime = startTime});
97 }
98 }
99 });
100}
101
102void FrameTracer::tracePendingFencesLocked(FrameTracerDataSource::TraceContext& ctx,
103 int32_t layerID, uint64_t bufferID) {
104 if (mTraceTracker[layerID].pendingFences.count(bufferID)) {
105 auto& pendingFences = mTraceTracker[layerID].pendingFences[bufferID];
106 for (size_t i = 0; i < pendingFences.size(); ++i) {
107 auto& pendingFence = pendingFences[i];
108
109 nsecs_t signalTime = Fence::SIGNAL_TIME_INVALID;
110 if (pendingFence.fence && pendingFence.fence->isValid()) {
111 signalTime = pendingFence.fence->getSignalTime();
112 if (signalTime == Fence::SIGNAL_TIME_PENDING) {
113 continue;
114 }
115 }
116
117 if (signalTime != Fence::SIGNAL_TIME_INVALID &&
118 systemTime() - signalTime < kFenceSignallingDeadline) {
119 traceSpanLocked(ctx, layerID, bufferID, pendingFence.frameNumber, pendingFence.type,
120 pendingFence.startTime, signalTime);
121 }
122
123 pendingFences.erase(pendingFences.begin() + i);
124 --i;
125 }
126 }
127}
128
129void FrameTracer::traceLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerID,
130 uint64_t bufferID, uint64_t frameNumber, nsecs_t timestamp,
131 FrameEvent::BufferEventType type, nsecs_t duration) {
132 auto packet = ctx.NewTracePacket();
133 packet->set_timestamp(timestamp);
134 auto* event = packet->set_graphics_frame_event()->set_buffer_event();
135 event->set_buffer_id(static_cast<uint32_t>(bufferID));
136 event->set_frame_number(frameNumber);
137 event->set_type(type);
138
139 if (mTraceTracker.find(layerID) != mTraceTracker.end() &&
140 !mTraceTracker[layerID].layerName.empty()) {
141 const std::string& layerName = mTraceTracker[layerID].layerName;
142 event->set_layer_name(layerName.c_str(), layerName.size());
143 }
144
145 if (duration > 0) {
146 event->set_duration_ns(duration);
147 }
148}
149
150void FrameTracer::traceSpanLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerID,
151 uint64_t bufferID, uint64_t frameNumber,
152 FrameEvent::BufferEventType type, nsecs_t startTime,
153 nsecs_t endTime) {
154 nsecs_t timestamp = endTime;
155 nsecs_t duration = 0;
156 if (startTime > 0 && startTime < endTime) {
157 timestamp = startTime;
158 duration = endTime - startTime;
159 }
160 traceLocked(ctx, layerID, bufferID, frameNumber, timestamp, type, duration);
161}
162
163void FrameTracer::onDestroy(int32_t layerID) {
164 std::lock_guard<std::mutex> traceLock(mTraceMutex);
165 mTraceTracker.erase(layerID);
166}
167
168std::string FrameTracer::miniDump() {
169 std::string result = "FrameTracer miniDump:\n";
170 std::lock_guard<std::mutex> lock(mTraceMutex);
171 android::base::StringAppendF(&result, "Number of layers currently being traced is %zu\n",
172 mTraceTracker.size());
173 return result;
174}
175
176} // namespace android