xref: /aosp_15_r20/frameworks/native/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
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