Merge "tp: Add ts, dur, ui_thread_utid and render_thread_utid info to android_frames" into main
diff --git a/src/trace_processor/perfetto_sql/stdlib/android/frames/timeline.sql b/src/trace_processor/perfetto_sql/stdlib/android/frames/timeline.sql
index e6963b2..b492bb3 100644
--- a/src/trace_processor/perfetto_sql/stdlib/android/frames/timeline.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/android/frames/timeline.sql
@@ -42,11 +42,18 @@
-- `slice.id`
id INT,
-- Frame id
- frame_id INT
+ frame_id INT,
+ -- Utid of the UI thread
+ ui_thread_utid INT
) AS
-SELECT * FROM _get_frame_table_with_id('Choreographer#doFrame*');
+SELECT
+ c.*,
+ thread_track.utid AS ui_thread_utid
+FROM _get_frame_table_with_id('Choreographer#doFrame*') c
+JOIN slice USING (id)
+JOIN thread_track ON (thread_track.id = slice.track_id);
--- All of the `DrawFrame` slices with their frame id.
+-- All of the `DrawFrame` slices with their frame id and render thread.
-- There might be multiple DrawFrames slices for a single vsync (frame id).
-- This happens when we are drawing multiple layers (e.g. status bar and
-- notifications).
@@ -54,16 +61,25 @@
-- `slice.id`
id INT,
-- Frame id
- frame_id INT
+ frame_id INT,
+ -- Utid of the render thread
+ render_thread_utid INT
) AS
-SELECT * FROM _get_frame_table_with_id('DrawFrame*');
+SELECT
+ d.*,
+ thread_track.utid AS render_thread_utid
+FROM _get_frame_table_with_id('DrawFrame*') d
+JOIN slice USING (id)
+JOIN thread_track ON (thread_track.id = slice.track_id);
-- `actual_frame_timeline_slice` returns the same slice on different tracks.
-- We are getting the first slice with one frame id.
CREATE PERFETTO TABLE _distinct_from_actual_timeline_slice AS
SELECT
id,
- cast_int!(name) AS frame_id
+ cast_int!(name) AS frame_id,
+ ts,
+ dur
FROM actual_frame_timeline_slice
GROUP BY 2;
@@ -79,9 +95,17 @@
-- All slices related to one frame. Aggregates `Choreographer#doFrame`,
-- `DrawFrame`, `actual_frame_timeline_slice` and
-- `expected_frame_timeline_slice` slices.
+-- See https://perfetto.dev/docs/data-sources/frametimeline for details.
CREATE PERFETTO TABLE android_frames(
-- Frame id.
frame_id INT,
+ -- Timestamp of the frame. Start of the frame as defined by the start of
+ -- "Choreographer#doFrame" slice and the same as the start of the frame in
+ -- `actual_frame_timeline_slice .
+ ts INT,
+ -- Duration of the frame, as defined by the duration of the corresponding
+ -- `actual_frame_timeline_slice` duration.
+ dur INT,
-- `slice.id` of "Choreographer#doFrame" slice.
do_frame_id INT,
-- `slice.id` of "DrawFrame" slice.
@@ -89,16 +113,54 @@
-- `slice.id` from `actual_frame_timeline_slice`
actual_frame_timeline_id INT,
-- `slice.id` from `expected_frame_timeline_slice`
- expected_frame_timeline_id INT
+ expected_frame_timeline_id INT,
+ -- `utid` of the render thread.
+ render_thread_utid INT,
+ -- `utid` of the UI thread.
+ ui_thread_utid INT
) AS
SELECT
frame_id,
+ ts,
+ dur,
do_frame.id AS do_frame_id,
draw_frame.id AS draw_frame_id,
act.id AS actual_frame_timeline_id,
- exp.id AS expected_frame_timeline_id
+ exp.id AS expected_frame_timeline_id,
+ draw_frame.render_thread_utid,
+ do_frame.ui_thread_utid
FROM android_frames_choreographer_do_frame do_frame
JOIN android_frames_draw_frame draw_frame USING (frame_id)
JOIN _distinct_from_actual_timeline_slice act USING (frame_id)
JOIN _distinct_from_expected_timeline_slice exp USING (frame_id)
-ORDER BY frame_id;
\ No newline at end of file
+ORDER BY frame_id;
+
+-- Returns first frame after the provided timestamp. The returning table has at
+-- most one row.
+CREATE PERFETTO FUNCTION android_first_frame_after(
+ -- Timestamp.
+ ts INT)
+RETURNS TABLE (
+ -- Frame id.
+ frame_id INT,
+ -- Start of the frame, the timestamp of the "Choreographer#doFrame" slice.
+ ts INT,
+ -- Duration of the frame.
+ dur INT,
+ -- `slice.id` of "Choreographer#doFrame" slice.
+ do_frame_id INT,
+ -- `slice.id` of "DrawFrame" slice.
+ draw_frame_id INT,
+ -- `slice.id` from `actual_frame_timeline_slice`
+ actual_frame_timeline_id INT,
+ -- `slice.id` from `expected_frame_timeline_slice`
+ expected_frame_timeline_id INT,
+ -- `utid` of the render thread.
+ render_thread_utid INT,
+ -- `utid` of the UI thread.
+ ui_thread_utid INT
+) AS
+SELECT * FROM android_frames
+WHERE ts > $ts
+ORDER BY ts
+LIMIT 1;
\ No newline at end of file
diff --git a/test/data/android_startup_real.perfetto_trace.sha256 b/test/data/android_startup_real.perfetto_trace.sha256
new file mode 100644
index 0000000..e07d671
--- /dev/null
+++ b/test/data/android_startup_real.perfetto_trace.sha256
@@ -0,0 +1 @@
+e5dcbdf8b87cea287268648d89262e8eeafd975e195d9ef9b14e574ce176ede3
\ No newline at end of file
diff --git a/test/trace_processor/diff_tests/stdlib/android/frames_tests.py b/test/trace_processor/diff_tests/stdlib/android/frames_tests.py
index 687afde..eb6e6d0 100644
--- a/test/trace_processor/diff_tests/stdlib/android/frames_tests.py
+++ b/test/trace_processor/diff_tests/stdlib/android/frames_tests.py
@@ -30,22 +30,22 @@
SELECT * FROM android_frames_choreographer_do_frame;
""",
out=Csv("""
- "id","frame_id"
- 2,10
- 15,20
- 22,30
- 35,40
- 46,60
- 55,90
- 63,100
- 73,110
- 79,120
- 87,130
- 93,140
- 99,145
- 102,150
- 108,160
- 140,1000
+ "id","frame_id","ui_thread_utid"
+ 2,10,2
+ 15,20,2
+ 22,30,2
+ 35,40,2
+ 46,60,2
+ 55,90,2
+ 63,100,2
+ 73,110,2
+ 79,120,2
+ 87,130,2
+ 93,140,2
+ 99,145,2
+ 102,150,2
+ 108,160,2
+ 140,1000,2
"""))
def test_android_frames_draw_frame(self):
@@ -57,24 +57,24 @@
SELECT * FROM android_frames_draw_frame;
""",
out=Csv("""
- "id","frame_id"
- 8,10
- 16,20
- 23,30
- 41,40
- 50,60
- 57,90
- 60,90
- 66,100
- 69,100
- 74,110
- 80,120
- 89,130
- 95,140
- 100,145
- 105,150
- 109,160
- 146,1000
+ "id","frame_id","render_thread_utid"
+ 8,10,4
+ 16,20,4
+ 23,30,4
+ 41,40,4
+ 50,60,4
+ 57,90,4
+ 60,90,4
+ 66,100,4
+ 69,100,4
+ 74,110,4
+ 80,120,4
+ 89,130,4
+ 95,140,4
+ 100,145,4
+ 105,150,4
+ 109,160,4
+ 146,1000,4
"""))
def test_android_frames(self):
@@ -86,24 +86,37 @@
SELECT * FROM android_frames;
""",
out=Csv("""
- "frame_id","do_frame_id","draw_frame_id","actual_frame_timeline_id","expected_frame_timeline_id"
- 10,2,8,1,0
- 20,15,16,12,11
- 30,22,23,21,20
- 40,35,41,37,36
- 60,46,50,48,47
- 90,55,57,54,53
- 90,55,60,54,53
- 100,63,66,65,64
- 100,63,69,65,64
- 110,73,74,71,70
- 120,79,80,78,77
- 130,87,89,85,84
- 140,93,95,94,91
- 145,99,100,98,97
- 150,102,105,104,103
- 160,108,109,132,107
- 1000,140,146,138,137
+ "frame_id","ts","dur","do_frame_id","draw_frame_id","actual_frame_timeline_id","expected_frame_timeline_id","render_thread_utid","ui_thread_utid"
+ 10,0,16000000,2,8,1,0,4,2
+ 20,8000000,28000000,15,16,12,11,4,2
+ 30,30000000,25000000,22,23,21,20,4,2
+ 40,40000000,40000000,35,41,37,36,4,2
+ 60,70000000,10000000,46,50,48,47,4,2
+ 90,100000000,23000000,55,57,54,53,4,2
+ 90,100000000,23000000,55,60,54,53,4,2
+ 100,200000000,22000000,63,66,65,64,4,2
+ 100,200000000,22000000,63,69,65,64,4,2
+ 110,300000000,61000000,73,74,71,70,4,2
+ 120,400000000,61000000,79,80,78,77,4,2
+ 130,500000000,2000000,87,89,85,84,4,2
+ 140,608600000,17000000,93,95,94,91,4,2
+ 145,650000000,20000000,99,100,98,97,4,2
+ 150,700500000,14500000,102,105,104,103,4,2
+ 160,1070000000,16000000,108,109,132,107,4,2
+ 1000,1100000000,500000000,140,146,138,137,4,2
+ """))
+
+ def test_android_first_frame_after(self):
+ return DiffTestBlueprint(
+ trace=Path('../../metrics/graphics/android_jank_cuj.py'),
+ query="""
+ INCLUDE PERFETTO MODULE android.frames.timeline;
+
+ SELECT frame_id FROM android_first_frame_after(100000000);
+ """,
+ out=Csv("""
+ "frame_id"
+ 100
"""))
def test_android_frames_overrun(self):