ui: tp: Add DrawFrames and SurfaceFlinger to AndroidFrames extension
diff --git a/src/trace_processor/perfetto_sql/stdlib/android/input.sql b/src/trace_processor/perfetto_sql/stdlib/android/input.sql
index 09d2d67..8785ee2 100644
--- a/src/trace_processor/perfetto_sql/stdlib/android/input.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/android/input.sql
@@ -15,6 +15,8 @@
 
 INCLUDE PERFETTO MODULE android.frames.timeline;
 
+INCLUDE PERFETTO MODULE android.surfaceflinger;
+
 INCLUDE PERFETTO MODULE intervals.intersect;
 
 INCLUDE PERFETTO MODULE slices.with_context;
@@ -607,13 +609,65 @@
 WHERE
   $slice_id IN (s_read.id, s_disp.id, s_recv.id, s_cons.id);
 
-CREATE PERFETTO VIEW _android_input_frames AS
+CREATE PERFETTO TABLE _input_sf_composite AS
 SELECT
-  chor.upid,
-  chor.frame_id,
+  s.id,
+  s.track_id,
+  s.ts,
+  s.dur,
+  cast_int!(STR_SPLIT(s.name, ' ', 1)) AS vsync_id
+FROM slice AS s
+JOIN thread_track AS t
+  ON s.track_id = t.id
+JOIN thread USING (utid)
+JOIN process USING (upid)
+WHERE
+  process.name = '/system/bin/surfaceflinger'
+  AND thread.is_main_thread
+  AND s.name GLOB 'composite *';
+
+CREATE PERFETTO INDEX _input_sf_composite_idx ON _input_sf_composite(vsync_id);
+
+CREATE PERFETTO TABLE _input_sf_resolved AS
+SELECT m.app_upid, m.app_vsync, s.id, s.track_id, s.ts, s.dur
+FROM android_app_to_sf_frame_timeline_match AS m
+JOIN _input_sf_composite AS s ON s.vsync_id = m.sf_vsync;
+
+CREATE PERFETTO INDEX _input_sf_resolved_idx ON _input_sf_resolved(id);
+
+CREATE PERFETTO VIEW _android_input_frames AS
+WITH
+  all_frame_keys AS (
+    SELECT frame_id, upid FROM android_frames_choreographer_do_frame
+    UNION
+    SELECT frame_id, upid FROM android_frames_draw_frame
+    UNION
+    SELECT app_vsync AS frame_id, app_upid AS upid FROM _input_sf_resolved
+  )
+SELECT
+  k.upid,
+  k.frame_id,
   chor.id AS id_do_frame,
   s_chor.track_id AS track_do_frame,
   chor.ts AS ts_do_frame,
-  s_chor.dur AS dur_do_frame
-FROM android_frames_choreographer_do_frame AS chor
-JOIN slice AS s_chor ON s_chor.id = chor.id;
+  s_chor.dur AS dur_do_frame,
+  d.id AS id_draw_frames,
+  s_draw.track_id AS track_draw_frames,
+  s_draw.ts AS ts_draw_frames,
+  s_draw.dur AS dur_draw_frames,
+  sf.id AS id_sf,
+  sf.track_id AS track_sf,
+  sf.ts AS ts_sf,
+  sf.dur AS dur_sf
+FROM all_frame_keys AS k
+LEFT JOIN android_frames_choreographer_do_frame AS chor
+  ON chor.frame_id = k.frame_id
+  AND chor.upid = k.upid
+LEFT JOIN slice AS s_chor ON s_chor.id = chor.id
+LEFT JOIN android_frames_draw_frame AS d
+  ON d.frame_id = k.frame_id
+  AND d.upid = k.upid
+LEFT JOIN slice AS s_draw ON s_draw.id = d.id
+LEFT JOIN _input_sf_resolved AS sf
+  ON sf.app_vsync = k.frame_id
+  AND sf.app_upid = k.upid;
diff --git a/ui/src/plugins/com.android.AndroidInputLifecycle/extensions/android_frames_extension.ts b/ui/src/plugins/com.android.AndroidInputLifecycle/extensions/android_frames_extension.ts
index 1328cbb..58717cc 100644
--- a/ui/src/plugins/com.android.AndroidInputLifecycle/extensions/android_frames_extension.ts
+++ b/ui/src/plugins/com.android.AndroidInputLifecycle/extensions/android_frames_extension.ts
@@ -52,6 +52,24 @@
         tsField: 'ts_do_frame',
         durField: 'dur_do_frame',
       },
+      {
+        key: 'draw_frames',
+        headerName: 'DrawFrames',
+        sequenceNumber: 6000,
+        idField: 'id_draw_frames',
+        trackField: 'track_draw_frames',
+        tsField: 'ts_draw_frames',
+        durField: 'dur_draw_frames',
+      },
+      {
+        key: 'sf',
+        headerName: 'SurfaceFlinger',
+        sequenceNumber: 7000,
+        idField: 'id_sf',
+        trackField: 'track_sf',
+        tsField: 'ts_sf',
+        durField: 'dur_sf',
+      },
     ];
   }
 
@@ -60,12 +78,25 @@
     sliceId: number,
   ): Promise<string | undefined> {
     const query = `
+      WITH selected_vsync AS (
+        -- Case 1: Selected Choreographer slice
+        SELECT chor.frame_id AS vsync_id, chor.upid
+        FROM android_frames_choreographer_do_frame chor
+        WHERE chor.id = ${sliceId}
+        UNION ALL
+        -- Case 2: Selected DrawFrames slice
+        SELECT d.frame_id AS vsync_id, d.upid
+        FROM android_frames_draw_frame d
+        WHERE d.id = ${sliceId}
+        UNION ALL
+        -- Case 3: Selected SurfaceFlinger composite slice
+        SELECT sf.app_vsync AS vsync_id, sf.app_upid AS upid
+        FROM _input_sf_resolved sf
+        WHERE sf.id = ${sliceId}
+      )
       SELECT e.input_event_id AS input_id
       FROM android_input_events e
-      JOIN android_frames_choreographer_do_frame chor 
-        ON chor.frame_id = e.frame_id
-        AND chor.upid = e.upid
-      WHERE chor.id = ${sliceId}
+      JOIN selected_vsync cv ON e.frame_id = cv.vsync_id AND e.upid = cv.upid
       LIMIT 1
     `;
     const result = await trace.engine.query(query);