1*38e8c45fSAndroid Build Coastguard Worker /*
2*38e8c45fSAndroid Build Coastguard Worker * Copyright 2020 The Android Open Source Project
3*38e8c45fSAndroid Build Coastguard Worker *
4*38e8c45fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*38e8c45fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*38e8c45fSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*38e8c45fSAndroid Build Coastguard Worker *
8*38e8c45fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*38e8c45fSAndroid Build Coastguard Worker *
10*38e8c45fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*38e8c45fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*38e8c45fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*38e8c45fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*38e8c45fSAndroid Build Coastguard Worker * limitations under the License.
15*38e8c45fSAndroid Build Coastguard Worker */
16*38e8c45fSAndroid Build Coastguard Worker
17*38e8c45fSAndroid Build Coastguard Worker #undef LOG_TAG
18*38e8c45fSAndroid Build Coastguard Worker #define LOG_TAG "FrameTimeline"
19*38e8c45fSAndroid Build Coastguard Worker #define ATRACE_TAG ATRACE_TAG_GRAPHICS
20*38e8c45fSAndroid Build Coastguard Worker
21*38e8c45fSAndroid Build Coastguard Worker #include "FrameTimeline.h"
22*38e8c45fSAndroid Build Coastguard Worker
23*38e8c45fSAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
24*38e8c45fSAndroid Build Coastguard Worker #include <common/FlagManager.h>
25*38e8c45fSAndroid Build Coastguard Worker #include <common/trace.h>
26*38e8c45fSAndroid Build Coastguard Worker #include <utils/Log.h>
27*38e8c45fSAndroid Build Coastguard Worker
28*38e8c45fSAndroid Build Coastguard Worker #include <chrono>
29*38e8c45fSAndroid Build Coastguard Worker #include <cinttypes>
30*38e8c45fSAndroid Build Coastguard Worker #include <numeric>
31*38e8c45fSAndroid Build Coastguard Worker #include <unordered_set>
32*38e8c45fSAndroid Build Coastguard Worker #include <vector>
33*38e8c45fSAndroid Build Coastguard Worker
34*38e8c45fSAndroid Build Coastguard Worker #include "../Jank/JankTracker.h"
35*38e8c45fSAndroid Build Coastguard Worker
36*38e8c45fSAndroid Build Coastguard Worker namespace android::frametimeline {
37*38e8c45fSAndroid Build Coastguard Worker
38*38e8c45fSAndroid Build Coastguard Worker using base::StringAppendF;
39*38e8c45fSAndroid Build Coastguard Worker using FrameTimelineEvent = perfetto::protos::pbzero::FrameTimelineEvent;
40*38e8c45fSAndroid Build Coastguard Worker using FrameTimelineDataSource = impl::FrameTimeline::FrameTimelineDataSource;
41*38e8c45fSAndroid Build Coastguard Worker
42*38e8c45fSAndroid Build Coastguard Worker namespace {
43*38e8c45fSAndroid Build Coastguard Worker
dumpTable(std::string & result,TimelineItem predictions,TimelineItem actuals,const std::string & indent,PredictionState predictionState,nsecs_t baseTime)44*38e8c45fSAndroid Build Coastguard Worker void dumpTable(std::string& result, TimelineItem predictions, TimelineItem actuals,
45*38e8c45fSAndroid Build Coastguard Worker const std::string& indent, PredictionState predictionState, nsecs_t baseTime) {
46*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "%s", indent.c_str());
47*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "\t\t");
48*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, " Start time\t\t|");
49*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, " End time\t\t|");
50*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, " Present time\n");
51*38e8c45fSAndroid Build Coastguard Worker if (predictionState == PredictionState::Valid) {
52*38e8c45fSAndroid Build Coastguard Worker // Dump the Predictions only if they are valid
53*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "%s", indent.c_str());
54*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "Expected\t|");
55*38e8c45fSAndroid Build Coastguard Worker std::chrono::nanoseconds startTime(predictions.startTime - baseTime);
56*38e8c45fSAndroid Build Coastguard Worker std::chrono::nanoseconds endTime(predictions.endTime - baseTime);
57*38e8c45fSAndroid Build Coastguard Worker std::chrono::nanoseconds presentTime(predictions.presentTime - baseTime);
58*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "\t%10.2f\t|\t%10.2f\t|\t%10.2f\n",
59*38e8c45fSAndroid Build Coastguard Worker std::chrono::duration<double, std::milli>(startTime).count(),
60*38e8c45fSAndroid Build Coastguard Worker std::chrono::duration<double, std::milli>(endTime).count(),
61*38e8c45fSAndroid Build Coastguard Worker std::chrono::duration<double, std::milli>(presentTime).count());
62*38e8c45fSAndroid Build Coastguard Worker }
63*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "%s", indent.c_str());
64*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "Actual \t|");
65*38e8c45fSAndroid Build Coastguard Worker
66*38e8c45fSAndroid Build Coastguard Worker if (actuals.startTime == 0) {
67*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "\t\tN/A\t|");
68*38e8c45fSAndroid Build Coastguard Worker } else {
69*38e8c45fSAndroid Build Coastguard Worker std::chrono::nanoseconds startTime(std::max<nsecs_t>(0, actuals.startTime - baseTime));
70*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "\t%10.2f\t|",
71*38e8c45fSAndroid Build Coastguard Worker std::chrono::duration<double, std::milli>(startTime).count());
72*38e8c45fSAndroid Build Coastguard Worker }
73*38e8c45fSAndroid Build Coastguard Worker if (actuals.endTime <= 0) {
74*38e8c45fSAndroid Build Coastguard Worker // Animation leashes can send the endTime as -1
75*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "\t\tN/A\t|");
76*38e8c45fSAndroid Build Coastguard Worker } else {
77*38e8c45fSAndroid Build Coastguard Worker std::chrono::nanoseconds endTime(actuals.endTime - baseTime);
78*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "\t%10.2f\t|",
79*38e8c45fSAndroid Build Coastguard Worker std::chrono::duration<double, std::milli>(endTime).count());
80*38e8c45fSAndroid Build Coastguard Worker }
81*38e8c45fSAndroid Build Coastguard Worker if (actuals.presentTime == 0) {
82*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "\t\tN/A\n");
83*38e8c45fSAndroid Build Coastguard Worker } else {
84*38e8c45fSAndroid Build Coastguard Worker std::chrono::nanoseconds presentTime(std::max<nsecs_t>(0, actuals.presentTime - baseTime));
85*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "\t%10.2f\n",
86*38e8c45fSAndroid Build Coastguard Worker std::chrono::duration<double, std::milli>(presentTime).count());
87*38e8c45fSAndroid Build Coastguard Worker }
88*38e8c45fSAndroid Build Coastguard Worker
89*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "%s", indent.c_str());
90*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "----------------------");
91*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "----------------------");
92*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "----------------------");
93*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "----------------------\n");
94*38e8c45fSAndroid Build Coastguard Worker }
95*38e8c45fSAndroid Build Coastguard Worker
toString(PredictionState predictionState)96*38e8c45fSAndroid Build Coastguard Worker std::string toString(PredictionState predictionState) {
97*38e8c45fSAndroid Build Coastguard Worker switch (predictionState) {
98*38e8c45fSAndroid Build Coastguard Worker case PredictionState::Valid:
99*38e8c45fSAndroid Build Coastguard Worker return "Valid";
100*38e8c45fSAndroid Build Coastguard Worker case PredictionState::Expired:
101*38e8c45fSAndroid Build Coastguard Worker return "Expired";
102*38e8c45fSAndroid Build Coastguard Worker case PredictionState::None:
103*38e8c45fSAndroid Build Coastguard Worker return "None";
104*38e8c45fSAndroid Build Coastguard Worker }
105*38e8c45fSAndroid Build Coastguard Worker }
106*38e8c45fSAndroid Build Coastguard Worker
jankTypeBitmaskToString(int32_t jankType)107*38e8c45fSAndroid Build Coastguard Worker std::string jankTypeBitmaskToString(int32_t jankType) {
108*38e8c45fSAndroid Build Coastguard Worker if (jankType == JankType::None) {
109*38e8c45fSAndroid Build Coastguard Worker return "None";
110*38e8c45fSAndroid Build Coastguard Worker }
111*38e8c45fSAndroid Build Coastguard Worker
112*38e8c45fSAndroid Build Coastguard Worker std::vector<std::string> janks;
113*38e8c45fSAndroid Build Coastguard Worker if (jankType & JankType::DisplayHAL) {
114*38e8c45fSAndroid Build Coastguard Worker janks.emplace_back("Display HAL");
115*38e8c45fSAndroid Build Coastguard Worker jankType &= ~JankType::DisplayHAL;
116*38e8c45fSAndroid Build Coastguard Worker }
117*38e8c45fSAndroid Build Coastguard Worker if (jankType & JankType::SurfaceFlingerCpuDeadlineMissed) {
118*38e8c45fSAndroid Build Coastguard Worker janks.emplace_back("SurfaceFlinger deadline missed (while in HWC)");
119*38e8c45fSAndroid Build Coastguard Worker jankType &= ~JankType::SurfaceFlingerCpuDeadlineMissed;
120*38e8c45fSAndroid Build Coastguard Worker }
121*38e8c45fSAndroid Build Coastguard Worker if (jankType & JankType::SurfaceFlingerGpuDeadlineMissed) {
122*38e8c45fSAndroid Build Coastguard Worker janks.emplace_back("SurfaceFlinger deadline missed (while in GPU comp)");
123*38e8c45fSAndroid Build Coastguard Worker jankType &= ~JankType::SurfaceFlingerGpuDeadlineMissed;
124*38e8c45fSAndroid Build Coastguard Worker }
125*38e8c45fSAndroid Build Coastguard Worker if (jankType & JankType::AppDeadlineMissed) {
126*38e8c45fSAndroid Build Coastguard Worker janks.emplace_back("App Deadline Missed");
127*38e8c45fSAndroid Build Coastguard Worker jankType &= ~JankType::AppDeadlineMissed;
128*38e8c45fSAndroid Build Coastguard Worker }
129*38e8c45fSAndroid Build Coastguard Worker if (jankType & JankType::PredictionError) {
130*38e8c45fSAndroid Build Coastguard Worker janks.emplace_back("Prediction Error");
131*38e8c45fSAndroid Build Coastguard Worker jankType &= ~JankType::PredictionError;
132*38e8c45fSAndroid Build Coastguard Worker }
133*38e8c45fSAndroid Build Coastguard Worker if (jankType & JankType::SurfaceFlingerScheduling) {
134*38e8c45fSAndroid Build Coastguard Worker janks.emplace_back("SurfaceFlinger Scheduling");
135*38e8c45fSAndroid Build Coastguard Worker jankType &= ~JankType::SurfaceFlingerScheduling;
136*38e8c45fSAndroid Build Coastguard Worker }
137*38e8c45fSAndroid Build Coastguard Worker if (jankType & JankType::BufferStuffing) {
138*38e8c45fSAndroid Build Coastguard Worker janks.emplace_back("Buffer Stuffing");
139*38e8c45fSAndroid Build Coastguard Worker jankType &= ~JankType::BufferStuffing;
140*38e8c45fSAndroid Build Coastguard Worker }
141*38e8c45fSAndroid Build Coastguard Worker if (jankType & JankType::Unknown) {
142*38e8c45fSAndroid Build Coastguard Worker janks.emplace_back("Unknown jank");
143*38e8c45fSAndroid Build Coastguard Worker jankType &= ~JankType::Unknown;
144*38e8c45fSAndroid Build Coastguard Worker }
145*38e8c45fSAndroid Build Coastguard Worker if (jankType & JankType::SurfaceFlingerStuffing) {
146*38e8c45fSAndroid Build Coastguard Worker janks.emplace_back("SurfaceFlinger Stuffing");
147*38e8c45fSAndroid Build Coastguard Worker jankType &= ~JankType::SurfaceFlingerStuffing;
148*38e8c45fSAndroid Build Coastguard Worker }
149*38e8c45fSAndroid Build Coastguard Worker if (jankType & JankType::Dropped) {
150*38e8c45fSAndroid Build Coastguard Worker janks.emplace_back("Dropped Frame");
151*38e8c45fSAndroid Build Coastguard Worker jankType &= ~JankType::Dropped;
152*38e8c45fSAndroid Build Coastguard Worker }
153*38e8c45fSAndroid Build Coastguard Worker
154*38e8c45fSAndroid Build Coastguard Worker // jankType should be 0 if all types of jank were checked for.
155*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(jankType != 0, "Unrecognized jank type value 0x%x", jankType);
156*38e8c45fSAndroid Build Coastguard Worker return std::accumulate(janks.begin(), janks.end(), std::string(),
157*38e8c45fSAndroid Build Coastguard Worker [](const std::string& l, const std::string& r) {
158*38e8c45fSAndroid Build Coastguard Worker return l.empty() ? r : l + ", " + r;
159*38e8c45fSAndroid Build Coastguard Worker });
160*38e8c45fSAndroid Build Coastguard Worker }
161*38e8c45fSAndroid Build Coastguard Worker
toString(FramePresentMetadata presentMetadata)162*38e8c45fSAndroid Build Coastguard Worker std::string toString(FramePresentMetadata presentMetadata) {
163*38e8c45fSAndroid Build Coastguard Worker switch (presentMetadata) {
164*38e8c45fSAndroid Build Coastguard Worker case FramePresentMetadata::OnTimePresent:
165*38e8c45fSAndroid Build Coastguard Worker return "On Time Present";
166*38e8c45fSAndroid Build Coastguard Worker case FramePresentMetadata::LatePresent:
167*38e8c45fSAndroid Build Coastguard Worker return "Late Present";
168*38e8c45fSAndroid Build Coastguard Worker case FramePresentMetadata::EarlyPresent:
169*38e8c45fSAndroid Build Coastguard Worker return "Early Present";
170*38e8c45fSAndroid Build Coastguard Worker case FramePresentMetadata::UnknownPresent:
171*38e8c45fSAndroid Build Coastguard Worker return "Unknown Present";
172*38e8c45fSAndroid Build Coastguard Worker }
173*38e8c45fSAndroid Build Coastguard Worker }
174*38e8c45fSAndroid Build Coastguard Worker
toString(FrameReadyMetadata finishMetadata)175*38e8c45fSAndroid Build Coastguard Worker std::string toString(FrameReadyMetadata finishMetadata) {
176*38e8c45fSAndroid Build Coastguard Worker switch (finishMetadata) {
177*38e8c45fSAndroid Build Coastguard Worker case FrameReadyMetadata::OnTimeFinish:
178*38e8c45fSAndroid Build Coastguard Worker return "On Time Finish";
179*38e8c45fSAndroid Build Coastguard Worker case FrameReadyMetadata::LateFinish:
180*38e8c45fSAndroid Build Coastguard Worker return "Late Finish";
181*38e8c45fSAndroid Build Coastguard Worker case FrameReadyMetadata::UnknownFinish:
182*38e8c45fSAndroid Build Coastguard Worker return "Unknown Finish";
183*38e8c45fSAndroid Build Coastguard Worker }
184*38e8c45fSAndroid Build Coastguard Worker }
185*38e8c45fSAndroid Build Coastguard Worker
toString(FrameStartMetadata startMetadata)186*38e8c45fSAndroid Build Coastguard Worker std::string toString(FrameStartMetadata startMetadata) {
187*38e8c45fSAndroid Build Coastguard Worker switch (startMetadata) {
188*38e8c45fSAndroid Build Coastguard Worker case FrameStartMetadata::OnTimeStart:
189*38e8c45fSAndroid Build Coastguard Worker return "On Time Start";
190*38e8c45fSAndroid Build Coastguard Worker case FrameStartMetadata::LateStart:
191*38e8c45fSAndroid Build Coastguard Worker return "Late Start";
192*38e8c45fSAndroid Build Coastguard Worker case FrameStartMetadata::EarlyStart:
193*38e8c45fSAndroid Build Coastguard Worker return "Early Start";
194*38e8c45fSAndroid Build Coastguard Worker case FrameStartMetadata::UnknownStart:
195*38e8c45fSAndroid Build Coastguard Worker return "Unknown Start";
196*38e8c45fSAndroid Build Coastguard Worker }
197*38e8c45fSAndroid Build Coastguard Worker }
198*38e8c45fSAndroid Build Coastguard Worker
toString(SurfaceFrame::PresentState presentState)199*38e8c45fSAndroid Build Coastguard Worker std::string toString(SurfaceFrame::PresentState presentState) {
200*38e8c45fSAndroid Build Coastguard Worker using PresentState = SurfaceFrame::PresentState;
201*38e8c45fSAndroid Build Coastguard Worker switch (presentState) {
202*38e8c45fSAndroid Build Coastguard Worker case PresentState::Presented:
203*38e8c45fSAndroid Build Coastguard Worker return "Presented";
204*38e8c45fSAndroid Build Coastguard Worker case PresentState::Dropped:
205*38e8c45fSAndroid Build Coastguard Worker return "Dropped";
206*38e8c45fSAndroid Build Coastguard Worker case PresentState::Unknown:
207*38e8c45fSAndroid Build Coastguard Worker return "Unknown";
208*38e8c45fSAndroid Build Coastguard Worker }
209*38e8c45fSAndroid Build Coastguard Worker }
210*38e8c45fSAndroid Build Coastguard Worker
toProto(FramePresentMetadata presentMetadata)211*38e8c45fSAndroid Build Coastguard Worker FrameTimelineEvent::PresentType toProto(FramePresentMetadata presentMetadata) {
212*38e8c45fSAndroid Build Coastguard Worker switch (presentMetadata) {
213*38e8c45fSAndroid Build Coastguard Worker case FramePresentMetadata::EarlyPresent:
214*38e8c45fSAndroid Build Coastguard Worker return FrameTimelineEvent::PRESENT_EARLY;
215*38e8c45fSAndroid Build Coastguard Worker case FramePresentMetadata::LatePresent:
216*38e8c45fSAndroid Build Coastguard Worker return FrameTimelineEvent::PRESENT_LATE;
217*38e8c45fSAndroid Build Coastguard Worker case FramePresentMetadata::OnTimePresent:
218*38e8c45fSAndroid Build Coastguard Worker return FrameTimelineEvent::PRESENT_ON_TIME;
219*38e8c45fSAndroid Build Coastguard Worker case FramePresentMetadata::UnknownPresent:
220*38e8c45fSAndroid Build Coastguard Worker return FrameTimelineEvent::PRESENT_UNSPECIFIED;
221*38e8c45fSAndroid Build Coastguard Worker }
222*38e8c45fSAndroid Build Coastguard Worker }
223*38e8c45fSAndroid Build Coastguard Worker
toProto(PredictionState predictionState)224*38e8c45fSAndroid Build Coastguard Worker FrameTimelineEvent::PredictionType toProto(PredictionState predictionState) {
225*38e8c45fSAndroid Build Coastguard Worker switch (predictionState) {
226*38e8c45fSAndroid Build Coastguard Worker case PredictionState::Valid:
227*38e8c45fSAndroid Build Coastguard Worker return FrameTimelineEvent::PREDICTION_VALID;
228*38e8c45fSAndroid Build Coastguard Worker case PredictionState::Expired:
229*38e8c45fSAndroid Build Coastguard Worker return FrameTimelineEvent::PREDICTION_EXPIRED;
230*38e8c45fSAndroid Build Coastguard Worker case PredictionState::None:
231*38e8c45fSAndroid Build Coastguard Worker return FrameTimelineEvent::PREDICTION_UNKNOWN;
232*38e8c45fSAndroid Build Coastguard Worker }
233*38e8c45fSAndroid Build Coastguard Worker }
234*38e8c45fSAndroid Build Coastguard Worker
jankTypeBitmaskToProto(int32_t jankType)235*38e8c45fSAndroid Build Coastguard Worker int32_t jankTypeBitmaskToProto(int32_t jankType) {
236*38e8c45fSAndroid Build Coastguard Worker if (jankType == JankType::None) {
237*38e8c45fSAndroid Build Coastguard Worker return FrameTimelineEvent::JANK_NONE;
238*38e8c45fSAndroid Build Coastguard Worker }
239*38e8c45fSAndroid Build Coastguard Worker
240*38e8c45fSAndroid Build Coastguard Worker int32_t protoJank = 0;
241*38e8c45fSAndroid Build Coastguard Worker if (jankType & JankType::DisplayHAL) {
242*38e8c45fSAndroid Build Coastguard Worker protoJank |= FrameTimelineEvent::JANK_DISPLAY_HAL;
243*38e8c45fSAndroid Build Coastguard Worker jankType &= ~JankType::DisplayHAL;
244*38e8c45fSAndroid Build Coastguard Worker }
245*38e8c45fSAndroid Build Coastguard Worker if (jankType & JankType::SurfaceFlingerCpuDeadlineMissed) {
246*38e8c45fSAndroid Build Coastguard Worker protoJank |= FrameTimelineEvent::JANK_SF_CPU_DEADLINE_MISSED;
247*38e8c45fSAndroid Build Coastguard Worker jankType &= ~JankType::SurfaceFlingerCpuDeadlineMissed;
248*38e8c45fSAndroid Build Coastguard Worker }
249*38e8c45fSAndroid Build Coastguard Worker if (jankType & JankType::SurfaceFlingerGpuDeadlineMissed) {
250*38e8c45fSAndroid Build Coastguard Worker protoJank |= FrameTimelineEvent::JANK_SF_GPU_DEADLINE_MISSED;
251*38e8c45fSAndroid Build Coastguard Worker jankType &= ~JankType::SurfaceFlingerGpuDeadlineMissed;
252*38e8c45fSAndroid Build Coastguard Worker }
253*38e8c45fSAndroid Build Coastguard Worker if (jankType & JankType::AppDeadlineMissed) {
254*38e8c45fSAndroid Build Coastguard Worker protoJank |= FrameTimelineEvent::JANK_APP_DEADLINE_MISSED;
255*38e8c45fSAndroid Build Coastguard Worker jankType &= ~JankType::AppDeadlineMissed;
256*38e8c45fSAndroid Build Coastguard Worker }
257*38e8c45fSAndroid Build Coastguard Worker if (jankType & JankType::PredictionError) {
258*38e8c45fSAndroid Build Coastguard Worker protoJank |= FrameTimelineEvent::JANK_PREDICTION_ERROR;
259*38e8c45fSAndroid Build Coastguard Worker jankType &= ~JankType::PredictionError;
260*38e8c45fSAndroid Build Coastguard Worker }
261*38e8c45fSAndroid Build Coastguard Worker if (jankType & JankType::SurfaceFlingerScheduling) {
262*38e8c45fSAndroid Build Coastguard Worker protoJank |= FrameTimelineEvent::JANK_SF_SCHEDULING;
263*38e8c45fSAndroid Build Coastguard Worker jankType &= ~JankType::SurfaceFlingerScheduling;
264*38e8c45fSAndroid Build Coastguard Worker }
265*38e8c45fSAndroid Build Coastguard Worker if (jankType & JankType::BufferStuffing) {
266*38e8c45fSAndroid Build Coastguard Worker protoJank |= FrameTimelineEvent::JANK_BUFFER_STUFFING;
267*38e8c45fSAndroid Build Coastguard Worker jankType &= ~JankType::BufferStuffing;
268*38e8c45fSAndroid Build Coastguard Worker }
269*38e8c45fSAndroid Build Coastguard Worker if (jankType & JankType::Unknown) {
270*38e8c45fSAndroid Build Coastguard Worker protoJank |= FrameTimelineEvent::JANK_UNKNOWN;
271*38e8c45fSAndroid Build Coastguard Worker jankType &= ~JankType::Unknown;
272*38e8c45fSAndroid Build Coastguard Worker }
273*38e8c45fSAndroid Build Coastguard Worker if (jankType & JankType::SurfaceFlingerStuffing) {
274*38e8c45fSAndroid Build Coastguard Worker protoJank |= FrameTimelineEvent::JANK_SF_STUFFING;
275*38e8c45fSAndroid Build Coastguard Worker jankType &= ~JankType::SurfaceFlingerStuffing;
276*38e8c45fSAndroid Build Coastguard Worker }
277*38e8c45fSAndroid Build Coastguard Worker if (jankType & JankType::Dropped) {
278*38e8c45fSAndroid Build Coastguard Worker // Jank dropped does not append to other janks, it fully overrides.
279*38e8c45fSAndroid Build Coastguard Worker protoJank |= FrameTimelineEvent::JANK_DROPPED;
280*38e8c45fSAndroid Build Coastguard Worker jankType &= ~JankType::Dropped;
281*38e8c45fSAndroid Build Coastguard Worker }
282*38e8c45fSAndroid Build Coastguard Worker
283*38e8c45fSAndroid Build Coastguard Worker // jankType should be 0 if all types of jank were checked for.
284*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(jankType != 0, "Unrecognized jank type value 0x%x", jankType);
285*38e8c45fSAndroid Build Coastguard Worker return protoJank;
286*38e8c45fSAndroid Build Coastguard Worker }
287*38e8c45fSAndroid Build Coastguard Worker
toProto(JankSeverityType jankSeverityType)288*38e8c45fSAndroid Build Coastguard Worker FrameTimelineEvent::JankSeverityType toProto(JankSeverityType jankSeverityType) {
289*38e8c45fSAndroid Build Coastguard Worker switch (jankSeverityType) {
290*38e8c45fSAndroid Build Coastguard Worker case JankSeverityType::Unknown:
291*38e8c45fSAndroid Build Coastguard Worker return FrameTimelineEvent::SEVERITY_UNKNOWN;
292*38e8c45fSAndroid Build Coastguard Worker case JankSeverityType::None:
293*38e8c45fSAndroid Build Coastguard Worker return FrameTimelineEvent::SEVERITY_NONE;
294*38e8c45fSAndroid Build Coastguard Worker case JankSeverityType::Partial:
295*38e8c45fSAndroid Build Coastguard Worker return FrameTimelineEvent::SEVERITY_PARTIAL;
296*38e8c45fSAndroid Build Coastguard Worker case JankSeverityType::Full:
297*38e8c45fSAndroid Build Coastguard Worker return FrameTimelineEvent::SEVERITY_FULL;
298*38e8c45fSAndroid Build Coastguard Worker }
299*38e8c45fSAndroid Build Coastguard Worker }
300*38e8c45fSAndroid Build Coastguard Worker
301*38e8c45fSAndroid Build Coastguard Worker // Returns the smallest timestamp from the set of predictions and actuals.
getMinTime(PredictionState predictionState,TimelineItem predictions,TimelineItem actuals)302*38e8c45fSAndroid Build Coastguard Worker nsecs_t getMinTime(PredictionState predictionState, TimelineItem predictions,
303*38e8c45fSAndroid Build Coastguard Worker TimelineItem actuals) {
304*38e8c45fSAndroid Build Coastguard Worker nsecs_t minTime = std::numeric_limits<nsecs_t>::max();
305*38e8c45fSAndroid Build Coastguard Worker if (predictionState == PredictionState::Valid) {
306*38e8c45fSAndroid Build Coastguard Worker // Checking start time for predictions is enough because start time is always lesser than
307*38e8c45fSAndroid Build Coastguard Worker // endTime and presentTime.
308*38e8c45fSAndroid Build Coastguard Worker minTime = std::min(minTime, predictions.startTime);
309*38e8c45fSAndroid Build Coastguard Worker }
310*38e8c45fSAndroid Build Coastguard Worker
311*38e8c45fSAndroid Build Coastguard Worker // Need to check startTime, endTime and presentTime for actuals because some frames might not
312*38e8c45fSAndroid Build Coastguard Worker // have them set.
313*38e8c45fSAndroid Build Coastguard Worker if (actuals.startTime != 0) {
314*38e8c45fSAndroid Build Coastguard Worker minTime = std::min(minTime, actuals.startTime);
315*38e8c45fSAndroid Build Coastguard Worker }
316*38e8c45fSAndroid Build Coastguard Worker if (actuals.endTime != 0) {
317*38e8c45fSAndroid Build Coastguard Worker minTime = std::min(minTime, actuals.endTime);
318*38e8c45fSAndroid Build Coastguard Worker }
319*38e8c45fSAndroid Build Coastguard Worker if (actuals.presentTime != 0) {
320*38e8c45fSAndroid Build Coastguard Worker minTime = std::min(minTime, actuals.presentTime);
321*38e8c45fSAndroid Build Coastguard Worker }
322*38e8c45fSAndroid Build Coastguard Worker return minTime;
323*38e8c45fSAndroid Build Coastguard Worker }
324*38e8c45fSAndroid Build Coastguard Worker
shouldTraceForDataSource(const FrameTimelineDataSource::TraceContext & ctx,nsecs_t timestamp)325*38e8c45fSAndroid Build Coastguard Worker bool shouldTraceForDataSource(const FrameTimelineDataSource::TraceContext& ctx, nsecs_t timestamp) {
326*38e8c45fSAndroid Build Coastguard Worker if (auto ds = ctx.GetDataSourceLocked(); ds && ds->getStartTime() > timestamp) {
327*38e8c45fSAndroid Build Coastguard Worker return false;
328*38e8c45fSAndroid Build Coastguard Worker }
329*38e8c45fSAndroid Build Coastguard Worker
330*38e8c45fSAndroid Build Coastguard Worker return true;
331*38e8c45fSAndroid Build Coastguard Worker }
332*38e8c45fSAndroid Build Coastguard Worker
333*38e8c45fSAndroid Build Coastguard Worker } // namespace
334*38e8c45fSAndroid Build Coastguard Worker
getCookieForTracing()335*38e8c45fSAndroid Build Coastguard Worker int64_t TraceCookieCounter::getCookieForTracing() {
336*38e8c45fSAndroid Build Coastguard Worker return ++mTraceCookie;
337*38e8c45fSAndroid Build Coastguard Worker }
338*38e8c45fSAndroid Build Coastguard Worker
SurfaceFrame(const FrameTimelineInfo & frameTimelineInfo,pid_t ownerPid,uid_t ownerUid,int32_t layerId,std::string layerName,std::string debugName,PredictionState predictionState,frametimeline::TimelineItem && predictions,std::shared_ptr<TimeStats> timeStats,JankClassificationThresholds thresholds,TraceCookieCounter * traceCookieCounter,bool isBuffer,GameMode gameMode)339*38e8c45fSAndroid Build Coastguard Worker SurfaceFrame::SurfaceFrame(const FrameTimelineInfo& frameTimelineInfo, pid_t ownerPid,
340*38e8c45fSAndroid Build Coastguard Worker uid_t ownerUid, int32_t layerId, std::string layerName,
341*38e8c45fSAndroid Build Coastguard Worker std::string debugName, PredictionState predictionState,
342*38e8c45fSAndroid Build Coastguard Worker frametimeline::TimelineItem&& predictions,
343*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<TimeStats> timeStats,
344*38e8c45fSAndroid Build Coastguard Worker JankClassificationThresholds thresholds,
345*38e8c45fSAndroid Build Coastguard Worker TraceCookieCounter* traceCookieCounter, bool isBuffer, GameMode gameMode)
346*38e8c45fSAndroid Build Coastguard Worker : mToken(frameTimelineInfo.vsyncId),
347*38e8c45fSAndroid Build Coastguard Worker mInputEventId(frameTimelineInfo.inputEventId),
348*38e8c45fSAndroid Build Coastguard Worker mOwnerPid(ownerPid),
349*38e8c45fSAndroid Build Coastguard Worker mOwnerUid(ownerUid),
350*38e8c45fSAndroid Build Coastguard Worker mLayerName(std::move(layerName)),
351*38e8c45fSAndroid Build Coastguard Worker mDebugName(std::move(debugName)),
352*38e8c45fSAndroid Build Coastguard Worker mLayerId(layerId),
353*38e8c45fSAndroid Build Coastguard Worker mPresentState(PresentState::Unknown),
354*38e8c45fSAndroid Build Coastguard Worker mPredictionState(predictionState),
355*38e8c45fSAndroid Build Coastguard Worker mPredictions(predictions),
356*38e8c45fSAndroid Build Coastguard Worker mActuals({0, 0, 0}),
357*38e8c45fSAndroid Build Coastguard Worker mTimeStats(timeStats),
358*38e8c45fSAndroid Build Coastguard Worker mJankClassificationThresholds(thresholds),
359*38e8c45fSAndroid Build Coastguard Worker mTraceCookieCounter(*traceCookieCounter),
360*38e8c45fSAndroid Build Coastguard Worker mIsBuffer(isBuffer),
361*38e8c45fSAndroid Build Coastguard Worker mGameMode(gameMode) {}
362*38e8c45fSAndroid Build Coastguard Worker
setActualStartTime(nsecs_t actualStartTime)363*38e8c45fSAndroid Build Coastguard Worker void SurfaceFrame::setActualStartTime(nsecs_t actualStartTime) {
364*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock lock(mMutex);
365*38e8c45fSAndroid Build Coastguard Worker mActuals.startTime = actualStartTime;
366*38e8c45fSAndroid Build Coastguard Worker }
367*38e8c45fSAndroid Build Coastguard Worker
setActualQueueTime(nsecs_t actualQueueTime)368*38e8c45fSAndroid Build Coastguard Worker void SurfaceFrame::setActualQueueTime(nsecs_t actualQueueTime) {
369*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock lock(mMutex);
370*38e8c45fSAndroid Build Coastguard Worker mActualQueueTime = actualQueueTime;
371*38e8c45fSAndroid Build Coastguard Worker }
372*38e8c45fSAndroid Build Coastguard Worker
setAcquireFenceTime(nsecs_t acquireFenceTime)373*38e8c45fSAndroid Build Coastguard Worker void SurfaceFrame::setAcquireFenceTime(nsecs_t acquireFenceTime) {
374*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock lock(mMutex);
375*38e8c45fSAndroid Build Coastguard Worker if (CC_UNLIKELY(acquireFenceTime == Fence::SIGNAL_TIME_PENDING)) {
376*38e8c45fSAndroid Build Coastguard Worker mActuals.endTime = mActualQueueTime;
377*38e8c45fSAndroid Build Coastguard Worker } else {
378*38e8c45fSAndroid Build Coastguard Worker mActuals.endTime = std::max(acquireFenceTime, mActualQueueTime);
379*38e8c45fSAndroid Build Coastguard Worker }
380*38e8c45fSAndroid Build Coastguard Worker }
381*38e8c45fSAndroid Build Coastguard Worker
setDesiredPresentTime(nsecs_t desiredPresentTime)382*38e8c45fSAndroid Build Coastguard Worker void SurfaceFrame::setDesiredPresentTime(nsecs_t desiredPresentTime) {
383*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock lock(mMutex);
384*38e8c45fSAndroid Build Coastguard Worker mActuals.desiredPresentTime = desiredPresentTime;
385*38e8c45fSAndroid Build Coastguard Worker }
386*38e8c45fSAndroid Build Coastguard Worker
setDropTime(nsecs_t dropTime)387*38e8c45fSAndroid Build Coastguard Worker void SurfaceFrame::setDropTime(nsecs_t dropTime) {
388*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock lock(mMutex);
389*38e8c45fSAndroid Build Coastguard Worker mDropTime = dropTime;
390*38e8c45fSAndroid Build Coastguard Worker }
391*38e8c45fSAndroid Build Coastguard Worker
setPresentState(PresentState presentState,nsecs_t lastLatchTime)392*38e8c45fSAndroid Build Coastguard Worker void SurfaceFrame::setPresentState(PresentState presentState, nsecs_t lastLatchTime) {
393*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock lock(mMutex);
394*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(mPresentState != PresentState::Unknown,
395*38e8c45fSAndroid Build Coastguard Worker "setPresentState called on a SurfaceFrame from Layer - %s, that has a "
396*38e8c45fSAndroid Build Coastguard Worker "PresentState - %s set already.",
397*38e8c45fSAndroid Build Coastguard Worker mDebugName.c_str(), toString(mPresentState).c_str());
398*38e8c45fSAndroid Build Coastguard Worker mPresentState = presentState;
399*38e8c45fSAndroid Build Coastguard Worker mLastLatchTime = lastLatchTime;
400*38e8c45fSAndroid Build Coastguard Worker }
401*38e8c45fSAndroid Build Coastguard Worker
setRenderRate(Fps renderRate)402*38e8c45fSAndroid Build Coastguard Worker void SurfaceFrame::setRenderRate(Fps renderRate) {
403*38e8c45fSAndroid Build Coastguard Worker std::lock_guard<std::mutex> lock(mMutex);
404*38e8c45fSAndroid Build Coastguard Worker mRenderRate = renderRate;
405*38e8c45fSAndroid Build Coastguard Worker }
406*38e8c45fSAndroid Build Coastguard Worker
getRenderRate() const407*38e8c45fSAndroid Build Coastguard Worker Fps SurfaceFrame::getRenderRate() const {
408*38e8c45fSAndroid Build Coastguard Worker std::lock_guard<std::mutex> lock(mMutex);
409*38e8c45fSAndroid Build Coastguard Worker return mRenderRate ? *mRenderRate : mDisplayFrameRenderRate;
410*38e8c45fSAndroid Build Coastguard Worker }
411*38e8c45fSAndroid Build Coastguard Worker
setGpuComposition()412*38e8c45fSAndroid Build Coastguard Worker void SurfaceFrame::setGpuComposition() {
413*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock lock(mMutex);
414*38e8c45fSAndroid Build Coastguard Worker mGpuComposition = true;
415*38e8c45fSAndroid Build Coastguard Worker }
416*38e8c45fSAndroid Build Coastguard Worker
417*38e8c45fSAndroid Build Coastguard Worker // TODO(b/316171339): migrate from perfetto side
isSelfJanky() const418*38e8c45fSAndroid Build Coastguard Worker bool SurfaceFrame::isSelfJanky() const {
419*38e8c45fSAndroid Build Coastguard Worker int32_t jankType = getJankType().value_or(JankType::None);
420*38e8c45fSAndroid Build Coastguard Worker
421*38e8c45fSAndroid Build Coastguard Worker if (jankType == JankType::None) {
422*38e8c45fSAndroid Build Coastguard Worker return false;
423*38e8c45fSAndroid Build Coastguard Worker }
424*38e8c45fSAndroid Build Coastguard Worker
425*38e8c45fSAndroid Build Coastguard Worker int32_t jankBitmask = JankType::AppDeadlineMissed | JankType::Unknown;
426*38e8c45fSAndroid Build Coastguard Worker if (jankType & jankBitmask) {
427*38e8c45fSAndroid Build Coastguard Worker return true;
428*38e8c45fSAndroid Build Coastguard Worker }
429*38e8c45fSAndroid Build Coastguard Worker
430*38e8c45fSAndroid Build Coastguard Worker return false;
431*38e8c45fSAndroid Build Coastguard Worker }
432*38e8c45fSAndroid Build Coastguard Worker
getJankType() const433*38e8c45fSAndroid Build Coastguard Worker std::optional<int32_t> SurfaceFrame::getJankType() const {
434*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock lock(mMutex);
435*38e8c45fSAndroid Build Coastguard Worker if (mPresentState == PresentState::Dropped) {
436*38e8c45fSAndroid Build Coastguard Worker return JankType::Dropped;
437*38e8c45fSAndroid Build Coastguard Worker }
438*38e8c45fSAndroid Build Coastguard Worker if (mActuals.presentTime == 0) {
439*38e8c45fSAndroid Build Coastguard Worker // Frame hasn't been presented yet.
440*38e8c45fSAndroid Build Coastguard Worker return std::nullopt;
441*38e8c45fSAndroid Build Coastguard Worker }
442*38e8c45fSAndroid Build Coastguard Worker return mJankType;
443*38e8c45fSAndroid Build Coastguard Worker }
444*38e8c45fSAndroid Build Coastguard Worker
getJankSeverityType() const445*38e8c45fSAndroid Build Coastguard Worker std::optional<JankSeverityType> SurfaceFrame::getJankSeverityType() const {
446*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock lock(mMutex);
447*38e8c45fSAndroid Build Coastguard Worker if (mActuals.presentTime == 0) {
448*38e8c45fSAndroid Build Coastguard Worker // Frame hasn't been presented yet.
449*38e8c45fSAndroid Build Coastguard Worker return std::nullopt;
450*38e8c45fSAndroid Build Coastguard Worker }
451*38e8c45fSAndroid Build Coastguard Worker return mJankSeverityType;
452*38e8c45fSAndroid Build Coastguard Worker }
453*38e8c45fSAndroid Build Coastguard Worker
getBaseTime() const454*38e8c45fSAndroid Build Coastguard Worker nsecs_t SurfaceFrame::getBaseTime() const {
455*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock lock(mMutex);
456*38e8c45fSAndroid Build Coastguard Worker return getMinTime(mPredictionState, mPredictions, mActuals);
457*38e8c45fSAndroid Build Coastguard Worker }
458*38e8c45fSAndroid Build Coastguard Worker
getActuals() const459*38e8c45fSAndroid Build Coastguard Worker TimelineItem SurfaceFrame::getActuals() const {
460*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock lock(mMutex);
461*38e8c45fSAndroid Build Coastguard Worker return mActuals;
462*38e8c45fSAndroid Build Coastguard Worker }
463*38e8c45fSAndroid Build Coastguard Worker
getPredictionState() const464*38e8c45fSAndroid Build Coastguard Worker PredictionState SurfaceFrame::getPredictionState() const {
465*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock lock(mMutex);
466*38e8c45fSAndroid Build Coastguard Worker return mPredictionState;
467*38e8c45fSAndroid Build Coastguard Worker }
468*38e8c45fSAndroid Build Coastguard Worker
getPresentState() const469*38e8c45fSAndroid Build Coastguard Worker SurfaceFrame::PresentState SurfaceFrame::getPresentState() const {
470*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock lock(mMutex);
471*38e8c45fSAndroid Build Coastguard Worker return mPresentState;
472*38e8c45fSAndroid Build Coastguard Worker }
473*38e8c45fSAndroid Build Coastguard Worker
getFramePresentMetadata() const474*38e8c45fSAndroid Build Coastguard Worker FramePresentMetadata SurfaceFrame::getFramePresentMetadata() const {
475*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock lock(mMutex);
476*38e8c45fSAndroid Build Coastguard Worker return mFramePresentMetadata;
477*38e8c45fSAndroid Build Coastguard Worker }
478*38e8c45fSAndroid Build Coastguard Worker
getFrameReadyMetadata() const479*38e8c45fSAndroid Build Coastguard Worker FrameReadyMetadata SurfaceFrame::getFrameReadyMetadata() const {
480*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock lock(mMutex);
481*38e8c45fSAndroid Build Coastguard Worker return mFrameReadyMetadata;
482*38e8c45fSAndroid Build Coastguard Worker }
483*38e8c45fSAndroid Build Coastguard Worker
getDropTime() const484*38e8c45fSAndroid Build Coastguard Worker nsecs_t SurfaceFrame::getDropTime() const {
485*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock lock(mMutex);
486*38e8c45fSAndroid Build Coastguard Worker return mDropTime;
487*38e8c45fSAndroid Build Coastguard Worker }
488*38e8c45fSAndroid Build Coastguard Worker
promoteToBuffer()489*38e8c45fSAndroid Build Coastguard Worker void SurfaceFrame::promoteToBuffer() {
490*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock lock(mMutex);
491*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(mIsBuffer == true,
492*38e8c45fSAndroid Build Coastguard Worker "Trying to promote an already promoted BufferSurfaceFrame from layer %s "
493*38e8c45fSAndroid Build Coastguard Worker "with token %" PRId64 "",
494*38e8c45fSAndroid Build Coastguard Worker mDebugName.c_str(), mToken);
495*38e8c45fSAndroid Build Coastguard Worker mIsBuffer = true;
496*38e8c45fSAndroid Build Coastguard Worker }
497*38e8c45fSAndroid Build Coastguard Worker
getIsBuffer() const498*38e8c45fSAndroid Build Coastguard Worker bool SurfaceFrame::getIsBuffer() const {
499*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock lock(mMutex);
500*38e8c45fSAndroid Build Coastguard Worker return mIsBuffer;
501*38e8c45fSAndroid Build Coastguard Worker }
502*38e8c45fSAndroid Build Coastguard Worker
dump(std::string & result,const std::string & indent,nsecs_t baseTime) const503*38e8c45fSAndroid Build Coastguard Worker void SurfaceFrame::dump(std::string& result, const std::string& indent, nsecs_t baseTime) const {
504*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock lock(mMutex);
505*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "%s", indent.c_str());
506*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "Layer - %s", mDebugName.c_str());
507*38e8c45fSAndroid Build Coastguard Worker if (mJankType != JankType::None) {
508*38e8c45fSAndroid Build Coastguard Worker // Easily identify a janky Surface Frame in the dump
509*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, " [*] ");
510*38e8c45fSAndroid Build Coastguard Worker }
511*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "\n");
512*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "%s", indent.c_str());
513*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "Token: %" PRId64 "\n", mToken);
514*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "%s", indent.c_str());
515*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "Is Buffer?: %d\n", mIsBuffer);
516*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "%s", indent.c_str());
517*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "Owner Pid : %d\n", mOwnerPid);
518*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "%s", indent.c_str());
519*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "Scheduled rendering rate: %d fps\n",
520*38e8c45fSAndroid Build Coastguard Worker mRenderRate ? mRenderRate->getIntValue() : 0);
521*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "%s", indent.c_str());
522*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "Layer ID : %d\n", mLayerId);
523*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "%s", indent.c_str());
524*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "Present State : %s\n", toString(mPresentState).c_str());
525*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "%s", indent.c_str());
526*38e8c45fSAndroid Build Coastguard Worker if (mPresentState == PresentState::Dropped) {
527*38e8c45fSAndroid Build Coastguard Worker std::chrono::nanoseconds dropTime(mDropTime - baseTime);
528*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "Drop time : %10f\n",
529*38e8c45fSAndroid Build Coastguard Worker std::chrono::duration<double, std::milli>(dropTime).count());
530*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "%s", indent.c_str());
531*38e8c45fSAndroid Build Coastguard Worker }
532*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "Prediction State : %s\n", toString(mPredictionState).c_str());
533*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "%s", indent.c_str());
534*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "Jank Type : %s\n", jankTypeBitmaskToString(mJankType).c_str());
535*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "%s", indent.c_str());
536*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "Present Metadata : %s\n", toString(mFramePresentMetadata).c_str());
537*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "%s", indent.c_str());
538*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "Finish Metadata: %s\n", toString(mFrameReadyMetadata).c_str());
539*38e8c45fSAndroid Build Coastguard Worker std::chrono::nanoseconds latchTime(
540*38e8c45fSAndroid Build Coastguard Worker std::max(static_cast<int64_t>(0), mLastLatchTime - baseTime));
541*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "%s", indent.c_str());
542*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "Last latch time: %10f\n",
543*38e8c45fSAndroid Build Coastguard Worker std::chrono::duration<double, std::milli>(latchTime).count());
544*38e8c45fSAndroid Build Coastguard Worker if (mPredictionState == PredictionState::Valid) {
545*38e8c45fSAndroid Build Coastguard Worker nsecs_t presentDelta = mActuals.presentTime - mPredictions.presentTime;
546*38e8c45fSAndroid Build Coastguard Worker std::chrono::nanoseconds presentDeltaNs(std::abs(presentDelta));
547*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "%s", indent.c_str());
548*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "Present delta: %10f\n",
549*38e8c45fSAndroid Build Coastguard Worker std::chrono::duration<double, std::milli>(presentDeltaNs).count());
550*38e8c45fSAndroid Build Coastguard Worker }
551*38e8c45fSAndroid Build Coastguard Worker dumpTable(result, mPredictions, mActuals, indent, mPredictionState, baseTime);
552*38e8c45fSAndroid Build Coastguard Worker }
553*38e8c45fSAndroid Build Coastguard Worker
miniDump() const554*38e8c45fSAndroid Build Coastguard Worker std::string SurfaceFrame::miniDump() const {
555*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock lock(mMutex);
556*38e8c45fSAndroid Build Coastguard Worker std::string result;
557*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "Layer - %s\n", mDebugName.c_str());
558*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "Token: %" PRId64 "\n", mToken);
559*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "Is Buffer?: %d\n", mIsBuffer);
560*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "Present State : %s\n", toString(mPresentState).c_str());
561*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "Prediction State : %s\n", toString(mPredictionState).c_str());
562*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "Jank Type : %s\n", jankTypeBitmaskToString(mJankType).c_str());
563*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "Present Metadata : %s\n", toString(mFramePresentMetadata).c_str());
564*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "Finish Metadata: %s\n", toString(mFrameReadyMetadata).c_str());
565*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "Present time: %" PRId64 "", mActuals.presentTime);
566*38e8c45fSAndroid Build Coastguard Worker return result;
567*38e8c45fSAndroid Build Coastguard Worker }
568*38e8c45fSAndroid Build Coastguard Worker
classifyJankLocked(int32_t displayFrameJankType,const Fps & refreshRate,Fps displayFrameRenderRate,nsecs_t * outDeadlineDelta)569*38e8c45fSAndroid Build Coastguard Worker void SurfaceFrame::classifyJankLocked(int32_t displayFrameJankType, const Fps& refreshRate,
570*38e8c45fSAndroid Build Coastguard Worker Fps displayFrameRenderRate, nsecs_t* outDeadlineDelta) {
571*38e8c45fSAndroid Build Coastguard Worker if (mActuals.presentTime == Fence::SIGNAL_TIME_INVALID) {
572*38e8c45fSAndroid Build Coastguard Worker // Cannot do any classification for invalid present time.
573*38e8c45fSAndroid Build Coastguard Worker mJankType = JankType::Unknown;
574*38e8c45fSAndroid Build Coastguard Worker mJankSeverityType = JankSeverityType::Unknown;
575*38e8c45fSAndroid Build Coastguard Worker if (outDeadlineDelta) {
576*38e8c45fSAndroid Build Coastguard Worker *outDeadlineDelta = -1;
577*38e8c45fSAndroid Build Coastguard Worker }
578*38e8c45fSAndroid Build Coastguard Worker return;
579*38e8c45fSAndroid Build Coastguard Worker }
580*38e8c45fSAndroid Build Coastguard Worker
581*38e8c45fSAndroid Build Coastguard Worker if (mPredictionState == PredictionState::Expired) {
582*38e8c45fSAndroid Build Coastguard Worker // We classify prediction expired as AppDeadlineMissed as the
583*38e8c45fSAndroid Build Coastguard Worker // TokenManager::kMaxTokens we store is large enough to account for a
584*38e8c45fSAndroid Build Coastguard Worker // reasonable app, so prediction expire would mean a huge scheduling delay.
585*38e8c45fSAndroid Build Coastguard Worker mJankType = mPresentState != PresentState::Presented ? JankType::Dropped
586*38e8c45fSAndroid Build Coastguard Worker : JankType::AppDeadlineMissed;
587*38e8c45fSAndroid Build Coastguard Worker mJankSeverityType = JankSeverityType::Unknown;
588*38e8c45fSAndroid Build Coastguard Worker if (outDeadlineDelta) {
589*38e8c45fSAndroid Build Coastguard Worker *outDeadlineDelta = -1;
590*38e8c45fSAndroid Build Coastguard Worker }
591*38e8c45fSAndroid Build Coastguard Worker return;
592*38e8c45fSAndroid Build Coastguard Worker }
593*38e8c45fSAndroid Build Coastguard Worker
594*38e8c45fSAndroid Build Coastguard Worker if (mPredictionState == PredictionState::None) {
595*38e8c45fSAndroid Build Coastguard Worker // Cannot do jank classification on frames that don't have a token.
596*38e8c45fSAndroid Build Coastguard Worker return;
597*38e8c45fSAndroid Build Coastguard Worker }
598*38e8c45fSAndroid Build Coastguard Worker
599*38e8c45fSAndroid Build Coastguard Worker const nsecs_t presentDelta = mActuals.presentTime - mPredictions.presentTime;
600*38e8c45fSAndroid Build Coastguard Worker const nsecs_t deltaToVsync = refreshRate.getPeriodNsecs() > 0
601*38e8c45fSAndroid Build Coastguard Worker ? std::abs(presentDelta) % refreshRate.getPeriodNsecs()
602*38e8c45fSAndroid Build Coastguard Worker : 0;
603*38e8c45fSAndroid Build Coastguard Worker const nsecs_t deadlineDelta = mActuals.endTime - mPredictions.endTime;
604*38e8c45fSAndroid Build Coastguard Worker if (outDeadlineDelta) {
605*38e8c45fSAndroid Build Coastguard Worker *outDeadlineDelta = deadlineDelta;
606*38e8c45fSAndroid Build Coastguard Worker }
607*38e8c45fSAndroid Build Coastguard Worker
608*38e8c45fSAndroid Build Coastguard Worker if (deadlineDelta > mJankClassificationThresholds.deadlineThreshold) {
609*38e8c45fSAndroid Build Coastguard Worker mFrameReadyMetadata = FrameReadyMetadata::LateFinish;
610*38e8c45fSAndroid Build Coastguard Worker } else {
611*38e8c45fSAndroid Build Coastguard Worker mFrameReadyMetadata = FrameReadyMetadata::OnTimeFinish;
612*38e8c45fSAndroid Build Coastguard Worker }
613*38e8c45fSAndroid Build Coastguard Worker
614*38e8c45fSAndroid Build Coastguard Worker if (std::abs(presentDelta) > mJankClassificationThresholds.presentThreshold) {
615*38e8c45fSAndroid Build Coastguard Worker mFramePresentMetadata = presentDelta > 0 ? FramePresentMetadata::LatePresent
616*38e8c45fSAndroid Build Coastguard Worker : FramePresentMetadata::EarlyPresent;
617*38e8c45fSAndroid Build Coastguard Worker // Jank that is missing by less than the render rate period is classified as partial jank,
618*38e8c45fSAndroid Build Coastguard Worker // otherwise it is a full jank.
619*38e8c45fSAndroid Build Coastguard Worker mJankSeverityType = std::abs(presentDelta) < displayFrameRenderRate.getPeriodNsecs()
620*38e8c45fSAndroid Build Coastguard Worker ? JankSeverityType::Partial
621*38e8c45fSAndroid Build Coastguard Worker : JankSeverityType::Full;
622*38e8c45fSAndroid Build Coastguard Worker } else {
623*38e8c45fSAndroid Build Coastguard Worker mFramePresentMetadata = FramePresentMetadata::OnTimePresent;
624*38e8c45fSAndroid Build Coastguard Worker }
625*38e8c45fSAndroid Build Coastguard Worker
626*38e8c45fSAndroid Build Coastguard Worker if (mFramePresentMetadata == FramePresentMetadata::OnTimePresent) {
627*38e8c45fSAndroid Build Coastguard Worker // Frames presented on time are not janky.
628*38e8c45fSAndroid Build Coastguard Worker mJankType = JankType::None;
629*38e8c45fSAndroid Build Coastguard Worker } else if (mFramePresentMetadata == FramePresentMetadata::EarlyPresent) {
630*38e8c45fSAndroid Build Coastguard Worker if (mFrameReadyMetadata == FrameReadyMetadata::OnTimeFinish) {
631*38e8c45fSAndroid Build Coastguard Worker // Finish on time, Present early
632*38e8c45fSAndroid Build Coastguard Worker if (deltaToVsync < mJankClassificationThresholds.presentThreshold ||
633*38e8c45fSAndroid Build Coastguard Worker deltaToVsync >= refreshRate.getPeriodNsecs() -
634*38e8c45fSAndroid Build Coastguard Worker mJankClassificationThresholds.presentThreshold) {
635*38e8c45fSAndroid Build Coastguard Worker // Delta factor of vsync
636*38e8c45fSAndroid Build Coastguard Worker mJankType = JankType::SurfaceFlingerScheduling;
637*38e8c45fSAndroid Build Coastguard Worker } else {
638*38e8c45fSAndroid Build Coastguard Worker // Delta not a factor of vsync
639*38e8c45fSAndroid Build Coastguard Worker mJankType = JankType::PredictionError;
640*38e8c45fSAndroid Build Coastguard Worker }
641*38e8c45fSAndroid Build Coastguard Worker } else if (mFrameReadyMetadata == FrameReadyMetadata::LateFinish) {
642*38e8c45fSAndroid Build Coastguard Worker // Finish late, Present early
643*38e8c45fSAndroid Build Coastguard Worker mJankType = JankType::Unknown;
644*38e8c45fSAndroid Build Coastguard Worker }
645*38e8c45fSAndroid Build Coastguard Worker } else {
646*38e8c45fSAndroid Build Coastguard Worker if (mLastLatchTime != 0 && mPredictions.endTime <= mLastLatchTime) {
647*38e8c45fSAndroid Build Coastguard Worker // Buffer Stuffing.
648*38e8c45fSAndroid Build Coastguard Worker mJankType |= JankType::BufferStuffing;
649*38e8c45fSAndroid Build Coastguard Worker // In a stuffed state, the frame could be stuck on a dequeue wait for quite some time.
650*38e8c45fSAndroid Build Coastguard Worker // Because of this dequeue wait, it can be hard to tell if a frame was genuinely late.
651*38e8c45fSAndroid Build Coastguard Worker // We try to do this by moving the deadline. Since the queue could be stuffed by more
652*38e8c45fSAndroid Build Coastguard Worker // than one buffer, we take the last latch time as reference and give one vsync
653*38e8c45fSAndroid Build Coastguard Worker // worth of time for the frame to be ready.
654*38e8c45fSAndroid Build Coastguard Worker nsecs_t adjustedDeadline = mLastLatchTime + refreshRate.getPeriodNsecs();
655*38e8c45fSAndroid Build Coastguard Worker if (adjustedDeadline > mActuals.endTime) {
656*38e8c45fSAndroid Build Coastguard Worker mFrameReadyMetadata = FrameReadyMetadata::OnTimeFinish;
657*38e8c45fSAndroid Build Coastguard Worker } else {
658*38e8c45fSAndroid Build Coastguard Worker mFrameReadyMetadata = FrameReadyMetadata::LateFinish;
659*38e8c45fSAndroid Build Coastguard Worker }
660*38e8c45fSAndroid Build Coastguard Worker }
661*38e8c45fSAndroid Build Coastguard Worker if (mFrameReadyMetadata == FrameReadyMetadata::OnTimeFinish) {
662*38e8c45fSAndroid Build Coastguard Worker // Finish on time, Present late
663*38e8c45fSAndroid Build Coastguard Worker if (displayFrameJankType != JankType::None) {
664*38e8c45fSAndroid Build Coastguard Worker // Propagate displayFrame's jank if it exists
665*38e8c45fSAndroid Build Coastguard Worker mJankType |= displayFrameJankType;
666*38e8c45fSAndroid Build Coastguard Worker } else {
667*38e8c45fSAndroid Build Coastguard Worker if (!(mJankType & JankType::BufferStuffing)) {
668*38e8c45fSAndroid Build Coastguard Worker // In a stuffed state, if the app finishes on time and there is no display frame
669*38e8c45fSAndroid Build Coastguard Worker // jank, only buffer stuffing is the root cause of the jank.
670*38e8c45fSAndroid Build Coastguard Worker if (deltaToVsync < mJankClassificationThresholds.presentThreshold ||
671*38e8c45fSAndroid Build Coastguard Worker deltaToVsync >= refreshRate.getPeriodNsecs() -
672*38e8c45fSAndroid Build Coastguard Worker mJankClassificationThresholds.presentThreshold) {
673*38e8c45fSAndroid Build Coastguard Worker // Delta factor of vsync
674*38e8c45fSAndroid Build Coastguard Worker mJankType |= JankType::SurfaceFlingerScheduling;
675*38e8c45fSAndroid Build Coastguard Worker } else {
676*38e8c45fSAndroid Build Coastguard Worker // Delta not a factor of vsync
677*38e8c45fSAndroid Build Coastguard Worker mJankType |= JankType::PredictionError;
678*38e8c45fSAndroid Build Coastguard Worker }
679*38e8c45fSAndroid Build Coastguard Worker }
680*38e8c45fSAndroid Build Coastguard Worker }
681*38e8c45fSAndroid Build Coastguard Worker } else if (mFrameReadyMetadata == FrameReadyMetadata::LateFinish) {
682*38e8c45fSAndroid Build Coastguard Worker // Finish late, Present late
683*38e8c45fSAndroid Build Coastguard Worker mJankType |= JankType::AppDeadlineMissed;
684*38e8c45fSAndroid Build Coastguard Worker // Propagate DisplayFrame's jankType if it is janky
685*38e8c45fSAndroid Build Coastguard Worker mJankType |= displayFrameJankType;
686*38e8c45fSAndroid Build Coastguard Worker }
687*38e8c45fSAndroid Build Coastguard Worker }
688*38e8c45fSAndroid Build Coastguard Worker if (mPresentState != PresentState::Presented) {
689*38e8c45fSAndroid Build Coastguard Worker mJankType = JankType::Dropped;
690*38e8c45fSAndroid Build Coastguard Worker // Since frame was not presented, lets drop any present value
691*38e8c45fSAndroid Build Coastguard Worker mActuals.presentTime = 0;
692*38e8c45fSAndroid Build Coastguard Worker mJankSeverityType = JankSeverityType::Unknown;
693*38e8c45fSAndroid Build Coastguard Worker }
694*38e8c45fSAndroid Build Coastguard Worker }
695*38e8c45fSAndroid Build Coastguard Worker
onPresent(nsecs_t presentTime,int32_t displayFrameJankType,Fps refreshRate,Fps displayFrameRenderRate,nsecs_t displayDeadlineDelta,nsecs_t displayPresentDelta)696*38e8c45fSAndroid Build Coastguard Worker void SurfaceFrame::onPresent(nsecs_t presentTime, int32_t displayFrameJankType, Fps refreshRate,
697*38e8c45fSAndroid Build Coastguard Worker Fps displayFrameRenderRate, nsecs_t displayDeadlineDelta,
698*38e8c45fSAndroid Build Coastguard Worker nsecs_t displayPresentDelta) {
699*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock lock(mMutex);
700*38e8c45fSAndroid Build Coastguard Worker
701*38e8c45fSAndroid Build Coastguard Worker mDisplayFrameRenderRate = displayFrameRenderRate;
702*38e8c45fSAndroid Build Coastguard Worker mActuals.presentTime = presentTime;
703*38e8c45fSAndroid Build Coastguard Worker nsecs_t deadlineDelta = 0;
704*38e8c45fSAndroid Build Coastguard Worker
705*38e8c45fSAndroid Build Coastguard Worker classifyJankLocked(displayFrameJankType, refreshRate, displayFrameRenderRate, &deadlineDelta);
706*38e8c45fSAndroid Build Coastguard Worker
707*38e8c45fSAndroid Build Coastguard Worker if (mPredictionState != PredictionState::None) {
708*38e8c45fSAndroid Build Coastguard Worker // Only update janky frames if the app used vsync predictions
709*38e8c45fSAndroid Build Coastguard Worker mTimeStats->incrementJankyFrames({refreshRate, mRenderRate, mOwnerUid, mLayerName,
710*38e8c45fSAndroid Build Coastguard Worker mGameMode, mJankType, displayDeadlineDelta,
711*38e8c45fSAndroid Build Coastguard Worker displayPresentDelta, deadlineDelta});
712*38e8c45fSAndroid Build Coastguard Worker
713*38e8c45fSAndroid Build Coastguard Worker gui::JankData jd;
714*38e8c45fSAndroid Build Coastguard Worker jd.frameVsyncId = mToken;
715*38e8c45fSAndroid Build Coastguard Worker jd.jankType = mJankType;
716*38e8c45fSAndroid Build Coastguard Worker jd.frameIntervalNs =
717*38e8c45fSAndroid Build Coastguard Worker (mRenderRate ? *mRenderRate : mDisplayFrameRenderRate).getPeriodNsecs();
718*38e8c45fSAndroid Build Coastguard Worker
719*38e8c45fSAndroid Build Coastguard Worker if (mPredictionState == PredictionState::Valid) {
720*38e8c45fSAndroid Build Coastguard Worker jd.scheduledAppFrameTimeNs = mPredictions.endTime - mPredictions.startTime;
721*38e8c45fSAndroid Build Coastguard Worker
722*38e8c45fSAndroid Build Coastguard Worker // Using expected start, rather than actual, to measure the entire frame time. That is
723*38e8c45fSAndroid Build Coastguard Worker // if the application starts the frame later than scheduled, include that delay in the
724*38e8c45fSAndroid Build Coastguard Worker // frame time, as it usually means main thread being busy with non-rendering work.
725*38e8c45fSAndroid Build Coastguard Worker if (mPresentState == PresentState::Dropped) {
726*38e8c45fSAndroid Build Coastguard Worker jd.actualAppFrameTimeNs = mDropTime - mPredictions.startTime;
727*38e8c45fSAndroid Build Coastguard Worker } else {
728*38e8c45fSAndroid Build Coastguard Worker jd.actualAppFrameTimeNs = mActuals.endTime - mPredictions.startTime;
729*38e8c45fSAndroid Build Coastguard Worker }
730*38e8c45fSAndroid Build Coastguard Worker } else {
731*38e8c45fSAndroid Build Coastguard Worker jd.scheduledAppFrameTimeNs = 0;
732*38e8c45fSAndroid Build Coastguard Worker jd.actualAppFrameTimeNs = 0;
733*38e8c45fSAndroid Build Coastguard Worker }
734*38e8c45fSAndroid Build Coastguard Worker
735*38e8c45fSAndroid Build Coastguard Worker JankTracker::onJankData(mLayerId, jd);
736*38e8c45fSAndroid Build Coastguard Worker }
737*38e8c45fSAndroid Build Coastguard Worker }
738*38e8c45fSAndroid Build Coastguard Worker
onCommitNotComposited(Fps refreshRate,Fps displayFrameRenderRate)739*38e8c45fSAndroid Build Coastguard Worker void SurfaceFrame::onCommitNotComposited(Fps refreshRate, Fps displayFrameRenderRate) {
740*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock lock(mMutex);
741*38e8c45fSAndroid Build Coastguard Worker
742*38e8c45fSAndroid Build Coastguard Worker mDisplayFrameRenderRate = displayFrameRenderRate;
743*38e8c45fSAndroid Build Coastguard Worker mActuals.presentTime = mPredictions.presentTime;
744*38e8c45fSAndroid Build Coastguard Worker classifyJankLocked(JankType::None, refreshRate, displayFrameRenderRate, nullptr);
745*38e8c45fSAndroid Build Coastguard Worker }
746*38e8c45fSAndroid Build Coastguard Worker
tracePredictions(int64_t displayFrameToken,nsecs_t monoBootOffset,bool filterFramesBeforeTraceStarts) const747*38e8c45fSAndroid Build Coastguard Worker void SurfaceFrame::tracePredictions(int64_t displayFrameToken, nsecs_t monoBootOffset,
748*38e8c45fSAndroid Build Coastguard Worker bool filterFramesBeforeTraceStarts) const {
749*38e8c45fSAndroid Build Coastguard Worker int64_t expectedTimelineCookie = mTraceCookieCounter.getCookieForTracing();
750*38e8c45fSAndroid Build Coastguard Worker bool traced = false;
751*38e8c45fSAndroid Build Coastguard Worker
752*38e8c45fSAndroid Build Coastguard Worker // Expected timeline start
753*38e8c45fSAndroid Build Coastguard Worker FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
754*38e8c45fSAndroid Build Coastguard Worker const auto timestamp = mPredictions.startTime;
755*38e8c45fSAndroid Build Coastguard Worker if (filterFramesBeforeTraceStarts && !shouldTraceForDataSource(ctx, timestamp)) {
756*38e8c45fSAndroid Build Coastguard Worker // Do not trace packets started before tracing starts.
757*38e8c45fSAndroid Build Coastguard Worker return;
758*38e8c45fSAndroid Build Coastguard Worker }
759*38e8c45fSAndroid Build Coastguard Worker traced = true;
760*38e8c45fSAndroid Build Coastguard Worker
761*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock lock(mMutex);
762*38e8c45fSAndroid Build Coastguard Worker auto packet = ctx.NewTracePacket();
763*38e8c45fSAndroid Build Coastguard Worker packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
764*38e8c45fSAndroid Build Coastguard Worker packet->set_timestamp(static_cast<uint64_t>(timestamp + monoBootOffset));
765*38e8c45fSAndroid Build Coastguard Worker
766*38e8c45fSAndroid Build Coastguard Worker auto* event = packet->set_frame_timeline_event();
767*38e8c45fSAndroid Build Coastguard Worker auto* expectedSurfaceFrameStartEvent = event->set_expected_surface_frame_start();
768*38e8c45fSAndroid Build Coastguard Worker
769*38e8c45fSAndroid Build Coastguard Worker expectedSurfaceFrameStartEvent->set_cookie(expectedTimelineCookie);
770*38e8c45fSAndroid Build Coastguard Worker
771*38e8c45fSAndroid Build Coastguard Worker expectedSurfaceFrameStartEvent->set_token(mToken);
772*38e8c45fSAndroid Build Coastguard Worker expectedSurfaceFrameStartEvent->set_display_frame_token(displayFrameToken);
773*38e8c45fSAndroid Build Coastguard Worker
774*38e8c45fSAndroid Build Coastguard Worker expectedSurfaceFrameStartEvent->set_pid(mOwnerPid);
775*38e8c45fSAndroid Build Coastguard Worker expectedSurfaceFrameStartEvent->set_layer_name(mDebugName);
776*38e8c45fSAndroid Build Coastguard Worker });
777*38e8c45fSAndroid Build Coastguard Worker
778*38e8c45fSAndroid Build Coastguard Worker if (traced) {
779*38e8c45fSAndroid Build Coastguard Worker // Expected timeline end
780*38e8c45fSAndroid Build Coastguard Worker FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
781*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock lock(mMutex);
782*38e8c45fSAndroid Build Coastguard Worker auto packet = ctx.NewTracePacket();
783*38e8c45fSAndroid Build Coastguard Worker packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
784*38e8c45fSAndroid Build Coastguard Worker packet->set_timestamp(static_cast<uint64_t>(mPredictions.endTime + monoBootOffset));
785*38e8c45fSAndroid Build Coastguard Worker
786*38e8c45fSAndroid Build Coastguard Worker auto* event = packet->set_frame_timeline_event();
787*38e8c45fSAndroid Build Coastguard Worker auto* expectedSurfaceFrameEndEvent = event->set_frame_end();
788*38e8c45fSAndroid Build Coastguard Worker
789*38e8c45fSAndroid Build Coastguard Worker expectedSurfaceFrameEndEvent->set_cookie(expectedTimelineCookie);
790*38e8c45fSAndroid Build Coastguard Worker });
791*38e8c45fSAndroid Build Coastguard Worker }
792*38e8c45fSAndroid Build Coastguard Worker }
793*38e8c45fSAndroid Build Coastguard Worker
traceActuals(int64_t displayFrameToken,nsecs_t monoBootOffset,bool filterFramesBeforeTraceStarts) const794*38e8c45fSAndroid Build Coastguard Worker void SurfaceFrame::traceActuals(int64_t displayFrameToken, nsecs_t monoBootOffset,
795*38e8c45fSAndroid Build Coastguard Worker bool filterFramesBeforeTraceStarts) const {
796*38e8c45fSAndroid Build Coastguard Worker int64_t actualTimelineCookie = mTraceCookieCounter.getCookieForTracing();
797*38e8c45fSAndroid Build Coastguard Worker bool traced = false;
798*38e8c45fSAndroid Build Coastguard Worker
799*38e8c45fSAndroid Build Coastguard Worker // Actual timeline start
800*38e8c45fSAndroid Build Coastguard Worker FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
801*38e8c45fSAndroid Build Coastguard Worker const auto timestamp = [&]() {
802*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock lock(mMutex);
803*38e8c45fSAndroid Build Coastguard Worker // Actual start time is not yet available, so use expected start instead
804*38e8c45fSAndroid Build Coastguard Worker if (mPredictionState == PredictionState::Expired) {
805*38e8c45fSAndroid Build Coastguard Worker // If prediction is expired, we can't use the predicted start time. Instead, just
806*38e8c45fSAndroid Build Coastguard Worker // use a start time a little earlier than the end time so that we have some info
807*38e8c45fSAndroid Build Coastguard Worker // about this frame in the trace.
808*38e8c45fSAndroid Build Coastguard Worker nsecs_t endTime =
809*38e8c45fSAndroid Build Coastguard Worker (mPresentState == PresentState::Dropped ? mDropTime : mActuals.endTime);
810*38e8c45fSAndroid Build Coastguard Worker return endTime - kPredictionExpiredStartTimeDelta;
811*38e8c45fSAndroid Build Coastguard Worker }
812*38e8c45fSAndroid Build Coastguard Worker
813*38e8c45fSAndroid Build Coastguard Worker return mActuals.startTime == 0 ? mPredictions.startTime : mActuals.startTime;
814*38e8c45fSAndroid Build Coastguard Worker }();
815*38e8c45fSAndroid Build Coastguard Worker
816*38e8c45fSAndroid Build Coastguard Worker if (filterFramesBeforeTraceStarts && !shouldTraceForDataSource(ctx, timestamp)) {
817*38e8c45fSAndroid Build Coastguard Worker // Do not trace packets started before tracing starts.
818*38e8c45fSAndroid Build Coastguard Worker return;
819*38e8c45fSAndroid Build Coastguard Worker }
820*38e8c45fSAndroid Build Coastguard Worker traced = true;
821*38e8c45fSAndroid Build Coastguard Worker
822*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock lock(mMutex);
823*38e8c45fSAndroid Build Coastguard Worker auto packet = ctx.NewTracePacket();
824*38e8c45fSAndroid Build Coastguard Worker packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
825*38e8c45fSAndroid Build Coastguard Worker packet->set_timestamp(static_cast<uint64_t>(timestamp + monoBootOffset));
826*38e8c45fSAndroid Build Coastguard Worker
827*38e8c45fSAndroid Build Coastguard Worker auto* event = packet->set_frame_timeline_event();
828*38e8c45fSAndroid Build Coastguard Worker auto* actualSurfaceFrameStartEvent = event->set_actual_surface_frame_start();
829*38e8c45fSAndroid Build Coastguard Worker
830*38e8c45fSAndroid Build Coastguard Worker actualSurfaceFrameStartEvent->set_cookie(actualTimelineCookie);
831*38e8c45fSAndroid Build Coastguard Worker
832*38e8c45fSAndroid Build Coastguard Worker actualSurfaceFrameStartEvent->set_token(mToken);
833*38e8c45fSAndroid Build Coastguard Worker actualSurfaceFrameStartEvent->set_display_frame_token(displayFrameToken);
834*38e8c45fSAndroid Build Coastguard Worker
835*38e8c45fSAndroid Build Coastguard Worker actualSurfaceFrameStartEvent->set_pid(mOwnerPid);
836*38e8c45fSAndroid Build Coastguard Worker actualSurfaceFrameStartEvent->set_layer_name(mDebugName);
837*38e8c45fSAndroid Build Coastguard Worker
838*38e8c45fSAndroid Build Coastguard Worker if (mPresentState == PresentState::Dropped) {
839*38e8c45fSAndroid Build Coastguard Worker actualSurfaceFrameStartEvent->set_present_type(FrameTimelineEvent::PRESENT_DROPPED);
840*38e8c45fSAndroid Build Coastguard Worker } else if (mPresentState == PresentState::Unknown) {
841*38e8c45fSAndroid Build Coastguard Worker actualSurfaceFrameStartEvent->set_present_type(FrameTimelineEvent::PRESENT_UNSPECIFIED);
842*38e8c45fSAndroid Build Coastguard Worker } else {
843*38e8c45fSAndroid Build Coastguard Worker actualSurfaceFrameStartEvent->set_present_type(toProto(mFramePresentMetadata));
844*38e8c45fSAndroid Build Coastguard Worker }
845*38e8c45fSAndroid Build Coastguard Worker actualSurfaceFrameStartEvent->set_on_time_finish(mFrameReadyMetadata ==
846*38e8c45fSAndroid Build Coastguard Worker FrameReadyMetadata::OnTimeFinish);
847*38e8c45fSAndroid Build Coastguard Worker actualSurfaceFrameStartEvent->set_gpu_composition(mGpuComposition);
848*38e8c45fSAndroid Build Coastguard Worker actualSurfaceFrameStartEvent->set_jank_type(jankTypeBitmaskToProto(mJankType));
849*38e8c45fSAndroid Build Coastguard Worker actualSurfaceFrameStartEvent->set_prediction_type(toProto(mPredictionState));
850*38e8c45fSAndroid Build Coastguard Worker actualSurfaceFrameStartEvent->set_is_buffer(mIsBuffer);
851*38e8c45fSAndroid Build Coastguard Worker actualSurfaceFrameStartEvent->set_jank_severity_type(toProto(mJankSeverityType));
852*38e8c45fSAndroid Build Coastguard Worker });
853*38e8c45fSAndroid Build Coastguard Worker
854*38e8c45fSAndroid Build Coastguard Worker if (traced) {
855*38e8c45fSAndroid Build Coastguard Worker // Actual timeline end
856*38e8c45fSAndroid Build Coastguard Worker FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
857*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock lock(mMutex);
858*38e8c45fSAndroid Build Coastguard Worker auto packet = ctx.NewTracePacket();
859*38e8c45fSAndroid Build Coastguard Worker packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
860*38e8c45fSAndroid Build Coastguard Worker if (mPresentState == PresentState::Dropped) {
861*38e8c45fSAndroid Build Coastguard Worker packet->set_timestamp(static_cast<uint64_t>(mDropTime + monoBootOffset));
862*38e8c45fSAndroid Build Coastguard Worker } else {
863*38e8c45fSAndroid Build Coastguard Worker packet->set_timestamp(static_cast<uint64_t>(mActuals.endTime + monoBootOffset));
864*38e8c45fSAndroid Build Coastguard Worker }
865*38e8c45fSAndroid Build Coastguard Worker
866*38e8c45fSAndroid Build Coastguard Worker auto* event = packet->set_frame_timeline_event();
867*38e8c45fSAndroid Build Coastguard Worker auto* actualSurfaceFrameEndEvent = event->set_frame_end();
868*38e8c45fSAndroid Build Coastguard Worker
869*38e8c45fSAndroid Build Coastguard Worker actualSurfaceFrameEndEvent->set_cookie(actualTimelineCookie);
870*38e8c45fSAndroid Build Coastguard Worker });
871*38e8c45fSAndroid Build Coastguard Worker }
872*38e8c45fSAndroid Build Coastguard Worker }
873*38e8c45fSAndroid Build Coastguard Worker
874*38e8c45fSAndroid Build Coastguard Worker /**
875*38e8c45fSAndroid Build Coastguard Worker * TODO(b/178637512): add inputEventId to the perfetto trace.
876*38e8c45fSAndroid Build Coastguard Worker */
trace(int64_t displayFrameToken,nsecs_t monoBootOffset,bool filterFramesBeforeTraceStarts) const877*38e8c45fSAndroid Build Coastguard Worker void SurfaceFrame::trace(int64_t displayFrameToken, nsecs_t monoBootOffset,
878*38e8c45fSAndroid Build Coastguard Worker bool filterFramesBeforeTraceStarts) const {
879*38e8c45fSAndroid Build Coastguard Worker if (mToken == FrameTimelineInfo::INVALID_VSYNC_ID ||
880*38e8c45fSAndroid Build Coastguard Worker displayFrameToken == FrameTimelineInfo::INVALID_VSYNC_ID) {
881*38e8c45fSAndroid Build Coastguard Worker // No packets can be traced with a missing token.
882*38e8c45fSAndroid Build Coastguard Worker return;
883*38e8c45fSAndroid Build Coastguard Worker }
884*38e8c45fSAndroid Build Coastguard Worker if (getPredictionState() != PredictionState::Expired) {
885*38e8c45fSAndroid Build Coastguard Worker // Expired predictions have zeroed timestamps. This cannot be used in any meaningful way in
886*38e8c45fSAndroid Build Coastguard Worker // a trace.
887*38e8c45fSAndroid Build Coastguard Worker tracePredictions(displayFrameToken, monoBootOffset, filterFramesBeforeTraceStarts);
888*38e8c45fSAndroid Build Coastguard Worker }
889*38e8c45fSAndroid Build Coastguard Worker traceActuals(displayFrameToken, monoBootOffset, filterFramesBeforeTraceStarts);
890*38e8c45fSAndroid Build Coastguard Worker }
891*38e8c45fSAndroid Build Coastguard Worker
892*38e8c45fSAndroid Build Coastguard Worker namespace impl {
893*38e8c45fSAndroid Build Coastguard Worker
generateTokenForPredictions(TimelineItem && predictions)894*38e8c45fSAndroid Build Coastguard Worker int64_t TokenManager::generateTokenForPredictions(TimelineItem&& predictions) {
895*38e8c45fSAndroid Build Coastguard Worker SFTRACE_CALL();
896*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock lock(mMutex);
897*38e8c45fSAndroid Build Coastguard Worker while (mPredictions.size() >= kMaxTokens) {
898*38e8c45fSAndroid Build Coastguard Worker mPredictions.erase(mPredictions.begin());
899*38e8c45fSAndroid Build Coastguard Worker }
900*38e8c45fSAndroid Build Coastguard Worker const int64_t assignedToken = mCurrentToken++;
901*38e8c45fSAndroid Build Coastguard Worker mPredictions[assignedToken] = predictions;
902*38e8c45fSAndroid Build Coastguard Worker return assignedToken;
903*38e8c45fSAndroid Build Coastguard Worker }
904*38e8c45fSAndroid Build Coastguard Worker
getPredictionsForToken(int64_t token) const905*38e8c45fSAndroid Build Coastguard Worker std::optional<TimelineItem> TokenManager::getPredictionsForToken(int64_t token) const {
906*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock lock(mMutex);
907*38e8c45fSAndroid Build Coastguard Worker auto predictionsIterator = mPredictions.find(token);
908*38e8c45fSAndroid Build Coastguard Worker if (predictionsIterator != mPredictions.end()) {
909*38e8c45fSAndroid Build Coastguard Worker return predictionsIterator->second;
910*38e8c45fSAndroid Build Coastguard Worker }
911*38e8c45fSAndroid Build Coastguard Worker return {};
912*38e8c45fSAndroid Build Coastguard Worker }
913*38e8c45fSAndroid Build Coastguard Worker
FrameTimeline(std::shared_ptr<TimeStats> timeStats,pid_t surfaceFlingerPid,JankClassificationThresholds thresholds,bool useBootTimeClock,bool filterFramesBeforeTraceStarts)914*38e8c45fSAndroid Build Coastguard Worker FrameTimeline::FrameTimeline(std::shared_ptr<TimeStats> timeStats, pid_t surfaceFlingerPid,
915*38e8c45fSAndroid Build Coastguard Worker JankClassificationThresholds thresholds, bool useBootTimeClock,
916*38e8c45fSAndroid Build Coastguard Worker bool filterFramesBeforeTraceStarts)
917*38e8c45fSAndroid Build Coastguard Worker : mUseBootTimeClock(useBootTimeClock),
918*38e8c45fSAndroid Build Coastguard Worker mFilterFramesBeforeTraceStarts(
919*38e8c45fSAndroid Build Coastguard Worker FlagManager::getInstance().filter_frames_before_trace_starts() &&
920*38e8c45fSAndroid Build Coastguard Worker filterFramesBeforeTraceStarts),
921*38e8c45fSAndroid Build Coastguard Worker mMaxDisplayFrames(kDefaultMaxDisplayFrames),
922*38e8c45fSAndroid Build Coastguard Worker mTimeStats(std::move(timeStats)),
923*38e8c45fSAndroid Build Coastguard Worker mSurfaceFlingerPid(surfaceFlingerPid),
924*38e8c45fSAndroid Build Coastguard Worker mJankClassificationThresholds(thresholds) {
925*38e8c45fSAndroid Build Coastguard Worker mCurrentDisplayFrame =
926*38e8c45fSAndroid Build Coastguard Worker std::make_shared<DisplayFrame>(mTimeStats, thresholds, &mTraceCookieCounter);
927*38e8c45fSAndroid Build Coastguard Worker }
928*38e8c45fSAndroid Build Coastguard Worker
onBootFinished()929*38e8c45fSAndroid Build Coastguard Worker void FrameTimeline::onBootFinished() {
930*38e8c45fSAndroid Build Coastguard Worker perfetto::TracingInitArgs args;
931*38e8c45fSAndroid Build Coastguard Worker args.backends = perfetto::kSystemBackend;
932*38e8c45fSAndroid Build Coastguard Worker perfetto::Tracing::Initialize(args);
933*38e8c45fSAndroid Build Coastguard Worker registerDataSource();
934*38e8c45fSAndroid Build Coastguard Worker }
935*38e8c45fSAndroid Build Coastguard Worker
registerDataSource()936*38e8c45fSAndroid Build Coastguard Worker void FrameTimeline::registerDataSource() {
937*38e8c45fSAndroid Build Coastguard Worker perfetto::DataSourceDescriptor dsd;
938*38e8c45fSAndroid Build Coastguard Worker dsd.set_name(kFrameTimelineDataSource);
939*38e8c45fSAndroid Build Coastguard Worker FrameTimelineDataSource::Register(dsd);
940*38e8c45fSAndroid Build Coastguard Worker }
941*38e8c45fSAndroid Build Coastguard Worker
createSurfaceFrameForToken(const FrameTimelineInfo & frameTimelineInfo,pid_t ownerPid,uid_t ownerUid,int32_t layerId,std::string layerName,std::string debugName,bool isBuffer,GameMode gameMode)942*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<SurfaceFrame> FrameTimeline::createSurfaceFrameForToken(
943*38e8c45fSAndroid Build Coastguard Worker const FrameTimelineInfo& frameTimelineInfo, pid_t ownerPid, uid_t ownerUid, int32_t layerId,
944*38e8c45fSAndroid Build Coastguard Worker std::string layerName, std::string debugName, bool isBuffer, GameMode gameMode) {
945*38e8c45fSAndroid Build Coastguard Worker SFTRACE_CALL();
946*38e8c45fSAndroid Build Coastguard Worker if (frameTimelineInfo.vsyncId == FrameTimelineInfo::INVALID_VSYNC_ID) {
947*38e8c45fSAndroid Build Coastguard Worker return std::make_shared<SurfaceFrame>(frameTimelineInfo, ownerPid, ownerUid, layerId,
948*38e8c45fSAndroid Build Coastguard Worker std::move(layerName), std::move(debugName),
949*38e8c45fSAndroid Build Coastguard Worker PredictionState::None, TimelineItem(), mTimeStats,
950*38e8c45fSAndroid Build Coastguard Worker mJankClassificationThresholds, &mTraceCookieCounter,
951*38e8c45fSAndroid Build Coastguard Worker isBuffer, gameMode);
952*38e8c45fSAndroid Build Coastguard Worker }
953*38e8c45fSAndroid Build Coastguard Worker std::optional<TimelineItem> predictions =
954*38e8c45fSAndroid Build Coastguard Worker mTokenManager.getPredictionsForToken(frameTimelineInfo.vsyncId);
955*38e8c45fSAndroid Build Coastguard Worker if (predictions) {
956*38e8c45fSAndroid Build Coastguard Worker return std::make_shared<SurfaceFrame>(frameTimelineInfo, ownerPid, ownerUid, layerId,
957*38e8c45fSAndroid Build Coastguard Worker std::move(layerName), std::move(debugName),
958*38e8c45fSAndroid Build Coastguard Worker PredictionState::Valid, std::move(*predictions),
959*38e8c45fSAndroid Build Coastguard Worker mTimeStats, mJankClassificationThresholds,
960*38e8c45fSAndroid Build Coastguard Worker &mTraceCookieCounter, isBuffer, gameMode);
961*38e8c45fSAndroid Build Coastguard Worker }
962*38e8c45fSAndroid Build Coastguard Worker return std::make_shared<SurfaceFrame>(frameTimelineInfo, ownerPid, ownerUid, layerId,
963*38e8c45fSAndroid Build Coastguard Worker std::move(layerName), std::move(debugName),
964*38e8c45fSAndroid Build Coastguard Worker PredictionState::Expired, TimelineItem(), mTimeStats,
965*38e8c45fSAndroid Build Coastguard Worker mJankClassificationThresholds, &mTraceCookieCounter,
966*38e8c45fSAndroid Build Coastguard Worker isBuffer, gameMode);
967*38e8c45fSAndroid Build Coastguard Worker }
968*38e8c45fSAndroid Build Coastguard Worker
DisplayFrame(std::shared_ptr<TimeStats> timeStats,JankClassificationThresholds thresholds,TraceCookieCounter * traceCookieCounter)969*38e8c45fSAndroid Build Coastguard Worker FrameTimeline::DisplayFrame::DisplayFrame(std::shared_ptr<TimeStats> timeStats,
970*38e8c45fSAndroid Build Coastguard Worker JankClassificationThresholds thresholds,
971*38e8c45fSAndroid Build Coastguard Worker TraceCookieCounter* traceCookieCounter)
972*38e8c45fSAndroid Build Coastguard Worker : mSurfaceFlingerPredictions(TimelineItem()),
973*38e8c45fSAndroid Build Coastguard Worker mSurfaceFlingerActuals(TimelineItem()),
974*38e8c45fSAndroid Build Coastguard Worker mTimeStats(timeStats),
975*38e8c45fSAndroid Build Coastguard Worker mJankClassificationThresholds(thresholds),
976*38e8c45fSAndroid Build Coastguard Worker mTraceCookieCounter(*traceCookieCounter) {
977*38e8c45fSAndroid Build Coastguard Worker mSurfaceFrames.reserve(kNumSurfaceFramesInitial);
978*38e8c45fSAndroid Build Coastguard Worker }
979*38e8c45fSAndroid Build Coastguard Worker
addSurfaceFrame(std::shared_ptr<SurfaceFrame> surfaceFrame)980*38e8c45fSAndroid Build Coastguard Worker void FrameTimeline::addSurfaceFrame(std::shared_ptr<SurfaceFrame> surfaceFrame) {
981*38e8c45fSAndroid Build Coastguard Worker SFTRACE_CALL();
982*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock lock(mMutex);
983*38e8c45fSAndroid Build Coastguard Worker mCurrentDisplayFrame->addSurfaceFrame(surfaceFrame);
984*38e8c45fSAndroid Build Coastguard Worker }
985*38e8c45fSAndroid Build Coastguard Worker
setSfWakeUp(int64_t token,nsecs_t wakeUpTime,Fps refreshRate,Fps renderRate)986*38e8c45fSAndroid Build Coastguard Worker void FrameTimeline::setSfWakeUp(int64_t token, nsecs_t wakeUpTime, Fps refreshRate,
987*38e8c45fSAndroid Build Coastguard Worker Fps renderRate) {
988*38e8c45fSAndroid Build Coastguard Worker SFTRACE_CALL();
989*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock lock(mMutex);
990*38e8c45fSAndroid Build Coastguard Worker mCurrentDisplayFrame->onSfWakeUp(token, refreshRate, renderRate,
991*38e8c45fSAndroid Build Coastguard Worker mTokenManager.getPredictionsForToken(token), wakeUpTime);
992*38e8c45fSAndroid Build Coastguard Worker }
993*38e8c45fSAndroid Build Coastguard Worker
setSfPresent(nsecs_t sfPresentTime,const std::shared_ptr<FenceTime> & presentFence,const std::shared_ptr<FenceTime> & gpuFence)994*38e8c45fSAndroid Build Coastguard Worker void FrameTimeline::setSfPresent(nsecs_t sfPresentTime,
995*38e8c45fSAndroid Build Coastguard Worker const std::shared_ptr<FenceTime>& presentFence,
996*38e8c45fSAndroid Build Coastguard Worker const std::shared_ptr<FenceTime>& gpuFence) {
997*38e8c45fSAndroid Build Coastguard Worker SFTRACE_CALL();
998*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock lock(mMutex);
999*38e8c45fSAndroid Build Coastguard Worker mCurrentDisplayFrame->setActualEndTime(sfPresentTime);
1000*38e8c45fSAndroid Build Coastguard Worker mCurrentDisplayFrame->setGpuFence(gpuFence);
1001*38e8c45fSAndroid Build Coastguard Worker mPendingPresentFences.emplace_back(std::make_pair(presentFence, mCurrentDisplayFrame));
1002*38e8c45fSAndroid Build Coastguard Worker flushPendingPresentFences();
1003*38e8c45fSAndroid Build Coastguard Worker finalizeCurrentDisplayFrame();
1004*38e8c45fSAndroid Build Coastguard Worker }
1005*38e8c45fSAndroid Build Coastguard Worker
getPresentFrames() const1006*38e8c45fSAndroid Build Coastguard Worker const std::vector<std::shared_ptr<frametimeline::SurfaceFrame>>& FrameTimeline::getPresentFrames()
1007*38e8c45fSAndroid Build Coastguard Worker const {
1008*38e8c45fSAndroid Build Coastguard Worker return mPresentFrames;
1009*38e8c45fSAndroid Build Coastguard Worker }
1010*38e8c45fSAndroid Build Coastguard Worker
onCommitNotComposited()1011*38e8c45fSAndroid Build Coastguard Worker void FrameTimeline::onCommitNotComposited() {
1012*38e8c45fSAndroid Build Coastguard Worker SFTRACE_CALL();
1013*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock lock(mMutex);
1014*38e8c45fSAndroid Build Coastguard Worker mCurrentDisplayFrame->onCommitNotComposited();
1015*38e8c45fSAndroid Build Coastguard Worker mCurrentDisplayFrame.reset();
1016*38e8c45fSAndroid Build Coastguard Worker mCurrentDisplayFrame = std::make_shared<DisplayFrame>(mTimeStats, mJankClassificationThresholds,
1017*38e8c45fSAndroid Build Coastguard Worker &mTraceCookieCounter);
1018*38e8c45fSAndroid Build Coastguard Worker }
1019*38e8c45fSAndroid Build Coastguard Worker
addSurfaceFrame(std::shared_ptr<SurfaceFrame> surfaceFrame)1020*38e8c45fSAndroid Build Coastguard Worker void FrameTimeline::DisplayFrame::addSurfaceFrame(std::shared_ptr<SurfaceFrame> surfaceFrame) {
1021*38e8c45fSAndroid Build Coastguard Worker mSurfaceFrames.push_back(surfaceFrame);
1022*38e8c45fSAndroid Build Coastguard Worker }
1023*38e8c45fSAndroid Build Coastguard Worker
onSfWakeUp(int64_t token,Fps refreshRate,Fps renderRate,std::optional<TimelineItem> predictions,nsecs_t wakeUpTime)1024*38e8c45fSAndroid Build Coastguard Worker void FrameTimeline::DisplayFrame::onSfWakeUp(int64_t token, Fps refreshRate, Fps renderRate,
1025*38e8c45fSAndroid Build Coastguard Worker std::optional<TimelineItem> predictions,
1026*38e8c45fSAndroid Build Coastguard Worker nsecs_t wakeUpTime) {
1027*38e8c45fSAndroid Build Coastguard Worker mToken = token;
1028*38e8c45fSAndroid Build Coastguard Worker mRefreshRate = refreshRate;
1029*38e8c45fSAndroid Build Coastguard Worker mRenderRate = renderRate;
1030*38e8c45fSAndroid Build Coastguard Worker if (!predictions) {
1031*38e8c45fSAndroid Build Coastguard Worker mPredictionState = PredictionState::Expired;
1032*38e8c45fSAndroid Build Coastguard Worker } else {
1033*38e8c45fSAndroid Build Coastguard Worker mPredictionState = PredictionState::Valid;
1034*38e8c45fSAndroid Build Coastguard Worker mSurfaceFlingerPredictions = *predictions;
1035*38e8c45fSAndroid Build Coastguard Worker }
1036*38e8c45fSAndroid Build Coastguard Worker mSurfaceFlingerActuals.startTime = wakeUpTime;
1037*38e8c45fSAndroid Build Coastguard Worker }
1038*38e8c45fSAndroid Build Coastguard Worker
setPredictions(PredictionState predictionState,TimelineItem predictions)1039*38e8c45fSAndroid Build Coastguard Worker void FrameTimeline::DisplayFrame::setPredictions(PredictionState predictionState,
1040*38e8c45fSAndroid Build Coastguard Worker TimelineItem predictions) {
1041*38e8c45fSAndroid Build Coastguard Worker mPredictionState = predictionState;
1042*38e8c45fSAndroid Build Coastguard Worker mSurfaceFlingerPredictions = predictions;
1043*38e8c45fSAndroid Build Coastguard Worker }
1044*38e8c45fSAndroid Build Coastguard Worker
setActualStartTime(nsecs_t actualStartTime)1045*38e8c45fSAndroid Build Coastguard Worker void FrameTimeline::DisplayFrame::setActualStartTime(nsecs_t actualStartTime) {
1046*38e8c45fSAndroid Build Coastguard Worker mSurfaceFlingerActuals.startTime = actualStartTime;
1047*38e8c45fSAndroid Build Coastguard Worker }
1048*38e8c45fSAndroid Build Coastguard Worker
setActualEndTime(nsecs_t actualEndTime)1049*38e8c45fSAndroid Build Coastguard Worker void FrameTimeline::DisplayFrame::setActualEndTime(nsecs_t actualEndTime) {
1050*38e8c45fSAndroid Build Coastguard Worker mSurfaceFlingerActuals.endTime = actualEndTime;
1051*38e8c45fSAndroid Build Coastguard Worker }
1052*38e8c45fSAndroid Build Coastguard Worker
setGpuFence(const std::shared_ptr<FenceTime> & gpuFence)1053*38e8c45fSAndroid Build Coastguard Worker void FrameTimeline::DisplayFrame::setGpuFence(const std::shared_ptr<FenceTime>& gpuFence) {
1054*38e8c45fSAndroid Build Coastguard Worker mGpuFence = gpuFence;
1055*38e8c45fSAndroid Build Coastguard Worker }
1056*38e8c45fSAndroid Build Coastguard Worker
classifyJank(nsecs_t & deadlineDelta,nsecs_t & deltaToVsync,nsecs_t previousPresentTime)1057*38e8c45fSAndroid Build Coastguard Worker void FrameTimeline::DisplayFrame::classifyJank(nsecs_t& deadlineDelta, nsecs_t& deltaToVsync,
1058*38e8c45fSAndroid Build Coastguard Worker nsecs_t previousPresentTime) {
1059*38e8c45fSAndroid Build Coastguard Worker const bool presentTimeValid =
1060*38e8c45fSAndroid Build Coastguard Worker mSurfaceFlingerActuals.presentTime >= mSurfaceFlingerActuals.startTime;
1061*38e8c45fSAndroid Build Coastguard Worker if (mPredictionState == PredictionState::Expired || !presentTimeValid) {
1062*38e8c45fSAndroid Build Coastguard Worker // Cannot do jank classification with expired predictions or invalid signal times. Set the
1063*38e8c45fSAndroid Build Coastguard Worker // deltas to 0 as both negative and positive deltas are used as real values.
1064*38e8c45fSAndroid Build Coastguard Worker mJankType = JankType::Unknown;
1065*38e8c45fSAndroid Build Coastguard Worker mJankSeverityType = JankSeverityType::Unknown;
1066*38e8c45fSAndroid Build Coastguard Worker deadlineDelta = 0;
1067*38e8c45fSAndroid Build Coastguard Worker deltaToVsync = 0;
1068*38e8c45fSAndroid Build Coastguard Worker if (!presentTimeValid) {
1069*38e8c45fSAndroid Build Coastguard Worker mSurfaceFlingerActuals.presentTime = mSurfaceFlingerActuals.endTime;
1070*38e8c45fSAndroid Build Coastguard Worker mJankType |= JankType::DisplayHAL;
1071*38e8c45fSAndroid Build Coastguard Worker }
1072*38e8c45fSAndroid Build Coastguard Worker
1073*38e8c45fSAndroid Build Coastguard Worker return;
1074*38e8c45fSAndroid Build Coastguard Worker }
1075*38e8c45fSAndroid Build Coastguard Worker
1076*38e8c45fSAndroid Build Coastguard Worker // Delta between the expected present and the actual present
1077*38e8c45fSAndroid Build Coastguard Worker const nsecs_t presentDelta =
1078*38e8c45fSAndroid Build Coastguard Worker mSurfaceFlingerActuals.presentTime - mSurfaceFlingerPredictions.presentTime;
1079*38e8c45fSAndroid Build Coastguard Worker // Sf actual end time represents the CPU end time. In case of HWC, SF's end time would have
1080*38e8c45fSAndroid Build Coastguard Worker // included the time for composition. However, for GPU composition, the final end time is max(sf
1081*38e8c45fSAndroid Build Coastguard Worker // end time, gpu fence time).
1082*38e8c45fSAndroid Build Coastguard Worker nsecs_t combinedEndTime = mSurfaceFlingerActuals.endTime;
1083*38e8c45fSAndroid Build Coastguard Worker if (mGpuFence != FenceTime::NO_FENCE) {
1084*38e8c45fSAndroid Build Coastguard Worker combinedEndTime = std::max(combinedEndTime, mGpuFence->getSignalTime());
1085*38e8c45fSAndroid Build Coastguard Worker }
1086*38e8c45fSAndroid Build Coastguard Worker deadlineDelta = combinedEndTime - mSurfaceFlingerPredictions.endTime;
1087*38e8c45fSAndroid Build Coastguard Worker
1088*38e8c45fSAndroid Build Coastguard Worker // How far off was the presentDelta when compared to the vsyncPeriod. Used in checking if there
1089*38e8c45fSAndroid Build Coastguard Worker // was a prediction error or not.
1090*38e8c45fSAndroid Build Coastguard Worker deltaToVsync = mRefreshRate.getPeriodNsecs() > 0
1091*38e8c45fSAndroid Build Coastguard Worker ? std::abs(presentDelta) % mRefreshRate.getPeriodNsecs()
1092*38e8c45fSAndroid Build Coastguard Worker : 0;
1093*38e8c45fSAndroid Build Coastguard Worker
1094*38e8c45fSAndroid Build Coastguard Worker if (std::abs(presentDelta) > mJankClassificationThresholds.presentThreshold) {
1095*38e8c45fSAndroid Build Coastguard Worker mFramePresentMetadata = presentDelta > 0 ? FramePresentMetadata::LatePresent
1096*38e8c45fSAndroid Build Coastguard Worker : FramePresentMetadata::EarlyPresent;
1097*38e8c45fSAndroid Build Coastguard Worker // Jank that is missing by less than the render rate period is classified as partial jank,
1098*38e8c45fSAndroid Build Coastguard Worker // otherwise it is a full jank.
1099*38e8c45fSAndroid Build Coastguard Worker mJankSeverityType = std::abs(presentDelta) < mRenderRate.getPeriodNsecs()
1100*38e8c45fSAndroid Build Coastguard Worker ? JankSeverityType::Partial
1101*38e8c45fSAndroid Build Coastguard Worker : JankSeverityType::Full;
1102*38e8c45fSAndroid Build Coastguard Worker } else {
1103*38e8c45fSAndroid Build Coastguard Worker mFramePresentMetadata = FramePresentMetadata::OnTimePresent;
1104*38e8c45fSAndroid Build Coastguard Worker }
1105*38e8c45fSAndroid Build Coastguard Worker
1106*38e8c45fSAndroid Build Coastguard Worker if (combinedEndTime > mSurfaceFlingerPredictions.endTime) {
1107*38e8c45fSAndroid Build Coastguard Worker mFrameReadyMetadata = FrameReadyMetadata::LateFinish;
1108*38e8c45fSAndroid Build Coastguard Worker } else {
1109*38e8c45fSAndroid Build Coastguard Worker mFrameReadyMetadata = FrameReadyMetadata::OnTimeFinish;
1110*38e8c45fSAndroid Build Coastguard Worker }
1111*38e8c45fSAndroid Build Coastguard Worker
1112*38e8c45fSAndroid Build Coastguard Worker if (std::abs(mSurfaceFlingerActuals.startTime - mSurfaceFlingerPredictions.startTime) >
1113*38e8c45fSAndroid Build Coastguard Worker mJankClassificationThresholds.startThreshold) {
1114*38e8c45fSAndroid Build Coastguard Worker mFrameStartMetadata =
1115*38e8c45fSAndroid Build Coastguard Worker mSurfaceFlingerActuals.startTime > mSurfaceFlingerPredictions.startTime
1116*38e8c45fSAndroid Build Coastguard Worker ? FrameStartMetadata::LateStart
1117*38e8c45fSAndroid Build Coastguard Worker : FrameStartMetadata::EarlyStart;
1118*38e8c45fSAndroid Build Coastguard Worker }
1119*38e8c45fSAndroid Build Coastguard Worker
1120*38e8c45fSAndroid Build Coastguard Worker if (mFramePresentMetadata != FramePresentMetadata::OnTimePresent) {
1121*38e8c45fSAndroid Build Coastguard Worker // Do jank classification only if present is not on time
1122*38e8c45fSAndroid Build Coastguard Worker if (mFramePresentMetadata == FramePresentMetadata::EarlyPresent) {
1123*38e8c45fSAndroid Build Coastguard Worker if (mFrameReadyMetadata == FrameReadyMetadata::OnTimeFinish) {
1124*38e8c45fSAndroid Build Coastguard Worker // Finish on time, Present early
1125*38e8c45fSAndroid Build Coastguard Worker if (deltaToVsync < mJankClassificationThresholds.presentThreshold ||
1126*38e8c45fSAndroid Build Coastguard Worker deltaToVsync >= (mRefreshRate.getPeriodNsecs() -
1127*38e8c45fSAndroid Build Coastguard Worker mJankClassificationThresholds.presentThreshold)) {
1128*38e8c45fSAndroid Build Coastguard Worker // Delta is a factor of vsync if its within the presentTheshold on either side
1129*38e8c45fSAndroid Build Coastguard Worker // of the vsyncPeriod. Example: 0-2ms and 9-11ms are both within the threshold
1130*38e8c45fSAndroid Build Coastguard Worker // of the vsyncPeriod if the threshold was 2ms and the vsyncPeriod was 11ms.
1131*38e8c45fSAndroid Build Coastguard Worker mJankType = JankType::SurfaceFlingerScheduling;
1132*38e8c45fSAndroid Build Coastguard Worker } else {
1133*38e8c45fSAndroid Build Coastguard Worker // Delta is not a factor of vsync,
1134*38e8c45fSAndroid Build Coastguard Worker mJankType = JankType::PredictionError;
1135*38e8c45fSAndroid Build Coastguard Worker }
1136*38e8c45fSAndroid Build Coastguard Worker } else if (mFrameReadyMetadata == FrameReadyMetadata::LateFinish) {
1137*38e8c45fSAndroid Build Coastguard Worker // Finish late, Present early
1138*38e8c45fSAndroid Build Coastguard Worker mJankType = JankType::SurfaceFlingerScheduling;
1139*38e8c45fSAndroid Build Coastguard Worker } else {
1140*38e8c45fSAndroid Build Coastguard Worker // Finish time unknown
1141*38e8c45fSAndroid Build Coastguard Worker mJankType = JankType::Unknown;
1142*38e8c45fSAndroid Build Coastguard Worker }
1143*38e8c45fSAndroid Build Coastguard Worker } else if (mFramePresentMetadata == FramePresentMetadata::LatePresent) {
1144*38e8c45fSAndroid Build Coastguard Worker if (std::abs(mSurfaceFlingerPredictions.presentTime - previousPresentTime) <=
1145*38e8c45fSAndroid Build Coastguard Worker mJankClassificationThresholds.presentThreshold ||
1146*38e8c45fSAndroid Build Coastguard Worker previousPresentTime > mSurfaceFlingerPredictions.presentTime) {
1147*38e8c45fSAndroid Build Coastguard Worker // The previous frame was either presented in the current frame's expected vsync or
1148*38e8c45fSAndroid Build Coastguard Worker // it was presented even later than the current frame's expected vsync.
1149*38e8c45fSAndroid Build Coastguard Worker mJankType = JankType::SurfaceFlingerStuffing;
1150*38e8c45fSAndroid Build Coastguard Worker }
1151*38e8c45fSAndroid Build Coastguard Worker if (mFrameReadyMetadata == FrameReadyMetadata::OnTimeFinish &&
1152*38e8c45fSAndroid Build Coastguard Worker !(mJankType & JankType::SurfaceFlingerStuffing)) {
1153*38e8c45fSAndroid Build Coastguard Worker // Finish on time, Present late
1154*38e8c45fSAndroid Build Coastguard Worker if (deltaToVsync < mJankClassificationThresholds.presentThreshold ||
1155*38e8c45fSAndroid Build Coastguard Worker deltaToVsync >= (mRefreshRate.getPeriodNsecs() -
1156*38e8c45fSAndroid Build Coastguard Worker mJankClassificationThresholds.presentThreshold)) {
1157*38e8c45fSAndroid Build Coastguard Worker // Delta is a factor of vsync if its within the presentTheshold on either side
1158*38e8c45fSAndroid Build Coastguard Worker // of the vsyncPeriod. Example: 0-2ms and 9-11ms are both within the threshold
1159*38e8c45fSAndroid Build Coastguard Worker // of the vsyncPeriod if the threshold was 2ms and the vsyncPeriod was 11ms.
1160*38e8c45fSAndroid Build Coastguard Worker mJankType = JankType::DisplayHAL;
1161*38e8c45fSAndroid Build Coastguard Worker } else {
1162*38e8c45fSAndroid Build Coastguard Worker // Delta is not a factor of vsync
1163*38e8c45fSAndroid Build Coastguard Worker mJankType = JankType::PredictionError;
1164*38e8c45fSAndroid Build Coastguard Worker }
1165*38e8c45fSAndroid Build Coastguard Worker } else if (mFrameReadyMetadata == FrameReadyMetadata::LateFinish) {
1166*38e8c45fSAndroid Build Coastguard Worker if (!(mJankType & JankType::SurfaceFlingerStuffing) ||
1167*38e8c45fSAndroid Build Coastguard Worker mSurfaceFlingerActuals.presentTime - previousPresentTime >
1168*38e8c45fSAndroid Build Coastguard Worker mRefreshRate.getPeriodNsecs() +
1169*38e8c45fSAndroid Build Coastguard Worker mJankClassificationThresholds.presentThreshold) {
1170*38e8c45fSAndroid Build Coastguard Worker // Classify CPU vs GPU if SF wasn't stuffed or if SF was stuffed but this frame
1171*38e8c45fSAndroid Build Coastguard Worker // was presented more than a vsync late.
1172*38e8c45fSAndroid Build Coastguard Worker if (mGpuFence != FenceTime::NO_FENCE) {
1173*38e8c45fSAndroid Build Coastguard Worker // If SF was in GPU composition, classify it as GPU deadline missed.
1174*38e8c45fSAndroid Build Coastguard Worker mJankType = JankType::SurfaceFlingerGpuDeadlineMissed;
1175*38e8c45fSAndroid Build Coastguard Worker } else {
1176*38e8c45fSAndroid Build Coastguard Worker mJankType = JankType::SurfaceFlingerCpuDeadlineMissed;
1177*38e8c45fSAndroid Build Coastguard Worker }
1178*38e8c45fSAndroid Build Coastguard Worker }
1179*38e8c45fSAndroid Build Coastguard Worker } else {
1180*38e8c45fSAndroid Build Coastguard Worker // Finish time unknown
1181*38e8c45fSAndroid Build Coastguard Worker mJankType = JankType::Unknown;
1182*38e8c45fSAndroid Build Coastguard Worker }
1183*38e8c45fSAndroid Build Coastguard Worker } else {
1184*38e8c45fSAndroid Build Coastguard Worker // Present unknown
1185*38e8c45fSAndroid Build Coastguard Worker mJankType = JankType::Unknown;
1186*38e8c45fSAndroid Build Coastguard Worker }
1187*38e8c45fSAndroid Build Coastguard Worker }
1188*38e8c45fSAndroid Build Coastguard Worker }
1189*38e8c45fSAndroid Build Coastguard Worker
onPresent(nsecs_t signalTime,nsecs_t previousPresentTime)1190*38e8c45fSAndroid Build Coastguard Worker void FrameTimeline::DisplayFrame::onPresent(nsecs_t signalTime, nsecs_t previousPresentTime) {
1191*38e8c45fSAndroid Build Coastguard Worker mSurfaceFlingerActuals.presentTime = signalTime;
1192*38e8c45fSAndroid Build Coastguard Worker nsecs_t deadlineDelta = 0;
1193*38e8c45fSAndroid Build Coastguard Worker nsecs_t deltaToVsync = 0;
1194*38e8c45fSAndroid Build Coastguard Worker classifyJank(deadlineDelta, deltaToVsync, previousPresentTime);
1195*38e8c45fSAndroid Build Coastguard Worker
1196*38e8c45fSAndroid Build Coastguard Worker for (auto& surfaceFrame : mSurfaceFrames) {
1197*38e8c45fSAndroid Build Coastguard Worker surfaceFrame->onPresent(signalTime, mJankType, mRefreshRate, mRenderRate, deadlineDelta,
1198*38e8c45fSAndroid Build Coastguard Worker deltaToVsync);
1199*38e8c45fSAndroid Build Coastguard Worker }
1200*38e8c45fSAndroid Build Coastguard Worker }
1201*38e8c45fSAndroid Build Coastguard Worker
onCommitNotComposited()1202*38e8c45fSAndroid Build Coastguard Worker void FrameTimeline::DisplayFrame::onCommitNotComposited() {
1203*38e8c45fSAndroid Build Coastguard Worker for (auto& surfaceFrame : mSurfaceFrames) {
1204*38e8c45fSAndroid Build Coastguard Worker surfaceFrame->onCommitNotComposited(mRefreshRate, mRenderRate);
1205*38e8c45fSAndroid Build Coastguard Worker }
1206*38e8c45fSAndroid Build Coastguard Worker }
1207*38e8c45fSAndroid Build Coastguard Worker
tracePredictions(pid_t surfaceFlingerPid,nsecs_t monoBootOffset,bool filterFramesBeforeTraceStarts) const1208*38e8c45fSAndroid Build Coastguard Worker void FrameTimeline::DisplayFrame::tracePredictions(pid_t surfaceFlingerPid, nsecs_t monoBootOffset,
1209*38e8c45fSAndroid Build Coastguard Worker bool filterFramesBeforeTraceStarts) const {
1210*38e8c45fSAndroid Build Coastguard Worker int64_t expectedTimelineCookie = mTraceCookieCounter.getCookieForTracing();
1211*38e8c45fSAndroid Build Coastguard Worker bool traced = false;
1212*38e8c45fSAndroid Build Coastguard Worker
1213*38e8c45fSAndroid Build Coastguard Worker // Expected timeline start
1214*38e8c45fSAndroid Build Coastguard Worker FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
1215*38e8c45fSAndroid Build Coastguard Worker const auto timestamp = mSurfaceFlingerPredictions.startTime;
1216*38e8c45fSAndroid Build Coastguard Worker if (filterFramesBeforeTraceStarts && !shouldTraceForDataSource(ctx, timestamp)) {
1217*38e8c45fSAndroid Build Coastguard Worker // Do not trace packets started before tracing starts.
1218*38e8c45fSAndroid Build Coastguard Worker return;
1219*38e8c45fSAndroid Build Coastguard Worker }
1220*38e8c45fSAndroid Build Coastguard Worker traced = true;
1221*38e8c45fSAndroid Build Coastguard Worker
1222*38e8c45fSAndroid Build Coastguard Worker auto packet = ctx.NewTracePacket();
1223*38e8c45fSAndroid Build Coastguard Worker packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
1224*38e8c45fSAndroid Build Coastguard Worker packet->set_timestamp(static_cast<uint64_t>(timestamp + monoBootOffset));
1225*38e8c45fSAndroid Build Coastguard Worker
1226*38e8c45fSAndroid Build Coastguard Worker auto* event = packet->set_frame_timeline_event();
1227*38e8c45fSAndroid Build Coastguard Worker auto* expectedDisplayFrameStartEvent = event->set_expected_display_frame_start();
1228*38e8c45fSAndroid Build Coastguard Worker
1229*38e8c45fSAndroid Build Coastguard Worker expectedDisplayFrameStartEvent->set_cookie(expectedTimelineCookie);
1230*38e8c45fSAndroid Build Coastguard Worker
1231*38e8c45fSAndroid Build Coastguard Worker expectedDisplayFrameStartEvent->set_token(mToken);
1232*38e8c45fSAndroid Build Coastguard Worker expectedDisplayFrameStartEvent->set_pid(surfaceFlingerPid);
1233*38e8c45fSAndroid Build Coastguard Worker });
1234*38e8c45fSAndroid Build Coastguard Worker
1235*38e8c45fSAndroid Build Coastguard Worker if (traced) {
1236*38e8c45fSAndroid Build Coastguard Worker // Expected timeline end
1237*38e8c45fSAndroid Build Coastguard Worker FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
1238*38e8c45fSAndroid Build Coastguard Worker auto packet = ctx.NewTracePacket();
1239*38e8c45fSAndroid Build Coastguard Worker packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
1240*38e8c45fSAndroid Build Coastguard Worker packet->set_timestamp(
1241*38e8c45fSAndroid Build Coastguard Worker static_cast<uint64_t>(mSurfaceFlingerPredictions.endTime + monoBootOffset));
1242*38e8c45fSAndroid Build Coastguard Worker
1243*38e8c45fSAndroid Build Coastguard Worker auto* event = packet->set_frame_timeline_event();
1244*38e8c45fSAndroid Build Coastguard Worker auto* expectedDisplayFrameEndEvent = event->set_frame_end();
1245*38e8c45fSAndroid Build Coastguard Worker
1246*38e8c45fSAndroid Build Coastguard Worker expectedDisplayFrameEndEvent->set_cookie(expectedTimelineCookie);
1247*38e8c45fSAndroid Build Coastguard Worker });
1248*38e8c45fSAndroid Build Coastguard Worker }
1249*38e8c45fSAndroid Build Coastguard Worker }
1250*38e8c45fSAndroid Build Coastguard Worker
addSkippedFrame(pid_t surfaceFlingerPid,nsecs_t monoBootOffset,nsecs_t previousPredictionPresentTime,bool filterFramesBeforeTraceStarts) const1251*38e8c45fSAndroid Build Coastguard Worker void FrameTimeline::DisplayFrame::addSkippedFrame(pid_t surfaceFlingerPid, nsecs_t monoBootOffset,
1252*38e8c45fSAndroid Build Coastguard Worker nsecs_t previousPredictionPresentTime,
1253*38e8c45fSAndroid Build Coastguard Worker bool filterFramesBeforeTraceStarts) const {
1254*38e8c45fSAndroid Build Coastguard Worker nsecs_t skippedFrameStartTime = 0, skippedFramePresentTime = 0;
1255*38e8c45fSAndroid Build Coastguard Worker const constexpr float kThresh = 0.5f;
1256*38e8c45fSAndroid Build Coastguard Worker const constexpr float kRange = 1.5f;
1257*38e8c45fSAndroid Build Coastguard Worker for (auto& surfaceFrame : mSurfaceFrames) {
1258*38e8c45fSAndroid Build Coastguard Worker if (previousPredictionPresentTime != 0 &&
1259*38e8c45fSAndroid Build Coastguard Worker static_cast<float>(mSurfaceFlingerPredictions.presentTime -
1260*38e8c45fSAndroid Build Coastguard Worker previousPredictionPresentTime) >=
1261*38e8c45fSAndroid Build Coastguard Worker static_cast<float>(mRenderRate.getPeriodNsecs()) * kRange &&
1262*38e8c45fSAndroid Build Coastguard Worker static_cast<float>(surfaceFrame->getPredictions().presentTime) <=
1263*38e8c45fSAndroid Build Coastguard Worker (static_cast<float>(mSurfaceFlingerPredictions.presentTime) -
1264*38e8c45fSAndroid Build Coastguard Worker kThresh * static_cast<float>(mRenderRate.getPeriodNsecs())) &&
1265*38e8c45fSAndroid Build Coastguard Worker static_cast<float>(surfaceFrame->getPredictions().presentTime) >=
1266*38e8c45fSAndroid Build Coastguard Worker (static_cast<float>(previousPredictionPresentTime) +
1267*38e8c45fSAndroid Build Coastguard Worker kThresh * static_cast<float>(mRenderRate.getPeriodNsecs())) &&
1268*38e8c45fSAndroid Build Coastguard Worker // sf skipped frame is not considered if app is self janked
1269*38e8c45fSAndroid Build Coastguard Worker surfaceFrame->getJankType() != JankType::None && !surfaceFrame->isSelfJanky()) {
1270*38e8c45fSAndroid Build Coastguard Worker skippedFrameStartTime = surfaceFrame->getPredictions().endTime;
1271*38e8c45fSAndroid Build Coastguard Worker skippedFramePresentTime = surfaceFrame->getPredictions().presentTime;
1272*38e8c45fSAndroid Build Coastguard Worker break;
1273*38e8c45fSAndroid Build Coastguard Worker }
1274*38e8c45fSAndroid Build Coastguard Worker }
1275*38e8c45fSAndroid Build Coastguard Worker
1276*38e8c45fSAndroid Build Coastguard Worker // add slice
1277*38e8c45fSAndroid Build Coastguard Worker if (skippedFrameStartTime != 0 && skippedFramePresentTime != 0) {
1278*38e8c45fSAndroid Build Coastguard Worker int64_t actualTimelineCookie = mTraceCookieCounter.getCookieForTracing();
1279*38e8c45fSAndroid Build Coastguard Worker bool traced = false;
1280*38e8c45fSAndroid Build Coastguard Worker
1281*38e8c45fSAndroid Build Coastguard Worker // Actual timeline start
1282*38e8c45fSAndroid Build Coastguard Worker FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
1283*38e8c45fSAndroid Build Coastguard Worker if (filterFramesBeforeTraceStarts &&
1284*38e8c45fSAndroid Build Coastguard Worker !shouldTraceForDataSource(ctx, skippedFrameStartTime)) {
1285*38e8c45fSAndroid Build Coastguard Worker // Do not trace packets started before tracing starts.
1286*38e8c45fSAndroid Build Coastguard Worker return;
1287*38e8c45fSAndroid Build Coastguard Worker }
1288*38e8c45fSAndroid Build Coastguard Worker traced = true;
1289*38e8c45fSAndroid Build Coastguard Worker
1290*38e8c45fSAndroid Build Coastguard Worker auto packet = ctx.NewTracePacket();
1291*38e8c45fSAndroid Build Coastguard Worker packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
1292*38e8c45fSAndroid Build Coastguard Worker packet->set_timestamp(static_cast<uint64_t>(skippedFrameStartTime + monoBootOffset));
1293*38e8c45fSAndroid Build Coastguard Worker
1294*38e8c45fSAndroid Build Coastguard Worker auto* event = packet->set_frame_timeline_event();
1295*38e8c45fSAndroid Build Coastguard Worker auto* actualDisplayFrameStartEvent = event->set_actual_display_frame_start();
1296*38e8c45fSAndroid Build Coastguard Worker
1297*38e8c45fSAndroid Build Coastguard Worker actualDisplayFrameStartEvent->set_cookie(actualTimelineCookie);
1298*38e8c45fSAndroid Build Coastguard Worker
1299*38e8c45fSAndroid Build Coastguard Worker actualDisplayFrameStartEvent->set_token(0);
1300*38e8c45fSAndroid Build Coastguard Worker actualDisplayFrameStartEvent->set_pid(surfaceFlingerPid);
1301*38e8c45fSAndroid Build Coastguard Worker actualDisplayFrameStartEvent->set_on_time_finish(mFrameReadyMetadata ==
1302*38e8c45fSAndroid Build Coastguard Worker FrameReadyMetadata::OnTimeFinish);
1303*38e8c45fSAndroid Build Coastguard Worker actualDisplayFrameStartEvent->set_gpu_composition(false);
1304*38e8c45fSAndroid Build Coastguard Worker actualDisplayFrameStartEvent->set_prediction_type(toProto(PredictionState::Valid));
1305*38e8c45fSAndroid Build Coastguard Worker actualDisplayFrameStartEvent->set_present_type(FrameTimelineEvent::PRESENT_DROPPED);
1306*38e8c45fSAndroid Build Coastguard Worker actualDisplayFrameStartEvent->set_jank_type(jankTypeBitmaskToProto(JankType::Dropped));
1307*38e8c45fSAndroid Build Coastguard Worker actualDisplayFrameStartEvent->set_jank_severity_type(toProto(JankSeverityType::None));
1308*38e8c45fSAndroid Build Coastguard Worker });
1309*38e8c45fSAndroid Build Coastguard Worker
1310*38e8c45fSAndroid Build Coastguard Worker if (traced) {
1311*38e8c45fSAndroid Build Coastguard Worker // Actual timeline end
1312*38e8c45fSAndroid Build Coastguard Worker FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
1313*38e8c45fSAndroid Build Coastguard Worker auto packet = ctx.NewTracePacket();
1314*38e8c45fSAndroid Build Coastguard Worker packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
1315*38e8c45fSAndroid Build Coastguard Worker packet->set_timestamp(
1316*38e8c45fSAndroid Build Coastguard Worker static_cast<uint64_t>(skippedFramePresentTime + monoBootOffset));
1317*38e8c45fSAndroid Build Coastguard Worker
1318*38e8c45fSAndroid Build Coastguard Worker auto* event = packet->set_frame_timeline_event();
1319*38e8c45fSAndroid Build Coastguard Worker auto* actualDisplayFrameEndEvent = event->set_frame_end();
1320*38e8c45fSAndroid Build Coastguard Worker
1321*38e8c45fSAndroid Build Coastguard Worker actualDisplayFrameEndEvent->set_cookie(actualTimelineCookie);
1322*38e8c45fSAndroid Build Coastguard Worker });
1323*38e8c45fSAndroid Build Coastguard Worker }
1324*38e8c45fSAndroid Build Coastguard Worker }
1325*38e8c45fSAndroid Build Coastguard Worker }
1326*38e8c45fSAndroid Build Coastguard Worker
traceActuals(pid_t surfaceFlingerPid,nsecs_t monoBootOffset,bool filterFramesBeforeTraceStarts) const1327*38e8c45fSAndroid Build Coastguard Worker void FrameTimeline::DisplayFrame::traceActuals(pid_t surfaceFlingerPid, nsecs_t monoBootOffset,
1328*38e8c45fSAndroid Build Coastguard Worker bool filterFramesBeforeTraceStarts) const {
1329*38e8c45fSAndroid Build Coastguard Worker int64_t actualTimelineCookie = mTraceCookieCounter.getCookieForTracing();
1330*38e8c45fSAndroid Build Coastguard Worker bool traced = false;
1331*38e8c45fSAndroid Build Coastguard Worker
1332*38e8c45fSAndroid Build Coastguard Worker // Actual timeline start
1333*38e8c45fSAndroid Build Coastguard Worker FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
1334*38e8c45fSAndroid Build Coastguard Worker const auto timestamp = mSurfaceFlingerActuals.startTime;
1335*38e8c45fSAndroid Build Coastguard Worker if (filterFramesBeforeTraceStarts && !shouldTraceForDataSource(ctx, timestamp)) {
1336*38e8c45fSAndroid Build Coastguard Worker // Do not trace packets started before tracing starts.
1337*38e8c45fSAndroid Build Coastguard Worker return;
1338*38e8c45fSAndroid Build Coastguard Worker }
1339*38e8c45fSAndroid Build Coastguard Worker traced = true;
1340*38e8c45fSAndroid Build Coastguard Worker
1341*38e8c45fSAndroid Build Coastguard Worker auto packet = ctx.NewTracePacket();
1342*38e8c45fSAndroid Build Coastguard Worker packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
1343*38e8c45fSAndroid Build Coastguard Worker packet->set_timestamp(static_cast<uint64_t>(timestamp + monoBootOffset));
1344*38e8c45fSAndroid Build Coastguard Worker
1345*38e8c45fSAndroid Build Coastguard Worker auto* event = packet->set_frame_timeline_event();
1346*38e8c45fSAndroid Build Coastguard Worker auto* actualDisplayFrameStartEvent = event->set_actual_display_frame_start();
1347*38e8c45fSAndroid Build Coastguard Worker
1348*38e8c45fSAndroid Build Coastguard Worker actualDisplayFrameStartEvent->set_cookie(actualTimelineCookie);
1349*38e8c45fSAndroid Build Coastguard Worker
1350*38e8c45fSAndroid Build Coastguard Worker actualDisplayFrameStartEvent->set_token(mToken);
1351*38e8c45fSAndroid Build Coastguard Worker actualDisplayFrameStartEvent->set_pid(surfaceFlingerPid);
1352*38e8c45fSAndroid Build Coastguard Worker
1353*38e8c45fSAndroid Build Coastguard Worker actualDisplayFrameStartEvent->set_present_type(toProto(mFramePresentMetadata));
1354*38e8c45fSAndroid Build Coastguard Worker actualDisplayFrameStartEvent->set_on_time_finish(mFrameReadyMetadata ==
1355*38e8c45fSAndroid Build Coastguard Worker FrameReadyMetadata::OnTimeFinish);
1356*38e8c45fSAndroid Build Coastguard Worker actualDisplayFrameStartEvent->set_gpu_composition(mGpuFence != FenceTime::NO_FENCE);
1357*38e8c45fSAndroid Build Coastguard Worker actualDisplayFrameStartEvent->set_jank_type(jankTypeBitmaskToProto(mJankType));
1358*38e8c45fSAndroid Build Coastguard Worker actualDisplayFrameStartEvent->set_prediction_type(toProto(mPredictionState));
1359*38e8c45fSAndroid Build Coastguard Worker actualDisplayFrameStartEvent->set_jank_severity_type(toProto(mJankSeverityType));
1360*38e8c45fSAndroid Build Coastguard Worker });
1361*38e8c45fSAndroid Build Coastguard Worker
1362*38e8c45fSAndroid Build Coastguard Worker if (traced) {
1363*38e8c45fSAndroid Build Coastguard Worker // Actual timeline end
1364*38e8c45fSAndroid Build Coastguard Worker FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
1365*38e8c45fSAndroid Build Coastguard Worker auto packet = ctx.NewTracePacket();
1366*38e8c45fSAndroid Build Coastguard Worker packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
1367*38e8c45fSAndroid Build Coastguard Worker packet->set_timestamp(
1368*38e8c45fSAndroid Build Coastguard Worker static_cast<uint64_t>(mSurfaceFlingerActuals.presentTime + monoBootOffset));
1369*38e8c45fSAndroid Build Coastguard Worker
1370*38e8c45fSAndroid Build Coastguard Worker auto* event = packet->set_frame_timeline_event();
1371*38e8c45fSAndroid Build Coastguard Worker auto* actualDisplayFrameEndEvent = event->set_frame_end();
1372*38e8c45fSAndroid Build Coastguard Worker
1373*38e8c45fSAndroid Build Coastguard Worker actualDisplayFrameEndEvent->set_cookie(actualTimelineCookie);
1374*38e8c45fSAndroid Build Coastguard Worker });
1375*38e8c45fSAndroid Build Coastguard Worker }
1376*38e8c45fSAndroid Build Coastguard Worker }
1377*38e8c45fSAndroid Build Coastguard Worker
trace(pid_t surfaceFlingerPid,nsecs_t monoBootOffset,nsecs_t previousPredictionPresentTime,bool filterFramesBeforeTraceStarts) const1378*38e8c45fSAndroid Build Coastguard Worker nsecs_t FrameTimeline::DisplayFrame::trace(pid_t surfaceFlingerPid, nsecs_t monoBootOffset,
1379*38e8c45fSAndroid Build Coastguard Worker nsecs_t previousPredictionPresentTime,
1380*38e8c45fSAndroid Build Coastguard Worker bool filterFramesBeforeTraceStarts) const {
1381*38e8c45fSAndroid Build Coastguard Worker if (mSurfaceFrames.empty()) {
1382*38e8c45fSAndroid Build Coastguard Worker // We don't want to trace display frames without any surface frames updates as this cannot
1383*38e8c45fSAndroid Build Coastguard Worker // be janky
1384*38e8c45fSAndroid Build Coastguard Worker return previousPredictionPresentTime;
1385*38e8c45fSAndroid Build Coastguard Worker }
1386*38e8c45fSAndroid Build Coastguard Worker
1387*38e8c45fSAndroid Build Coastguard Worker if (mToken == FrameTimelineInfo::INVALID_VSYNC_ID) {
1388*38e8c45fSAndroid Build Coastguard Worker // DisplayFrame should not have an invalid token.
1389*38e8c45fSAndroid Build Coastguard Worker ALOGE("Cannot trace DisplayFrame with invalid token");
1390*38e8c45fSAndroid Build Coastguard Worker return previousPredictionPresentTime;
1391*38e8c45fSAndroid Build Coastguard Worker }
1392*38e8c45fSAndroid Build Coastguard Worker
1393*38e8c45fSAndroid Build Coastguard Worker if (mPredictionState == PredictionState::Valid) {
1394*38e8c45fSAndroid Build Coastguard Worker // Expired and unknown predictions have zeroed timestamps. This cannot be used in any
1395*38e8c45fSAndroid Build Coastguard Worker // meaningful way in a trace.
1396*38e8c45fSAndroid Build Coastguard Worker tracePredictions(surfaceFlingerPid, monoBootOffset, filterFramesBeforeTraceStarts);
1397*38e8c45fSAndroid Build Coastguard Worker }
1398*38e8c45fSAndroid Build Coastguard Worker traceActuals(surfaceFlingerPid, monoBootOffset, filterFramesBeforeTraceStarts);
1399*38e8c45fSAndroid Build Coastguard Worker
1400*38e8c45fSAndroid Build Coastguard Worker for (auto& surfaceFrame : mSurfaceFrames) {
1401*38e8c45fSAndroid Build Coastguard Worker surfaceFrame->trace(mToken, monoBootOffset, filterFramesBeforeTraceStarts);
1402*38e8c45fSAndroid Build Coastguard Worker }
1403*38e8c45fSAndroid Build Coastguard Worker
1404*38e8c45fSAndroid Build Coastguard Worker if (FlagManager::getInstance().add_sf_skipped_frames_to_trace()) {
1405*38e8c45fSAndroid Build Coastguard Worker addSkippedFrame(surfaceFlingerPid, monoBootOffset, previousPredictionPresentTime,
1406*38e8c45fSAndroid Build Coastguard Worker filterFramesBeforeTraceStarts);
1407*38e8c45fSAndroid Build Coastguard Worker }
1408*38e8c45fSAndroid Build Coastguard Worker return mSurfaceFlingerPredictions.presentTime;
1409*38e8c45fSAndroid Build Coastguard Worker }
1410*38e8c45fSAndroid Build Coastguard Worker
computeFps(const std::unordered_set<int32_t> & layerIds)1411*38e8c45fSAndroid Build Coastguard Worker float FrameTimeline::computeFps(const std::unordered_set<int32_t>& layerIds) {
1412*38e8c45fSAndroid Build Coastguard Worker if (layerIds.empty()) {
1413*38e8c45fSAndroid Build Coastguard Worker return 0.0f;
1414*38e8c45fSAndroid Build Coastguard Worker }
1415*38e8c45fSAndroid Build Coastguard Worker
1416*38e8c45fSAndroid Build Coastguard Worker std::vector<nsecs_t> presentTimes;
1417*38e8c45fSAndroid Build Coastguard Worker {
1418*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock lock(mMutex);
1419*38e8c45fSAndroid Build Coastguard Worker presentTimes.reserve(mDisplayFrames.size());
1420*38e8c45fSAndroid Build Coastguard Worker for (size_t i = 0; i < mDisplayFrames.size(); i++) {
1421*38e8c45fSAndroid Build Coastguard Worker const auto& displayFrame = mDisplayFrames[i];
1422*38e8c45fSAndroid Build Coastguard Worker if (displayFrame->getActuals().presentTime <= 0) {
1423*38e8c45fSAndroid Build Coastguard Worker continue;
1424*38e8c45fSAndroid Build Coastguard Worker }
1425*38e8c45fSAndroid Build Coastguard Worker for (const auto& surfaceFrame : displayFrame->getSurfaceFrames()) {
1426*38e8c45fSAndroid Build Coastguard Worker if (surfaceFrame->getPresentState() == SurfaceFrame::PresentState::Presented &&
1427*38e8c45fSAndroid Build Coastguard Worker layerIds.count(surfaceFrame->getLayerId()) > 0) {
1428*38e8c45fSAndroid Build Coastguard Worker // We're looking for DisplayFrames that presents at least one layer from
1429*38e8c45fSAndroid Build Coastguard Worker // layerIds, so push the present time and skip looking through the rest of the
1430*38e8c45fSAndroid Build Coastguard Worker // SurfaceFrames.
1431*38e8c45fSAndroid Build Coastguard Worker presentTimes.push_back(displayFrame->getActuals().presentTime);
1432*38e8c45fSAndroid Build Coastguard Worker break;
1433*38e8c45fSAndroid Build Coastguard Worker }
1434*38e8c45fSAndroid Build Coastguard Worker }
1435*38e8c45fSAndroid Build Coastguard Worker }
1436*38e8c45fSAndroid Build Coastguard Worker }
1437*38e8c45fSAndroid Build Coastguard Worker
1438*38e8c45fSAndroid Build Coastguard Worker // FPS can't be computed when there's fewer than 2 presented frames.
1439*38e8c45fSAndroid Build Coastguard Worker if (presentTimes.size() <= 1) {
1440*38e8c45fSAndroid Build Coastguard Worker return 0.0f;
1441*38e8c45fSAndroid Build Coastguard Worker }
1442*38e8c45fSAndroid Build Coastguard Worker
1443*38e8c45fSAndroid Build Coastguard Worker nsecs_t priorPresentTime = -1;
1444*38e8c45fSAndroid Build Coastguard Worker nsecs_t totalPresentToPresentWalls = 0;
1445*38e8c45fSAndroid Build Coastguard Worker
1446*38e8c45fSAndroid Build Coastguard Worker for (const nsecs_t presentTime : presentTimes) {
1447*38e8c45fSAndroid Build Coastguard Worker if (priorPresentTime == -1) {
1448*38e8c45fSAndroid Build Coastguard Worker priorPresentTime = presentTime;
1449*38e8c45fSAndroid Build Coastguard Worker continue;
1450*38e8c45fSAndroid Build Coastguard Worker }
1451*38e8c45fSAndroid Build Coastguard Worker
1452*38e8c45fSAndroid Build Coastguard Worker totalPresentToPresentWalls += (presentTime - priorPresentTime);
1453*38e8c45fSAndroid Build Coastguard Worker priorPresentTime = presentTime;
1454*38e8c45fSAndroid Build Coastguard Worker }
1455*38e8c45fSAndroid Build Coastguard Worker
1456*38e8c45fSAndroid Build Coastguard Worker if (CC_UNLIKELY(totalPresentToPresentWalls <= 0)) {
1457*38e8c45fSAndroid Build Coastguard Worker ALOGW("Invalid total present-to-present duration when computing fps: %" PRId64,
1458*38e8c45fSAndroid Build Coastguard Worker totalPresentToPresentWalls);
1459*38e8c45fSAndroid Build Coastguard Worker return 0.0f;
1460*38e8c45fSAndroid Build Coastguard Worker }
1461*38e8c45fSAndroid Build Coastguard Worker
1462*38e8c45fSAndroid Build Coastguard Worker const constexpr nsecs_t kOneSecond =
1463*38e8c45fSAndroid Build Coastguard Worker std::chrono::duration_cast<std::chrono::nanoseconds>(1s).count();
1464*38e8c45fSAndroid Build Coastguard Worker // (10^9 nanoseconds / second) * (N present deltas) / (total nanoseconds in N present deltas) =
1465*38e8c45fSAndroid Build Coastguard Worker // M frames / second
1466*38e8c45fSAndroid Build Coastguard Worker return kOneSecond * static_cast<nsecs_t>((presentTimes.size() - 1)) /
1467*38e8c45fSAndroid Build Coastguard Worker static_cast<float>(totalPresentToPresentWalls);
1468*38e8c45fSAndroid Build Coastguard Worker }
1469*38e8c45fSAndroid Build Coastguard Worker
generateFrameStats(int32_t layer,size_t count,FrameStats * outStats) const1470*38e8c45fSAndroid Build Coastguard Worker void FrameTimeline::generateFrameStats(int32_t layer, size_t count, FrameStats* outStats) const {
1471*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock lock(mMutex);
1472*38e8c45fSAndroid Build Coastguard Worker
1473*38e8c45fSAndroid Build Coastguard Worker // TODO: Include FPS calculation here
1474*38e8c45fSAndroid Build Coastguard Worker for (auto displayFrame : mDisplayFrames) {
1475*38e8c45fSAndroid Build Coastguard Worker if (!count--) {
1476*38e8c45fSAndroid Build Coastguard Worker break;
1477*38e8c45fSAndroid Build Coastguard Worker }
1478*38e8c45fSAndroid Build Coastguard Worker
1479*38e8c45fSAndroid Build Coastguard Worker if (displayFrame->getActuals().presentTime <= 0) {
1480*38e8c45fSAndroid Build Coastguard Worker continue;
1481*38e8c45fSAndroid Build Coastguard Worker }
1482*38e8c45fSAndroid Build Coastguard Worker
1483*38e8c45fSAndroid Build Coastguard Worker for (const auto& surfaceFrame : displayFrame->getSurfaceFrames()) {
1484*38e8c45fSAndroid Build Coastguard Worker if (surfaceFrame->getLayerId() == layer) {
1485*38e8c45fSAndroid Build Coastguard Worker outStats->actualPresentTimesNano.push_back(surfaceFrame->getActuals().presentTime);
1486*38e8c45fSAndroid Build Coastguard Worker outStats->desiredPresentTimesNano.push_back(
1487*38e8c45fSAndroid Build Coastguard Worker surfaceFrame->getActuals().desiredPresentTime);
1488*38e8c45fSAndroid Build Coastguard Worker outStats->frameReadyTimesNano.push_back(surfaceFrame->getActuals().endTime);
1489*38e8c45fSAndroid Build Coastguard Worker }
1490*38e8c45fSAndroid Build Coastguard Worker }
1491*38e8c45fSAndroid Build Coastguard Worker }
1492*38e8c45fSAndroid Build Coastguard Worker }
1493*38e8c45fSAndroid Build Coastguard Worker
getFirstSignalFenceIndex() const1494*38e8c45fSAndroid Build Coastguard Worker std::optional<size_t> FrameTimeline::getFirstSignalFenceIndex() const {
1495*38e8c45fSAndroid Build Coastguard Worker for (size_t i = 0; i < mPendingPresentFences.size(); i++) {
1496*38e8c45fSAndroid Build Coastguard Worker const auto& [fence, _] = mPendingPresentFences[i];
1497*38e8c45fSAndroid Build Coastguard Worker if (fence && fence->getSignalTime() != Fence::SIGNAL_TIME_PENDING) {
1498*38e8c45fSAndroid Build Coastguard Worker return i;
1499*38e8c45fSAndroid Build Coastguard Worker }
1500*38e8c45fSAndroid Build Coastguard Worker }
1501*38e8c45fSAndroid Build Coastguard Worker
1502*38e8c45fSAndroid Build Coastguard Worker return {};
1503*38e8c45fSAndroid Build Coastguard Worker }
1504*38e8c45fSAndroid Build Coastguard Worker
flushPendingPresentFences()1505*38e8c45fSAndroid Build Coastguard Worker void FrameTimeline::flushPendingPresentFences() {
1506*38e8c45fSAndroid Build Coastguard Worker const auto firstSignaledFence = getFirstSignalFenceIndex();
1507*38e8c45fSAndroid Build Coastguard Worker if (!firstSignaledFence.has_value()) {
1508*38e8c45fSAndroid Build Coastguard Worker return;
1509*38e8c45fSAndroid Build Coastguard Worker }
1510*38e8c45fSAndroid Build Coastguard Worker
1511*38e8c45fSAndroid Build Coastguard Worker // Perfetto is using boottime clock to void drifts when the device goes
1512*38e8c45fSAndroid Build Coastguard Worker // to suspend.
1513*38e8c45fSAndroid Build Coastguard Worker const auto monoBootOffset = mUseBootTimeClock
1514*38e8c45fSAndroid Build Coastguard Worker ? (systemTime(SYSTEM_TIME_BOOTTIME) - systemTime(SYSTEM_TIME_MONOTONIC))
1515*38e8c45fSAndroid Build Coastguard Worker : 0;
1516*38e8c45fSAndroid Build Coastguard Worker
1517*38e8c45fSAndroid Build Coastguard Worker // Present fences are expected to be signaled in order. Mark all the previous
1518*38e8c45fSAndroid Build Coastguard Worker // pending fences as errors.
1519*38e8c45fSAndroid Build Coastguard Worker for (size_t i = 0; i < firstSignaledFence.value(); i++) {
1520*38e8c45fSAndroid Build Coastguard Worker const auto& pendingPresentFence = *mPendingPresentFences.begin();
1521*38e8c45fSAndroid Build Coastguard Worker const nsecs_t signalTime = Fence::SIGNAL_TIME_INVALID;
1522*38e8c45fSAndroid Build Coastguard Worker auto& displayFrame = pendingPresentFence.second;
1523*38e8c45fSAndroid Build Coastguard Worker displayFrame->onPresent(signalTime, mPreviousActualPresentTime);
1524*38e8c45fSAndroid Build Coastguard Worker mPreviousPredictionPresentTime =
1525*38e8c45fSAndroid Build Coastguard Worker displayFrame->trace(mSurfaceFlingerPid, monoBootOffset,
1526*38e8c45fSAndroid Build Coastguard Worker mPreviousPredictionPresentTime, mFilterFramesBeforeTraceStarts);
1527*38e8c45fSAndroid Build Coastguard Worker mPendingPresentFences.erase(mPendingPresentFences.begin());
1528*38e8c45fSAndroid Build Coastguard Worker }
1529*38e8c45fSAndroid Build Coastguard Worker
1530*38e8c45fSAndroid Build Coastguard Worker mPresentFrames.clear();
1531*38e8c45fSAndroid Build Coastguard Worker for (size_t i = 0; i < mPendingPresentFences.size(); i++) {
1532*38e8c45fSAndroid Build Coastguard Worker const auto& pendingPresentFence = mPendingPresentFences[i];
1533*38e8c45fSAndroid Build Coastguard Worker nsecs_t signalTime = Fence::SIGNAL_TIME_INVALID;
1534*38e8c45fSAndroid Build Coastguard Worker if (pendingPresentFence.first && pendingPresentFence.first->isValid()) {
1535*38e8c45fSAndroid Build Coastguard Worker signalTime = pendingPresentFence.first->getSignalTime();
1536*38e8c45fSAndroid Build Coastguard Worker if (signalTime == Fence::SIGNAL_TIME_PENDING) {
1537*38e8c45fSAndroid Build Coastguard Worker break;
1538*38e8c45fSAndroid Build Coastguard Worker }
1539*38e8c45fSAndroid Build Coastguard Worker }
1540*38e8c45fSAndroid Build Coastguard Worker
1541*38e8c45fSAndroid Build Coastguard Worker auto& displayFrame = pendingPresentFence.second;
1542*38e8c45fSAndroid Build Coastguard Worker displayFrame->onPresent(signalTime, mPreviousActualPresentTime);
1543*38e8c45fSAndroid Build Coastguard Worker
1544*38e8c45fSAndroid Build Coastguard Worker // Surface frames have been jank classified and can be provided to caller
1545*38e8c45fSAndroid Build Coastguard Worker // to detect if buffer stuffing is occurring.
1546*38e8c45fSAndroid Build Coastguard Worker for (const auto& frame : displayFrame->getSurfaceFrames()) {
1547*38e8c45fSAndroid Build Coastguard Worker mPresentFrames.push_back(frame);
1548*38e8c45fSAndroid Build Coastguard Worker }
1549*38e8c45fSAndroid Build Coastguard Worker
1550*38e8c45fSAndroid Build Coastguard Worker mPreviousPredictionPresentTime =
1551*38e8c45fSAndroid Build Coastguard Worker displayFrame->trace(mSurfaceFlingerPid, monoBootOffset,
1552*38e8c45fSAndroid Build Coastguard Worker mPreviousPredictionPresentTime, mFilterFramesBeforeTraceStarts);
1553*38e8c45fSAndroid Build Coastguard Worker mPreviousActualPresentTime = signalTime;
1554*38e8c45fSAndroid Build Coastguard Worker
1555*38e8c45fSAndroid Build Coastguard Worker mPendingPresentFences.erase(mPendingPresentFences.begin() + static_cast<int>(i));
1556*38e8c45fSAndroid Build Coastguard Worker --i;
1557*38e8c45fSAndroid Build Coastguard Worker }
1558*38e8c45fSAndroid Build Coastguard Worker }
1559*38e8c45fSAndroid Build Coastguard Worker
finalizeCurrentDisplayFrame()1560*38e8c45fSAndroid Build Coastguard Worker void FrameTimeline::finalizeCurrentDisplayFrame() {
1561*38e8c45fSAndroid Build Coastguard Worker while (mDisplayFrames.size() >= mMaxDisplayFrames) {
1562*38e8c45fSAndroid Build Coastguard Worker // We maintain only a fixed number of frames' data. Pop older frames
1563*38e8c45fSAndroid Build Coastguard Worker mDisplayFrames.pop_front();
1564*38e8c45fSAndroid Build Coastguard Worker }
1565*38e8c45fSAndroid Build Coastguard Worker mDisplayFrames.push_back(mCurrentDisplayFrame);
1566*38e8c45fSAndroid Build Coastguard Worker mCurrentDisplayFrame.reset();
1567*38e8c45fSAndroid Build Coastguard Worker mCurrentDisplayFrame = std::make_shared<DisplayFrame>(mTimeStats, mJankClassificationThresholds,
1568*38e8c45fSAndroid Build Coastguard Worker &mTraceCookieCounter);
1569*38e8c45fSAndroid Build Coastguard Worker }
1570*38e8c45fSAndroid Build Coastguard Worker
getBaseTime() const1571*38e8c45fSAndroid Build Coastguard Worker nsecs_t FrameTimeline::DisplayFrame::getBaseTime() const {
1572*38e8c45fSAndroid Build Coastguard Worker nsecs_t baseTime =
1573*38e8c45fSAndroid Build Coastguard Worker getMinTime(mPredictionState, mSurfaceFlingerPredictions, mSurfaceFlingerActuals);
1574*38e8c45fSAndroid Build Coastguard Worker for (const auto& surfaceFrame : mSurfaceFrames) {
1575*38e8c45fSAndroid Build Coastguard Worker nsecs_t surfaceFrameBaseTime = surfaceFrame->getBaseTime();
1576*38e8c45fSAndroid Build Coastguard Worker if (surfaceFrameBaseTime != 0) {
1577*38e8c45fSAndroid Build Coastguard Worker baseTime = std::min(baseTime, surfaceFrameBaseTime);
1578*38e8c45fSAndroid Build Coastguard Worker }
1579*38e8c45fSAndroid Build Coastguard Worker }
1580*38e8c45fSAndroid Build Coastguard Worker return baseTime;
1581*38e8c45fSAndroid Build Coastguard Worker }
1582*38e8c45fSAndroid Build Coastguard Worker
dumpJank(std::string & result,nsecs_t baseTime,int displayFrameCount) const1583*38e8c45fSAndroid Build Coastguard Worker void FrameTimeline::DisplayFrame::dumpJank(std::string& result, nsecs_t baseTime,
1584*38e8c45fSAndroid Build Coastguard Worker int displayFrameCount) const {
1585*38e8c45fSAndroid Build Coastguard Worker if (mJankType == JankType::None) {
1586*38e8c45fSAndroid Build Coastguard Worker // Check if any Surface Frame has been janky
1587*38e8c45fSAndroid Build Coastguard Worker bool isJanky = false;
1588*38e8c45fSAndroid Build Coastguard Worker for (const auto& surfaceFrame : mSurfaceFrames) {
1589*38e8c45fSAndroid Build Coastguard Worker if (surfaceFrame->getJankType() != JankType::None) {
1590*38e8c45fSAndroid Build Coastguard Worker isJanky = true;
1591*38e8c45fSAndroid Build Coastguard Worker break;
1592*38e8c45fSAndroid Build Coastguard Worker }
1593*38e8c45fSAndroid Build Coastguard Worker }
1594*38e8c45fSAndroid Build Coastguard Worker if (!isJanky) {
1595*38e8c45fSAndroid Build Coastguard Worker return;
1596*38e8c45fSAndroid Build Coastguard Worker }
1597*38e8c45fSAndroid Build Coastguard Worker }
1598*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "Display Frame %d", displayFrameCount);
1599*38e8c45fSAndroid Build Coastguard Worker dump(result, baseTime);
1600*38e8c45fSAndroid Build Coastguard Worker }
1601*38e8c45fSAndroid Build Coastguard Worker
dumpAll(std::string & result,nsecs_t baseTime) const1602*38e8c45fSAndroid Build Coastguard Worker void FrameTimeline::DisplayFrame::dumpAll(std::string& result, nsecs_t baseTime) const {
1603*38e8c45fSAndroid Build Coastguard Worker dump(result, baseTime);
1604*38e8c45fSAndroid Build Coastguard Worker }
1605*38e8c45fSAndroid Build Coastguard Worker
dump(std::string & result,nsecs_t baseTime) const1606*38e8c45fSAndroid Build Coastguard Worker void FrameTimeline::DisplayFrame::dump(std::string& result, nsecs_t baseTime) const {
1607*38e8c45fSAndroid Build Coastguard Worker if (mJankType != JankType::None) {
1608*38e8c45fSAndroid Build Coastguard Worker // Easily identify a janky Display Frame in the dump
1609*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, " [*] ");
1610*38e8c45fSAndroid Build Coastguard Worker }
1611*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "\n");
1612*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "Prediction State : %s\n", toString(mPredictionState).c_str());
1613*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "Jank Type : %s\n", jankTypeBitmaskToString(mJankType).c_str());
1614*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "Present Metadata : %s\n", toString(mFramePresentMetadata).c_str());
1615*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "Finish Metadata: %s\n", toString(mFrameReadyMetadata).c_str());
1616*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "Start Metadata: %s\n", toString(mFrameStartMetadata).c_str());
1617*38e8c45fSAndroid Build Coastguard Worker std::chrono::nanoseconds vsyncPeriod(mRefreshRate.getPeriodNsecs());
1618*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "Vsync Period: %10f\n",
1619*38e8c45fSAndroid Build Coastguard Worker std::chrono::duration<double, std::milli>(vsyncPeriod).count());
1620*38e8c45fSAndroid Build Coastguard Worker nsecs_t presentDelta =
1621*38e8c45fSAndroid Build Coastguard Worker mSurfaceFlingerActuals.presentTime - mSurfaceFlingerPredictions.presentTime;
1622*38e8c45fSAndroid Build Coastguard Worker std::chrono::nanoseconds presentDeltaNs(std::abs(presentDelta));
1623*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "Present delta: %10f\n",
1624*38e8c45fSAndroid Build Coastguard Worker std::chrono::duration<double, std::milli>(presentDeltaNs).count());
1625*38e8c45fSAndroid Build Coastguard Worker std::chrono::nanoseconds deltaToVsync(std::abs(presentDelta) % mRefreshRate.getPeriodNsecs());
1626*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "Present delta %% refreshrate: %10f\n",
1627*38e8c45fSAndroid Build Coastguard Worker std::chrono::duration<double, std::milli>(deltaToVsync).count());
1628*38e8c45fSAndroid Build Coastguard Worker dumpTable(result, mSurfaceFlingerPredictions, mSurfaceFlingerActuals, "", mPredictionState,
1629*38e8c45fSAndroid Build Coastguard Worker baseTime);
1630*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "\n");
1631*38e8c45fSAndroid Build Coastguard Worker std::string indent = " "; // 4 spaces
1632*38e8c45fSAndroid Build Coastguard Worker for (const auto& surfaceFrame : mSurfaceFrames) {
1633*38e8c45fSAndroid Build Coastguard Worker surfaceFrame->dump(result, indent, baseTime);
1634*38e8c45fSAndroid Build Coastguard Worker }
1635*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "\n");
1636*38e8c45fSAndroid Build Coastguard Worker }
1637*38e8c45fSAndroid Build Coastguard Worker
dumpAll(std::string & result)1638*38e8c45fSAndroid Build Coastguard Worker void FrameTimeline::dumpAll(std::string& result) {
1639*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock lock(mMutex);
1640*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "Number of display frames : %d\n", (int)mDisplayFrames.size());
1641*38e8c45fSAndroid Build Coastguard Worker nsecs_t baseTime = (mDisplayFrames.empty()) ? 0 : mDisplayFrames[0]->getBaseTime();
1642*38e8c45fSAndroid Build Coastguard Worker for (size_t i = 0; i < mDisplayFrames.size(); i++) {
1643*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "Display Frame %d", static_cast<int>(i));
1644*38e8c45fSAndroid Build Coastguard Worker mDisplayFrames[i]->dumpAll(result, baseTime);
1645*38e8c45fSAndroid Build Coastguard Worker }
1646*38e8c45fSAndroid Build Coastguard Worker }
1647*38e8c45fSAndroid Build Coastguard Worker
dumpJank(std::string & result)1648*38e8c45fSAndroid Build Coastguard Worker void FrameTimeline::dumpJank(std::string& result) {
1649*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock lock(mMutex);
1650*38e8c45fSAndroid Build Coastguard Worker nsecs_t baseTime = (mDisplayFrames.empty()) ? 0 : mDisplayFrames[0]->getBaseTime();
1651*38e8c45fSAndroid Build Coastguard Worker for (size_t i = 0; i < mDisplayFrames.size(); i++) {
1652*38e8c45fSAndroid Build Coastguard Worker mDisplayFrames[i]->dumpJank(result, baseTime, static_cast<int>(i));
1653*38e8c45fSAndroid Build Coastguard Worker }
1654*38e8c45fSAndroid Build Coastguard Worker }
1655*38e8c45fSAndroid Build Coastguard Worker
parseArgs(const Vector<String16> & args,std::string & result)1656*38e8c45fSAndroid Build Coastguard Worker void FrameTimeline::parseArgs(const Vector<String16>& args, std::string& result) {
1657*38e8c45fSAndroid Build Coastguard Worker SFTRACE_CALL();
1658*38e8c45fSAndroid Build Coastguard Worker std::unordered_map<std::string, bool> argsMap;
1659*38e8c45fSAndroid Build Coastguard Worker for (size_t i = 0; i < args.size(); i++) {
1660*38e8c45fSAndroid Build Coastguard Worker argsMap[std::string(String8(args[i]).c_str())] = true;
1661*38e8c45fSAndroid Build Coastguard Worker }
1662*38e8c45fSAndroid Build Coastguard Worker if (argsMap.count("-jank")) {
1663*38e8c45fSAndroid Build Coastguard Worker dumpJank(result);
1664*38e8c45fSAndroid Build Coastguard Worker }
1665*38e8c45fSAndroid Build Coastguard Worker if (argsMap.count("-all")) {
1666*38e8c45fSAndroid Build Coastguard Worker dumpAll(result);
1667*38e8c45fSAndroid Build Coastguard Worker }
1668*38e8c45fSAndroid Build Coastguard Worker }
1669*38e8c45fSAndroid Build Coastguard Worker
setMaxDisplayFrames(uint32_t size)1670*38e8c45fSAndroid Build Coastguard Worker void FrameTimeline::setMaxDisplayFrames(uint32_t size) {
1671*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock lock(mMutex);
1672*38e8c45fSAndroid Build Coastguard Worker
1673*38e8c45fSAndroid Build Coastguard Worker // The size can either increase or decrease, clear everything, to be consistent
1674*38e8c45fSAndroid Build Coastguard Worker mDisplayFrames.clear();
1675*38e8c45fSAndroid Build Coastguard Worker mPendingPresentFences.clear();
1676*38e8c45fSAndroid Build Coastguard Worker mMaxDisplayFrames = size;
1677*38e8c45fSAndroid Build Coastguard Worker }
1678*38e8c45fSAndroid Build Coastguard Worker
reset()1679*38e8c45fSAndroid Build Coastguard Worker void FrameTimeline::reset() {
1680*38e8c45fSAndroid Build Coastguard Worker setMaxDisplayFrames(kDefaultMaxDisplayFrames);
1681*38e8c45fSAndroid Build Coastguard Worker }
1682*38e8c45fSAndroid Build Coastguard Worker
1683*38e8c45fSAndroid Build Coastguard Worker } // namespace impl
1684*38e8c45fSAndroid Build Coastguard Worker } // namespace android::frametimeline
1685