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):