@@ -231,3 +231,88 @@ WITH
231231 main_thread_boundary .ts
232232 )
233233SELECT * , ts_end - ts AS dur FROM boundary_base;
234+
235+
236+ -- Similar to `_android_jank_cuj_main_thread_frame_boundary` but for the render
237+ -- thread the expected start time is the time of the first `postAndWait` slice
238+ -- on the main thread.
239+ -- The query is slightly simpler because we don't have to handle the clock drift
240+ -- and data loss like with the frame timeline.
241+ -- One difference vs main thread is that there might be multiple DrawFrames
242+ -- slices for a single vsync - this happens when we are drawing multiple layers
243+ -- (e.g. status bar & notifications).
244+ CREATE PERFETTO TABLE _android_jank_cuj_render_thread_frame_boundary(
245+ -- CUJ id.
246+ cuj_id LONG,
247+ -- Thread id of the render thread.
248+ utid JOINID(thread .id ),
249+ -- Vsync ID of this frame.
250+ vsync LONG,
251+ -- Expected start timestamp (first postAndWait slice).
252+ ts_expected TIMESTAMP ,
253+ -- Start timestamp of the DrawFrame slice.
254+ ts_draw_frame_start TIMESTAMP ,
255+ -- End timestamp of the previous DrawFrame slice.
256+ ts_prev_draw_frame_end TIMESTAMP ,
257+ -- Corrected start timestamp for the frame boundary.
258+ ts TIMESTAMP ,
259+ -- End timestamp of the DrawFrame slice.
260+ ts_end TIMESTAMP ,
261+ -- Duration of the frame boundary.
262+ dur DURATION
263+ )
264+ AS
265+ -- see do_frame_ordered above
266+ -- we also order by `ts` to handle multiple DrawFrames for a single vsync
267+ WITH draw_frame_ordered AS (
268+ SELECT
269+ * ,
270+ -- ts_end of the previous draw frame, or -1 if no previous draw frame found
271+ COALESCE(LAG(ts_end) OVER (PARTITION BY cuj_id ORDER BY vsync ASC , ts ASC ), - 1 ) AS ts_prev_draw_frame_end
272+ FROM _android_jank_cuj_draw_frame_slice
273+ ),
274+ -- introducing an intermediate table since we want to calculate dur = ts_end - ts
275+ frame_boundary_base AS (
276+ SELECT
277+ draw_frame .cuj_id ,
278+ draw_frame .utid ,
279+ draw_frame .vsync ,
280+ MIN (post_and_wait .ts ) AS ts_expected,
281+ MIN (draw_frame .ts ) AS ts_draw_frame_start,
282+ MIN (draw_frame .ts_prev_draw_frame_end ) AS ts_prev_draw_frame_end,
283+ MIN (
284+ MAX (
285+ MIN (post_and_wait .ts ),
286+ MIN (draw_frame .ts_prev_draw_frame_end )),
287+ MIN (draw_frame .ts )) AS ts,
288+ MAX (draw_frame .ts_end ) AS ts_end
289+ FROM draw_frame_ordered draw_frame
290+ JOIN _android_jank_cuj_do_frames do_frame USING (cuj_id, vsync)
291+ JOIN descendant_slice(do_frame .id ) post_and_wait
292+ WHERE post_and_wait .name = ' postAndWait'
293+ GROUP BY draw_frame .cuj_id , draw_frame .utid , draw_frame .vsync
294+ )
295+ SELECT * , ts_end - ts AS dur FROM frame_boundary_base;
296+
297+ -- Compute the CUJ boundary on the render thread from the frame boundaries.
298+ CREATE PERFETTO TABLE _android_jank_cuj_render_thread_cuj_boundary(
299+ -- CUJ id.
300+ cuj_id LONG,
301+ -- Thread id of the render thread.
302+ utid JOINID(thread .id ),
303+ -- Start timestamp of the CUJ on the render thread.
304+ ts TIMESTAMP ,
305+ -- End timestamp of the CUJ on the render thread.
306+ ts_end TIMESTAMP ,
307+ -- Duration of the CUJ on the render thread.
308+ dur DURATION
309+ )
310+ AS
311+ SELECT
312+ cuj_id,
313+ utid,
314+ MIN (ts) AS ts,
315+ MAX (ts_end) AS ts_end,
316+ MAX (ts_end) - MIN (ts) AS dur
317+ FROM _android_jank_cuj_render_thread_frame_boundary
318+ GROUP BY cuj_id, utid;
0 commit comments