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 #pragma once
18 
19 #include <perfetto/trace/android/graphics_frame_event.pbzero.h>
20 #include <perfetto/tracing.h>
21 #include <ui/FenceTime.h>
22 
23 #include <mutex>
24 #include <unordered_map>
25 
26 namespace android {
27 
28 class FrameTracer {
29 public:
30     class FrameTracerDataSource : public perfetto::DataSource<FrameTracerDataSource> {
OnSetup(const SetupArgs &)31         virtual void OnSetup(const SetupArgs&) override{};
OnStart(const StartArgs &)32         virtual void OnStart(const StartArgs&) override{};
OnStop(const StopArgs &)33         virtual void OnStop(const StopArgs&) override{};
34     };
35 
36     static const uint64_t UNSPECIFIED_FRAME_NUMBER = std::numeric_limits<uint64_t>::max();
37 
38     using FrameEvent = perfetto::protos::pbzero::GraphicsFrameEvent;
39 
40     ~FrameTracer() = default;
41 
42     // Sets up the perfetto tracing backend and data source.
43     void initialize();
44     // Registers the data source with the perfetto backend. Called as part of initialize()
45     // and should not be called manually outside of tests. Public to allow for substituting a
46     // perfetto::kInProcessBackend in tests.
47     void registerDataSource();
48     // Starts tracking a new layer for tracing. Needs to be called once before traceTimestamp() or
49     // traceFence() for each layer.
50     void traceNewLayer(int32_t layerId, const std::string& layerName);
51     // Creates a trace point at the timestamp provided.
52     void traceTimestamp(int32_t layerId, uint64_t bufferID, uint64_t frameNumber, nsecs_t timestamp,
53                         FrameEvent::BufferEventType type, nsecs_t duration = 0);
54     // Creates a trace point after the provided fence has been signalled. If a startTime is provided
55     // the trace will have be timestamped from startTime until fence signalling time. If no
56     // startTime is provided, a durationless trace point will be created timestamped at fence
57     // signalling time. If the fence hasn't signalled yet, the trace point will be created the next
58     // time after signalling a trace call for this buffer occurs.
59     void traceFence(int32_t layerId, uint64_t bufferID, uint64_t frameNumber,
60                     const std::shared_ptr<FenceTime>& fence, FrameEvent::BufferEventType type,
61                     nsecs_t startTime = 0);
62 
63     // Takes care of cleanup when a layer is destroyed.
64     void onDestroy(int32_t layerId);
65 
66     std::string miniDump();
67 
68     static constexpr char kFrameTracerDataSource[] = "android.surfaceflinger.frame";
69 
70     // The maximum amount of time a fence has to signal before it is discarded.
71     // Used to avoid fences from previous traces generating new trace points in later ones.
72     // Public for testing.
73     static constexpr nsecs_t kFenceSignallingDeadline = 60'000'000'000; // 60 seconds
74 
75 private:
76     struct PendingFence {
77         uint64_t frameNumber;
78         FrameEvent::BufferEventType type;
79         std::shared_ptr<FenceTime> fence;
80         nsecs_t startTime;
81     };
82 
83     struct TraceRecord {
84         std::string layerName;
85         using BufferID = uint64_t;
86         std::unordered_map<BufferID, std::vector<PendingFence>> pendingFences;
87     };
88 
89     // Checks if any pending fences for a layer and buffer have signalled and, if they have, creates
90     // trace points for them.
91     void tracePendingFencesLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerId,
92                                   uint64_t bufferID);
93     // Creates a trace point by translating a start time and an end time to a timestamp and
94     // duration. If startTime is later than end time it sets end time as the timestamp and the
95     // duration to 0. Used by traceFence().
96     void traceSpanLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerId,
97                          uint64_t bufferID, uint64_t frameNumber, FrameEvent::BufferEventType type,
98                          nsecs_t startTime, nsecs_t endTime);
99     void traceLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerId, uint64_t bufferID,
100                      uint64_t frameNumber, nsecs_t timestamp, FrameEvent::BufferEventType type,
101                      nsecs_t duration = 0);
102 
103     std::mutex mTraceMutex;
104     std::unordered_map<int32_t, TraceRecord> mTraceTracker;
105     std::once_flag mInitializationFlag;
106 };
107 
108 } // namespace android
109