• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 // TODO(b/129481165): remove the #pragma below and fix conversion issues
18 #pragma clang diagnostic push
19 #pragma clang diagnostic ignored "-Wconversion"
20 
21 #undef LOG_TAG
22 #define LOG_TAG "FrameTracer"
23 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
24 
25 #include "FrameTracer.h"
26 
27 #include <android-base/stringprintf.h>
28 #include <perfetto/common/builtin_clock.pbzero.h>
29 
30 #include <algorithm>
31 #include <mutex>
32 
33 PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(android::FrameTracer::FrameTracerDataSource);
34 
35 namespace android {
36 
initialize()37 void FrameTracer::initialize() {
38     std::call_once(mInitializationFlag, [this]() {
39         perfetto::TracingInitArgs args;
40         args.backends = perfetto::kSystemBackend;
41         perfetto::Tracing::Initialize(args);
42         registerDataSource();
43     });
44 }
45 
registerDataSource()46 void FrameTracer::registerDataSource() {
47     perfetto::DataSourceDescriptor dsd;
48     dsd.set_name(kFrameTracerDataSource);
49     FrameTracerDataSource::Register(dsd);
50 }
51 
traceNewLayer(int32_t layerId,const std::string & layerName)52 void FrameTracer::traceNewLayer(int32_t layerId, const std::string& layerName) {
53     FrameTracerDataSource::Trace([this, layerId, &layerName](FrameTracerDataSource::TraceContext) {
54         if (mTraceTracker.find(layerId) == mTraceTracker.end()) {
55             std::lock_guard<std::mutex> lock(mTraceMutex);
56             mTraceTracker[layerId].layerName = layerName;
57         }
58     });
59 }
60 
traceTimestamp(int32_t layerId,uint64_t bufferID,uint64_t frameNumber,nsecs_t timestamp,FrameEvent::BufferEventType type,nsecs_t duration)61 void FrameTracer::traceTimestamp(int32_t layerId, uint64_t bufferID, uint64_t frameNumber,
62                                  nsecs_t timestamp, FrameEvent::BufferEventType type,
63                                  nsecs_t duration) {
64     FrameTracerDataSource::Trace([this, layerId, bufferID, frameNumber, timestamp, type,
65                                   duration](FrameTracerDataSource::TraceContext ctx) {
66         std::lock_guard<std::mutex> lock(mTraceMutex);
67         if (mTraceTracker.find(layerId) == mTraceTracker.end()) {
68             return;
69         }
70 
71         // Handle any pending fences for this buffer.
72         tracePendingFencesLocked(ctx, layerId, bufferID);
73 
74         // Complete current trace.
75         traceLocked(ctx, layerId, bufferID, frameNumber, timestamp, type, duration);
76     });
77 }
78 
traceFence(int32_t layerId,uint64_t bufferID,uint64_t frameNumber,const std::shared_ptr<FenceTime> & fence,FrameEvent::BufferEventType type,nsecs_t startTime)79 void FrameTracer::traceFence(int32_t layerId, uint64_t bufferID, uint64_t frameNumber,
80                              const std::shared_ptr<FenceTime>& fence,
81                              FrameEvent::BufferEventType type, nsecs_t startTime) {
82     FrameTracerDataSource::Trace([this, layerId, bufferID, frameNumber, &fence, type,
83                                   startTime](FrameTracerDataSource::TraceContext ctx) {
84         const nsecs_t signalTime = fence->getSignalTime();
85         if (signalTime != Fence::SIGNAL_TIME_INVALID) {
86             std::lock_guard<std::mutex> lock(mTraceMutex);
87             if (mTraceTracker.find(layerId) == mTraceTracker.end()) {
88                 return;
89             }
90 
91             // Handle any pending fences for this buffer.
92             tracePendingFencesLocked(ctx, layerId, bufferID);
93 
94             if (signalTime != Fence::SIGNAL_TIME_PENDING) {
95                 traceSpanLocked(ctx, layerId, bufferID, frameNumber, type, startTime, signalTime);
96             } else {
97                 mTraceTracker[layerId].pendingFences[bufferID].push_back(
98                         {.frameNumber = frameNumber,
99                          .type = type,
100                          .fence = fence,
101                          .startTime = startTime});
102             }
103         }
104     });
105 }
106 
tracePendingFencesLocked(FrameTracerDataSource::TraceContext & ctx,int32_t layerId,uint64_t bufferID)107 void FrameTracer::tracePendingFencesLocked(FrameTracerDataSource::TraceContext& ctx,
108                                            int32_t layerId, uint64_t bufferID) {
109     if (mTraceTracker[layerId].pendingFences.count(bufferID)) {
110         auto& pendingFences = mTraceTracker[layerId].pendingFences[bufferID];
111         for (size_t i = 0; i < pendingFences.size(); ++i) {
112             auto& pendingFence = pendingFences[i];
113 
114             nsecs_t signalTime = Fence::SIGNAL_TIME_INVALID;
115             if (pendingFence.fence && pendingFence.fence->isValid()) {
116                 signalTime = pendingFence.fence->getSignalTime();
117                 if (signalTime == Fence::SIGNAL_TIME_PENDING) {
118                     continue;
119                 }
120             }
121 
122             if (signalTime != Fence::SIGNAL_TIME_INVALID &&
123                 systemTime() - signalTime < kFenceSignallingDeadline) {
124                 traceSpanLocked(ctx, layerId, bufferID, pendingFence.frameNumber, pendingFence.type,
125                                 pendingFence.startTime, signalTime);
126             }
127 
128             pendingFences.erase(pendingFences.begin() + i);
129             --i;
130         }
131     }
132 }
133 
traceLocked(FrameTracerDataSource::TraceContext & ctx,int32_t layerId,uint64_t bufferID,uint64_t frameNumber,nsecs_t timestamp,FrameEvent::BufferEventType type,nsecs_t duration)134 void FrameTracer::traceLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerId,
135                               uint64_t bufferID, uint64_t frameNumber, nsecs_t timestamp,
136                               FrameEvent::BufferEventType type, nsecs_t duration) {
137     auto packet = ctx.NewTracePacket();
138     packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
139     packet->set_timestamp(timestamp);
140     auto* event = packet->set_graphics_frame_event()->set_buffer_event();
141     event->set_buffer_id(static_cast<uint32_t>(bufferID));
142     if (frameNumber != UNSPECIFIED_FRAME_NUMBER) {
143         event->set_frame_number(frameNumber);
144     }
145     event->set_type(type);
146 
147     if (mTraceTracker.find(layerId) != mTraceTracker.end() &&
148         !mTraceTracker[layerId].layerName.empty()) {
149         const std::string& layerName = mTraceTracker[layerId].layerName;
150         event->set_layer_name(layerName.c_str(), layerName.size());
151     }
152 
153     if (duration > 0) {
154         event->set_duration_ns(duration);
155     }
156 }
157 
traceSpanLocked(FrameTracerDataSource::TraceContext & ctx,int32_t layerId,uint64_t bufferID,uint64_t frameNumber,FrameEvent::BufferEventType type,nsecs_t startTime,nsecs_t endTime)158 void FrameTracer::traceSpanLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerId,
159                                   uint64_t bufferID, uint64_t frameNumber,
160                                   FrameEvent::BufferEventType type, nsecs_t startTime,
161                                   nsecs_t endTime) {
162     nsecs_t timestamp = endTime;
163     nsecs_t duration = 0;
164     if (startTime > 0 && startTime < endTime) {
165         timestamp = startTime;
166         duration = endTime - startTime;
167     }
168     traceLocked(ctx, layerId, bufferID, frameNumber, timestamp, type, duration);
169 }
170 
onDestroy(int32_t layerId)171 void FrameTracer::onDestroy(int32_t layerId) {
172     std::lock_guard<std::mutex> traceLock(mTraceMutex);
173     mTraceTracker.erase(layerId);
174 }
175 
miniDump()176 std::string FrameTracer::miniDump() {
177     std::string result = "FrameTracer miniDump:\n";
178     std::lock_guard<std::mutex> lock(mTraceMutex);
179     android::base::StringAppendF(&result, "Number of layers currently being traced is %zu\n",
180                                  mTraceTracker.size());
181     return result;
182 }
183 
184 } // namespace android
185 
186 // TODO(b/129481165): remove the #pragma below and fix conversion issues
187 #pragma clang diagnostic pop // ignored "-Wconversion"
188