Merge "tp: implement wrapper around sqlite window functions" into main
diff --git a/Android.bp b/Android.bp
index 1a7fd1d..d5da1dd 100644
--- a/Android.bp
+++ b/Android.bp
@@ -15548,12 +15548,6 @@
     defaults: [
         "perfetto_defaults",
     ],
-    required: [
-        "libperfetto_android_internal",
-        "mm_events",
-        "traced_perf",
-        "trigger_perfetto",
-    ],
     target: {
         android: {
             shared_libs: [
@@ -15921,3 +15915,13 @@
     sub_dir: "perfetto",
     src: "persistent_cfg.pbtxt",
 }
+
+phony {
+    name: "perfetto-extras",
+    required: [
+        "libperfetto_android_internal",
+        "mm_events",
+        "traced_perf",
+        "trigger_perfetto",
+    ],
+}
diff --git a/Android.bp.extras b/Android.bp.extras
index 2ce8e95..3aab5af 100644
--- a/Android.bp.extras
+++ b/Android.bp.extras
@@ -205,3 +205,13 @@
     sub_dir: "perfetto",
     src: "persistent_cfg.pbtxt",
 }
+
+phony {
+    name: "perfetto-extras",
+    required: [
+        "libperfetto_android_internal",
+        "mm_events",
+        "traced_perf",
+        "trigger_perfetto",
+    ],
+}
diff --git a/src/trace_processor/perfetto_sql/stdlib/sched/thread_executing_span.sql b/src/trace_processor/perfetto_sql/stdlib/sched/thread_executing_span.sql
index 19f68c2..348d261 100644
--- a/src/trace_processor/perfetto_sql/stdlib/sched/thread_executing_span.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/sched/thread_executing_span.sql
@@ -41,10 +41,13 @@
   thread_state.dur,
   thread_state.state,
   thread_state.utid,
+  thread_state.waker_id,
   thread_state.waker_utid
 FROM thread_state
-WHERE thread_state.dur != -1 AND thread_state.waker_utid IS NOT NULL
-   AND (thread_state.irq_context = 0 OR thread_state.irq_context IS NULL);
+WHERE
+  thread_state.dur != -1
+  AND thread_state.waker_utid IS NOT NULL
+  AND (thread_state.irq_context = 0 OR thread_state.irq_context IS NULL);
 
 -- Similar to |_runnable_state| but finds the first runnable state at thread.
 CREATE PERFETTO VIEW _first_runnable_state
@@ -62,10 +65,15 @@
   thread_state.dur,
   thread_state.state,
   thread_state.utid,
+  thread_state.waker_id,
   thread_state.waker_utid
 FROM thread_state
-JOIN first_state USING (id)
-WHERE thread_state.dur != -1 AND thread_state.state = 'R' AND (thread_state.irq_context = 0 OR thread_state.irq_context IS NULL);
+JOIN first_state
+  USING (id)
+WHERE
+  thread_state.dur != -1
+  AND thread_state.state = 'R'
+  AND (thread_state.irq_context = 0 OR thread_state.irq_context IS NULL);
 
 --
 -- Finds all sleep states including interruptible (S) and uninterruptible (D).
@@ -125,82 +133,71 @@
 --
 -- We define the following markers in this table:
 --
--- prev_start_id    = R0_id.
--- prev_start_ts    = R0_ts.
--- prev_start_dur   = R0_dur.
--- prev_start_state = 'R'.
+-- prev_id          = R0_id.
 --
--- prev_end_id      = S0_id.
 -- prev_end_ts      = S0_ts.
--- prev_end_dur     = S0_dur.
--- prev_end_state   = 'S' or 'D'.
+-- state            = 'S' or 'D'.
+-- blocked_function = <kernel blocking function>
 --
--- start_id         = R1_id.
--- start_ts         = R1_ts.
--- start_dur        = R1_dur.
--- start_state      = 'R'.
+-- id               = R1_id.
+-- ts               = R1_ts.
 --
--- end_id           = S1_id.
 -- end_ts           = S1_ts.
--- end_dur          = S1_dur.
--- end_state        = 'S' or 'D'.
-CREATE TABLE _wakeup AS
-  SELECT
-  LAG(r.id, 1) OVER (PARTITION BY r.utid ORDER BY r.ts) AS prev_start_id,
-  LAG(r.ts, 1) OVER (PARTITION BY r.utid ORDER BY r.ts) AS prev_start_ts,
-  LAG(r.dur, 1) OVER (PARTITION BY r.utid ORDER BY r.ts) AS prev_start_dur,
-  LAG(r.state, 1) OVER (PARTITION BY r.utid ORDER BY r.ts) AS prev_start_state,
-  s.id AS prev_end_id,
-  s.ts AS prev_end_ts,
-  s.dur AS prev_end_dur,
-  s.state AS prev_end_state,
-  s.blocked_function AS prev_blocked_function,
-  r.id AS start_id,
-  r.ts AS start_ts,
-  r.dur AS start_dur,
-  r.state AS start_state,
+CREATE PERFETTO TABLE _wakeup
+AS
+SELECT
+  s.state,
+  s.blocked_function,
+  r.id,
+  r.ts AS ts,
   r.utid AS utid,
+  r.waker_id,
   r.waker_utid,
-  LEAD(s.id, 1) OVER (PARTITION BY r.utid ORDER BY r.ts) AS end_id,
-  IFNULL(LEAD(s.ts, 1) OVER (PARTITION BY r.utid ORDER BY r.ts), thread_end.end_ts)  AS end_ts,
-  LEAD(s.dur, 1) OVER (PARTITION BY r.utid ORDER BY r.ts) AS end_dur,
-  LEAD(s.state, 1) OVER (PARTITION BY r.utid ORDER BY r.ts) AS end_state,
-  LEAD(s.blocked_function, 1) OVER (PARTITION BY r.utid ORDER BY r.ts) AS blocked_function
+  IFNULL(LEAD(s.ts) OVER (PARTITION BY r.utid ORDER BY r.ts), thread_end.end_ts) AS end_ts,
+  s.ts AS prev_end_ts,
+  LAG(r.id) OVER (PARTITION BY r.utid ORDER BY r.ts) AS prev_id
 FROM _runnable_state r
 JOIN _sleep_state s
   ON s.utid = r.utid AND (s.ts + s.dur = r.ts)
-LEFT JOIN _thread_end_ts thread_end USING(utid)
+LEFT JOIN _thread_end_ts thread_end
+  USING (utid)
 UNION ALL
-  SELECT
-  NULL AS prev_start_id,
-  NULL AS prev_start_ts,
-  NULL AS prev_start_dur,
-  NULL AS prev_start_state,
-  NULL AS prev_end_id,
-  NULL AS prev_end_ts,
-  NULL AS prev_end_dur,
-  NULL AS prev_end_state,
-  NULL AS prev_blocked_function,
-  r.id AS start_id,
-  r.ts AS start_ts,
-  r.dur AS start_dur,
-  r.state AS start_state,
+SELECT
+  NULL AS state,
+  NULL AS blocked_function,
+  r.id,
+  r.ts,
   r.utid AS utid,
+  r.waker_id,
   r.waker_utid,
-  s.id AS end_id,
-  IFNULL(s.ts, thread_end.end_ts)  AS end_ts,
-  s.dur AS end_dur,
-  s.state AS end_state,
-  s.blocked_function AS blocked_function
+  IFNULL(s.ts, thread_end.end_ts) AS end_ts,
+  NULL AS prev_end_ts,
+  NULL AS prev_id
 FROM _first_runnable_state r
 LEFT JOIN _first_sleep_state s
   ON s.utid = r.utid
-LEFT JOIN _thread_end_ts thread_end USING(utid);
+LEFT JOIN _thread_end_ts thread_end
+  USING (utid);
 
--- Improves performance of |_wakeup_chain| computation.
-CREATE
-  INDEX _wakeup_idx
-ON _wakeup(waker_utid, start_ts);
+-- Mapping from running thread state to runnable
+CREATE PERFETTO TABLE _waker_map
+AS
+WITH x AS (
+SELECT id, waker_id, utid, state FROM thread_state WHERE state = 'Running' AND dur != -1
+UNION ALL
+SELECT id, waker_id, utid, state FROM _first_runnable_state
+UNION ALL
+SELECT id, waker_id, utid, state FROM _runnable_state
+), y AS (
+    SELECT
+      id AS waker_id,
+      state,
+      max(id)
+        filter(WHERE state = 'R')
+          OVER (PARTITION BY utid ORDER BY id) AS id
+    FROM x
+  )
+SELECT id, waker_id FROM y WHERE state = 'Running' AND id IS NOT NULL ORDER BY waker_id;
 
 --
 -- Builds the parent-child chain from all thread_executing_spans. The parent is the waker and
@@ -209,14 +206,38 @@
 -- Note that this doesn't include the roots. We'll compute the roots below.
 -- This two step process improves performance because it's more efficient to scan
 -- parent and find a child between than to scan child and find the parent it lies between.
-CREATE PERFETTO VIEW _wakeup_chain
+CREATE PERFETTO TABLE _wakeup_chain
 AS
-SELECT parent.start_id AS parent_id, child.*
-FROM _wakeup parent
-JOIN _wakeup child
-  ON (
-    parent.utid = child.waker_utid
-    AND child.start_ts BETWEEN parent.start_ts AND parent.end_ts);
+SELECT
+  _waker_map.id AS parent_id,
+  prev_id,
+  prev_end_ts,
+  _wakeup.id AS id,
+  _wakeup.ts AS ts,
+  _wakeup.end_ts,
+  IIF(_wakeup.state IS NULL OR _wakeup.state = 'S', 0, 1) AS is_kernel,
+  _wakeup.utid,
+  _wakeup.state,
+  _wakeup.blocked_function
+FROM _wakeup
+JOIN _waker_map USING(waker_id);
+
+-- The inverse of thread_executing_spans. All the sleeping periods between thread_executing_spans.
+CREATE PERFETTO TABLE _sleeping_span
+AS
+WITH
+  x AS (
+    SELECT
+      id,
+      ts,
+      lag(end_ts) OVER (PARTITION BY utid ORDER BY id) AS prev_end_ts,
+      utid
+    FROM _wakeup_chain
+  )
+SELECT
+  ts - prev_end_ts AS dur, prev_end_ts AS ts, id AS root_id, utid AS root_utid
+FROM x
+WHERE ts IS NOT NULL;
 
 --
 -- Finds the roots of the |_wakeup_chain|.
@@ -226,37 +247,56 @@
   _wakeup_root_id AS (
     SELECT DISTINCT parent_id AS id FROM _wakeup_chain
     EXCEPT
-    SELECT DISTINCT start_id AS id FROM _wakeup_chain
+    SELECT DISTINCT id FROM _wakeup_chain
   )
 SELECT NULL AS parent_id, _wakeup.*
 FROM _wakeup
-JOIN _wakeup_root_id
-  ON _wakeup_root_id.id = _wakeup.start_id;
+JOIN _wakeup_root_id USING(id);
 
 --
 -- Finds the leafs of the |_wakeup_chain|.
 CREATE PERFETTO TABLE _wakeup_leaf AS
 WITH
   _wakeup_leaf_id AS (
-    SELECT DISTINCT start_id AS id FROM _wakeup_chain
+    SELECT DISTINCT id AS id FROM _wakeup_chain
     EXCEPT
     SELECT DISTINCT parent_id AS id FROM _wakeup_chain
   )
 SELECT _wakeup_chain.*
 FROM _wakeup_chain
-JOIN _wakeup_leaf_id
-  ON _wakeup_leaf_id.id = _wakeup_chain.start_id;
+JOIN _wakeup_leaf_id USING(id);
 
 --
 -- Merges the roots, leafs and the rest of the chain.
 CREATE TABLE _wakeup_graph
 AS
-SELECT _wakeup_chain.*, 0 AS is_root, (_wakeup_leaf.start_id IS NOT NULL) AS is_leaf
+SELECT
+  _wakeup_chain.parent_id,
+  _wakeup_chain.id,
+  _wakeup_chain.ts,
+  _wakeup_chain.end_ts - _wakeup_chain.ts AS dur,
+  _wakeup_chain.utid,
+  _wakeup_chain.prev_end_ts,
+  _wakeup_chain.state,
+  _wakeup_chain.blocked_function,
+  0 AS is_root,
+  (_wakeup_leaf.id IS NOT NULL) AS is_leaf
 FROM _wakeup_chain
 LEFT JOIN _wakeup_leaf
-  USING (start_id)
+  USING (id)
 UNION ALL
-SELECT *, 1 AS is_root, 0 AS is_leaf FROM _wakeup_root;
+SELECT
+  _wakeup_root.parent_id,
+  _wakeup_root.id,
+  _wakeup_root.ts,
+  _wakeup_root.end_ts - _wakeup_root.ts AS dur,
+  _wakeup_root.utid,
+  _wakeup_root.prev_end_ts,
+  _wakeup_root.state,
+  _wakeup_root.blocked_function,
+  1 AS is_root,
+  0 AS is_leaf
+FROM _wakeup_root;
 
 -- Thread_executing_span graph of all wakeups across all processes.
 --
@@ -266,7 +306,6 @@
 -- @column ts                 Timestamp of first thread_state in thread_executing_span.
 -- @column dur                Duration of thread_executing_span.
 -- @column utid               Utid of thread with thread_state.
--- @column waker_utid         Utid of thread that woke the first thread_state in thread_executing_span.
 -- @column blocked_dur        Duration of blocking thread state before waking up.
 -- @column blocked_state      Thread state ('D' or 'S') of blocked thread_state before waking up.
 -- @column blocked_function   Kernel blocked_function of thread state before waking up.
@@ -275,16 +314,15 @@
 CREATE TABLE _thread_executing_span_graph AS
 WITH roots AS (
 SELECT
-  start_id AS root_id,
+  id AS root_id,
   parent_id,
-  start_id AS id,
-  start_ts AS ts,
-  end_ts - start_ts AS dur,
+  id,
+  ts,
+  end_ts - ts AS dur,
   utid,
-  waker_utid,
-  prev_end_dur AS blocked_dur,
-  prev_end_state AS blocked_state,
-  prev_blocked_function AS blocked_function,
+  ts - prev_end_ts AS blocked_dur,
+  state AS blocked_state,
+  blocked_function AS blocked_function,
   1 AS is_root,
   0 AS depth
 FROM _wakeup_root
@@ -294,14 +332,13 @@
   SELECT
     chain.root_id,
     graph.parent_id,
-    graph.start_id AS id,
-    graph.start_ts AS ts,
-    graph.end_ts - graph.start_ts AS dur,
+    graph.id,
+    graph.ts,
+    graph.dur,
     graph.utid,
-    graph.waker_utid,
-    graph.prev_end_dur AS blocked_dur,
-    graph.prev_end_state AS blocked_state,
-    graph.prev_blocked_function AS blocked_function,
+    graph.ts - graph.prev_end_ts AS blocked_dur,
+    graph.state AS blocked_state,
+    graph.blocked_function AS blocked_function,
     0 AS is_root,
     chain.depth + 1 AS depth
   FROM _wakeup_graph graph
diff --git a/test/trace_processor/diff_tests/tables/tests_sched.py b/test/trace_processor/diff_tests/tables/tests_sched.py
index 46ff428..71ca6ab 100644
--- a/test/trace_processor/diff_tests/tables/tests_sched.py
+++ b/test/trace_processor/diff_tests/tables/tests_sched.py
@@ -152,7 +152,6 @@
           ts,
           dur,
           utid,
-          waker_utid,
           blocked_dur,
           blocked_state,
           blocked_function,
@@ -164,17 +163,17 @@
         LIMIT 10
         """,
         out=Csv("""
-        "root_id","parent_id","id","ts","dur","utid","waker_utid","blocked_dur","blocked_state","blocked_function","is_root","depth"
-        357,377,380,1735842234188,283571,46,427,351402620,"I","worker_thread",0,5
-        394,402,405,1735843726296,8545303,46,427,1208537,"I","worker_thread",0,3
-        357,419,432,1735850643698,16245,95,1465,154087,"I","worker_thread",0,4
-        357,443,446,1735851953029,554638012,95,427,1103252,"I","worker_thread",0,6
-        357,500,503,1735886367018,191863,46,427,34095419,"I","worker_thread",0,10
-        357,446,667,1736125372478,52493,46,95,238813597,"I","worker_thread",0,7
-        357,835,838,1736405409972,278036,46,427,279985001,"I","worker_thread",0,12
-        357,862,865,1736406817672,7959441,46,427,1129664,"I","worker_thread",0,10
-        357,882,889,1736413734042,25870,95,1467,7143001,"I","worker_thread",0,11
-        357,882,894,1736413763072,31692550,11,1467,4413060,"I","rcu_gp_fqs_loop",0,11
+        "root_id","parent_id","id","ts","dur","utid","blocked_dur","blocked_state","blocked_function","is_root","depth"
+        357,377,380,1735842234188,283571,46,351402620,"I","worker_thread",0,5
+        394,402,405,1735843726296,8545303,46,1208537,"I","worker_thread",0,3
+        357,419,432,1735850643698,16245,95,154087,"I","worker_thread",0,4
+        357,443,446,1735851953029,554638012,95,1103252,"I","worker_thread",0,6
+        357,500,503,1735886367018,191863,46,34095419,"I","worker_thread",0,10
+        357,446,667,1736125372478,52493,46,238813597,"I","worker_thread",0,7
+        357,835,838,1736405409972,278036,46,279985001,"I","worker_thread",0,12
+        357,862,865,1736406817672,7959441,46,1129664,"I","worker_thread",0,10
+        357,882,889,1736413734042,25870,95,7143001,"I","worker_thread",0,11
+        357,882,894,1736413763072,31692550,11,4413060,"I","rcu_gp_fqs_loop",0,11
         """))
 
   def test_thread_executing_span_graph_contains_forked_states(self):
@@ -189,7 +188,6 @@
           ts,
           dur,
           utid,
-          waker_utid,
           blocked_dur,
           blocked_state,
           blocked_function,
@@ -199,8 +197,8 @@
           WHERE ts = 1735842081507 AND dur = 293868
         """,
         out=Csv("""
-        "root_id","parent_id","id","ts","dur","utid","waker_utid","blocked_dur","blocked_state","blocked_function","is_root","depth"
-        357,369,376,1735842081507,293868,1465,230,"[NULL]","[NULL]","[NULL]",0,4
+        "root_id","parent_id","id","ts","dur","utid","blocked_dur","blocked_state","blocked_function","is_root","depth"
+        357,369,376,1735842081507,293868,1465,"[NULL]","[NULL]","[NULL]",0,4
         """))
 
   def test_thread_executing_span_runnable_state_has_no_running(self):
diff --git a/tools/check_sql_modules.py b/tools/check_sql_modules.py
index ff21b4f..935bf9e 100755
--- a/tools/check_sql_modules.py
+++ b/tools/check_sql_modules.py
@@ -44,10 +44,8 @@
         '_chrome_mojo_slices', '_chrome_java_views', '_chrome_scheduler_tasks',
         '_chrome_tasks'
     ],
-    '/sched/thread_executing_span.sql': [
-        '_wakeup', '_thread_executing_span_graph', '_critical_path',
-        '_wakeup_graph', '_thread_executing_span_graph'
-    ],
+    '/sched/thread_executing_span.sql': ['_wakeup_graph', '_thread_executing_span_graph',
+        '_critical_path'],
     '/slices/flat_slices.sql': ['_slice_flattened']
 }
 
diff --git a/tools/gen_android_bp b/tools/gen_android_bp
index 561657d..ba5320c 100755
--- a/tools/gen_android_bp
+++ b/tools/gen_android_bp
@@ -245,10 +245,6 @@
         ('test_suites', {'general-tests'}),
         ('test_config', 'PerfettoIntegrationTests.xml'),
     ],
-    'traced_probes': [('required', {
-        'libperfetto_android_internal', 'trigger_perfetto', 'traced_perf',
-        'mm_events'
-    }),],
     'libperfetto_android_internal': [('static_libs', {'libhealthhalutils'}),],
     'trace_processor_shell': [
         ('strip', {