tp: Add time module to stdlib

Bug:324801834
Change-Id: I410038c244e9c704f55878f1f063eef646a186f0
diff --git a/Android.bp b/Android.bp
index 6f5ab9a..e37b386 100644
--- a/Android.bp
+++ b/Android.bp
@@ -12004,11 +12004,13 @@
         "src/trace_processor/perfetto_sql/stdlib/linux/cpu_idle.sql",
         "src/trace_processor/perfetto_sql/stdlib/pkvm/hypervisor.sql",
         "src/trace_processor/perfetto_sql/stdlib/prelude/slices.sql",
+        "src/trace_processor/perfetto_sql/stdlib/prelude/trace_bounds.sql",
         "src/trace_processor/perfetto_sql/stdlib/sched/thread_executing_span.sql",
         "src/trace_processor/perfetto_sql/stdlib/sched/thread_level_parallelism.sql",
         "src/trace_processor/perfetto_sql/stdlib/sched/thread_state_flattened.sql",
         "src/trace_processor/perfetto_sql/stdlib/slices/flat_slices.sql",
         "src/trace_processor/perfetto_sql/stdlib/slices/slices.sql",
+        "src/trace_processor/perfetto_sql/stdlib/time/conversion.sql",
     ],
     cmd: "$(location tools/gen_amalgamated_sql.py) --namespace=stdlib --cpp-out=$(out) $(in)",
     out: [
diff --git a/BUILD b/BUILD
index 88b3138..1789e35 100644
--- a/BUILD
+++ b/BUILD
@@ -2364,6 +2364,7 @@
     name = "src_trace_processor_perfetto_sql_stdlib_prelude_prelude",
     srcs = [
         "src/trace_processor/perfetto_sql/stdlib/prelude/slices.sql",
+        "src/trace_processor/perfetto_sql/stdlib/prelude/trace_bounds.sql",
     ],
 )
 
@@ -2386,6 +2387,14 @@
     ],
 )
 
+# GN target: //src/trace_processor/perfetto_sql/stdlib/time:time
+perfetto_filegroup(
+    name = "src_trace_processor_perfetto_sql_stdlib_time_time",
+    srcs = [
+        "src/trace_processor/perfetto_sql/stdlib/time/conversion.sql",
+    ],
+)
+
 # GN target: //src/trace_processor/perfetto_sql/stdlib:stdlib
 perfetto_cc_amalgamated_sql(
     name = "src_trace_processor_perfetto_sql_stdlib_stdlib",
@@ -2403,6 +2412,7 @@
         ":src_trace_processor_perfetto_sql_stdlib_prelude_prelude",
         ":src_trace_processor_perfetto_sql_stdlib_sched_sched",
         ":src_trace_processor_perfetto_sql_stdlib_slices_slices",
+        ":src_trace_processor_perfetto_sql_stdlib_time_time",
     ],
     outs = [
         "src/trace_processor/perfetto_sql/stdlib/stdlib.h",
diff --git a/python/generators/sql_processing/docs_parse.py b/python/generators/sql_processing/docs_parse.py
index 46a6308..ea0b90e 100644
--- a/python/generators/sql_processing/docs_parse.py
+++ b/python/generators/sql_processing/docs_parse.py
@@ -426,13 +426,17 @@
 
 # Reads the provided SQL and, if possible, generates a dictionary with data
 # from documentation together with errors from validation of the schema.
-def parse_file(path: str, sql: str) -> ParsedFile:
+def parse_file(path: str, sql: str) -> Optional[ParsedFile]:
   if sys.platform.startswith('win'):
     path = path.replace('\\', '/')
 
   # Get module name
   module_name = path.split('/stdlib/')[-1].split('/')[0]
 
+  # Disable support for `deprecated` module
+  if module_name == "deprecated":
+    return
+
   # Extract all the docs from the SQL.
   extractor = DocsExtractor(path, module_name, sql)
   docs = extractor.extract()
diff --git a/src/trace_processor/metrics/sql/android/android_cpu_agg.sql b/src/trace_processor/metrics/sql/android/android_cpu_agg.sql
index 71d3847..619d560 100644
--- a/src/trace_processor/metrics/sql/android/android_cpu_agg.sql
+++ b/src/trace_processor/metrics/sql/android/android_cpu_agg.sql
@@ -21,7 +21,7 @@
 SELECT
   cpu,
   ts,
-  LEAD(ts, 1, (SELECT end_ts FROM trace_bounds))
+  LEAD(ts, 1, trace_end())
   OVER (PARTITION BY cpu ORDER BY ts) - ts AS dur,
   CAST(value AS INT) AS freq_khz
 FROM counter
diff --git a/src/trace_processor/metrics/sql/android/android_dma_heap.sql b/src/trace_processor/metrics/sql/android/android_dma_heap.sql
index ae80ac5..03813f7 100644
--- a/src/trace_processor/metrics/sql/android/android_dma_heap.sql
+++ b/src/trace_processor/metrics/sql/android/android_dma_heap.sql
@@ -18,7 +18,7 @@
 CREATE PERFETTO VIEW dma_heap_timeline AS
 SELECT
   ts,
-  LEAD(ts, 1, (SELECT end_ts FROM trace_bounds))
+  LEAD(ts, 1, trace_end())
   OVER(PARTITION BY track_id ORDER BY ts) - ts AS dur,
   track_id,
   value
diff --git a/src/trace_processor/metrics/sql/android/android_dvfs.sql b/src/trace_processor/metrics/sql/android/android_dvfs.sql
index 6ec1bb2..6366256 100644
--- a/src/trace_processor/metrics/sql/android/android_dvfs.sql
+++ b/src/trace_processor/metrics/sql/android/android_dvfs.sql
@@ -21,8 +21,7 @@
   track.name AS freq_name,
   ts,
   value AS freq_value,
-  LEAD(ts, 1, (SELECT end_ts + 1 FROM trace_bounds))
-  OVER (PARTITION BY track.id ORDER BY ts) - ts AS duration
+  LEAD(ts, 1, trace_end()) OVER (PARTITION BY track.id ORDER BY ts) - ts AS duration
 FROM counter
 LEFT JOIN track ON counter.track_id = track.id
 WHERE track.name GLOB "* Frequency"
diff --git a/src/trace_processor/metrics/sql/android/android_fastrpc.sql b/src/trace_processor/metrics/sql/android/android_fastrpc.sql
index d895b42..6d174de 100644
--- a/src/trace_processor/metrics/sql/android/android_fastrpc.sql
+++ b/src/trace_processor/metrics/sql/android/android_fastrpc.sql
@@ -2,7 +2,7 @@
 CREATE PERFETTO VIEW fastrpc_timeline AS
 SELECT
   ts,
-  LEAD(ts, 1, (SELECT end_ts FROM trace_bounds))
+  LEAD(ts, 1, trace_end())
   OVER(PARTITION BY track_id ORDER BY ts) - ts AS dur,
   RTRIM(SUBSTR(name, 13), ']') AS subsystem_name,
   track_id,
diff --git a/src/trace_processor/metrics/sql/android/android_ion.sql b/src/trace_processor/metrics/sql/android/android_ion.sql
index a6bdf07..1071eef 100644
--- a/src/trace_processor/metrics/sql/android/android_ion.sql
+++ b/src/trace_processor/metrics/sql/android/android_ion.sql
@@ -18,7 +18,7 @@
 CREATE PERFETTO VIEW ion_timeline AS
 SELECT
   ts,
-  LEAD(ts, 1, (SELECT end_ts FROM trace_bounds))
+  LEAD(ts, 1, trace_end())
   OVER(PARTITION BY track_id ORDER BY ts) - ts AS dur,
   CASE name
     WHEN 'mem.ion' THEN 'all'
diff --git a/src/trace_processor/metrics/sql/android/android_netperf.sql b/src/trace_processor/metrics/sql/android/android_netperf.sql
index f7192b9..2676eb0 100644
--- a/src/trace_processor/metrics/sql/android/android_netperf.sql
+++ b/src/trace_processor/metrics/sql/android/android_netperf.sql
@@ -236,7 +236,7 @@
 SELECT
   cpu,
   ts,
-  LEAD(ts, 1, (SELECT end_ts FROM trace_bounds))
+  LEAD(ts, 1, trace_end())
   OVER (PARTITION BY cpu ORDER BY ts) - ts AS dur,
   CAST(value AS INT) AS freq_khz
 FROM counter
diff --git a/src/trace_processor/metrics/sql/android/android_startup.sql b/src/trace_processor/metrics/sql/android/android_startup.sql
index 10fa253..605f9a7 100644
--- a/src/trace_processor/metrics/sql/android/android_startup.sql
+++ b/src/trace_processor/metrics/sql/android/android_startup.sql
@@ -23,7 +23,7 @@
 -- Define the helper functions which will be used throught the remainder
 -- of the metric.
 SELECT RUN_METRIC('android/startup/slice_functions.sql');
-INCLUDE PERFETTO MODULE common.timestamps;
+INCLUDE PERFETTO MODULE intervals.overlap;
 
 -- Define helper functions related to slow start reasons
 SELECT RUN_METRIC('android/startup/slow_start_reasons.sql');
@@ -45,6 +45,15 @@
 -- Define helper functions for system state.
 SELECT RUN_METRIC('android/startup/system_state.sql');
 
+CREATE OR REPLACE PERFETTO FUNCTION is_spans_overlapping(
+  ts1 LONG,
+  ts_end1 LONG,
+  ts2 LONG,
+  ts_end2 LONG)
+RETURNS BOOL AS
+SELECT (IIF($ts1 < $ts2, $ts2, $ts1)
+      < IIF($ts_end1 < $ts_end2, $ts_end1, $ts_end2));
+
 -- Returns the slices for forked processes. Never present in hot starts.
 -- Prefer this over process start_ts, since the process might have
 -- been preforked.
diff --git a/src/trace_processor/metrics/sql/android/counter_span_view_merged.sql b/src/trace_processor/metrics/sql/android/counter_span_view_merged.sql
index 4caaf88..eff2fbb 100644
--- a/src/trace_processor/metrics/sql/android/counter_span_view_merged.sql
+++ b/src/trace_processor/metrics/sql/android/counter_span_view_merged.sql
@@ -28,8 +28,7 @@
 CREATE PERFETTO VIEW {{table_name}}_span AS
 SELECT
   ts,
-  LEAD(ts, 1, (SELECT end_ts + 1 FROM trace_bounds))
-  OVER(ORDER BY ts) - ts AS dur,
+  LEAD(ts, 1, trace_end()) OVER(ORDER BY ts) - ts AS dur,
   CAST(value AS INT) AS {{table_name}}_val
 FROM (
     SELECT ts, value, LAG(value) OVER (ORDER BY ts) AS lag_value
diff --git a/src/trace_processor/metrics/sql/android/global_counter_span_view.sql b/src/trace_processor/metrics/sql/android/global_counter_span_view.sql
index 4db10d3..61c7b99 100644
--- a/src/trace_processor/metrics/sql/android/global_counter_span_view.sql
+++ b/src/trace_processor/metrics/sql/android/global_counter_span_view.sql
@@ -18,8 +18,7 @@
 CREATE PERFETTO VIEW {{table_name}}_span AS
 SELECT
   ts,
-  LEAD(ts, 1, (SELECT end_ts + 1 FROM trace_bounds))
-  OVER(PARTITION BY track_id ORDER BY ts) - ts AS dur,
+  LEAD(ts, 1, trace_end()) OVER(PARTITION BY track_id ORDER BY ts) - ts AS dur,
   value AS {{table_name}}_val
 FROM counter c JOIN counter_track t
   ON t.id = c.track_id
diff --git a/src/trace_processor/metrics/sql/android/gpu_counter_span_view.sql b/src/trace_processor/metrics/sql/android/gpu_counter_span_view.sql
index 9c902a3..7017e9e 100644
--- a/src/trace_processor/metrics/sql/android/gpu_counter_span_view.sql
+++ b/src/trace_processor/metrics/sql/android/gpu_counter_span_view.sql
@@ -18,8 +18,7 @@
 CREATE PERFETTO VIEW {{table_name}}_span AS
 SELECT
   ts,
-  LEAD(ts, 1, (SELECT end_ts + 1 FROM trace_bounds))
-  OVER (PARTITION BY track_id ORDER BY ts) - ts AS dur,
+  LEAD(ts, 1, trace_end()) OVER (PARTITION BY track_id ORDER BY ts) - ts AS dur,
   gpu_id,
   value AS {{table_name}}_val
 FROM counter c JOIN gpu_counter_track t
diff --git a/src/trace_processor/metrics/sql/android/process_counter_span_view.sql b/src/trace_processor/metrics/sql/android/process_counter_span_view.sql
index 0ab4088..89919c9 100644
--- a/src/trace_processor/metrics/sql/android/process_counter_span_view.sql
+++ b/src/trace_processor/metrics/sql/android/process_counter_span_view.sql
@@ -21,7 +21,7 @@
   LEAD(ts, 1, (
     SELECT IFNULL(
       end_ts,
-      (SELECT end_ts FROM trace_bounds)
+      trace_end()
     )
     FROM process p WHERE p.upid = pct.upid) + 1
   ) OVER(PARTITION BY track_id ORDER BY ts) - ts AS dur,
diff --git a/src/trace_processor/metrics/sql/android/process_oom_score.sql b/src/trace_processor/metrics/sql/android/process_oom_score.sql
index 84a1657..df72398 100644
--- a/src/trace_processor/metrics/sql/android/process_oom_score.sql
+++ b/src/trace_processor/metrics/sql/android/process_oom_score.sql
@@ -19,7 +19,7 @@
 CREATE PERFETTO VIEW oom_score_span AS
 SELECT
   ts,
-  LEAD(ts, 1, (SELECT end_ts + 1 FROM trace_bounds))
+  LEAD(ts, 1, trace_end() + 1)
   OVER(PARTITION BY track_id ORDER BY ts) - ts AS dur,
   upid,
   CAST(value AS INT) AS oom_score_val
diff --git a/src/trace_processor/metrics/sql/android/startup/launches_minsdk29.sql b/src/trace_processor/metrics/sql/android/startup/launches_minsdk29.sql
index eae7d59..00faead 100644
--- a/src/trace_processor/metrics/sql/android/startup/launches_minsdk29.sql
+++ b/src/trace_processor/metrics/sql/android/startup/launches_minsdk29.sql
@@ -32,7 +32,7 @@
   ROW_NUMBER()
   OVER(ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS id,
   ts,
-  LEAD(ts, 1, (SELECT end_ts FROM trace_bounds)) OVER(ORDER BY ts) - ts AS dur
+  LEAD(ts, 1, trace_end()) OVER(ORDER BY ts) - ts AS dur
 FROM activity_intent_received
 ORDER BY ts;
 
diff --git a/src/trace_processor/metrics/sql/android/startup/slow_start_reasons.sql b/src/trace_processor/metrics/sql/android/startup/slow_start_reasons.sql
index 4d361f4..a1b7895 100644
--- a/src/trace_processor/metrics/sql/android/startup/slow_start_reasons.sql
+++ b/src/trace_processor/metrics/sql/android/startup/slow_start_reasons.sql
@@ -20,6 +20,15 @@
 SELECT RUN_METRIC('android/startup/system_state.sql');
 SELECT RUN_METRIC('android/startup/mcycles_per_launch.sql');
 
+CREATE OR REPLACE PERFETTO FUNCTION is_spans_overlapping(
+  ts1 LONG,
+  ts_end1 LONG,
+  ts2 LONG,
+  ts_end2 LONG)
+RETURNS BOOL AS
+SELECT (IIF($ts1 < $ts2, $ts2, $ts1)
+      < IIF($ts_end1 < $ts_end2, $ts_end1, $ts_end2));
+
 CREATE OR REPLACE PERFETTO FUNCTION get_percent(num LONG, total LONG)
 RETURNS STRING AS
   SELECT SUBSTRING(CAST(($num * 100 + 0.0) / $total AS STRING), 1, 5);
diff --git a/src/trace_processor/metrics/sql/android/startup/thread_state_breakdown.sql b/src/trace_processor/metrics/sql/android/startup/thread_state_breakdown.sql
index 7bd3dee..92103f1 100644
--- a/src/trace_processor/metrics/sql/android/startup/thread_state_breakdown.sql
+++ b/src/trace_processor/metrics/sql/android/startup/thread_state_breakdown.sql
@@ -20,7 +20,7 @@
 CREATE PERFETTO VIEW thread_state_extended AS
 SELECT
   ts,
-  IIF(dur = -1, (SELECT end_ts FROM trace_bounds), dur) AS dur,
+  IIF(dur = -1, trace_end(), dur) AS dur,
   utid,
   state,
   io_wait
diff --git a/src/trace_processor/metrics/sql/android/thread_counter_span_view.sql b/src/trace_processor/metrics/sql/android/thread_counter_span_view.sql
index 21961a9..6e7bba7 100644
--- a/src/trace_processor/metrics/sql/android/thread_counter_span_view.sql
+++ b/src/trace_processor/metrics/sql/android/thread_counter_span_view.sql
@@ -21,7 +21,7 @@
   LEAD(ts, 1, (
     SELECT IFNULL(
       end_ts,
-      (SELECT end_ts FROM trace_bounds)
+      trace_end()
     )
     FROM thread th WHERE th.utid = t.utid) + 1
   ) OVER(PARTITION BY track_id ORDER BY ts) - ts AS dur,
diff --git a/src/trace_processor/metrics/sql/chrome/rail_modes.sql b/src/trace_processor/metrics/sql/chrome/rail_modes.sql
index 38c095b..c0da0fb 100644
--- a/src/trace_processor/metrics/sql/chrome/rail_modes.sql
+++ b/src/trace_processor/metrics/sql/chrome/rail_modes.sql
@@ -97,8 +97,7 @@
 -- metrics that use the trace.
 DROP VIEW IF EXISTS trace_has_realistic_length;
 CREATE PERFETTO VIEW trace_has_realistic_length AS
-SELECT (end_ts - start_ts) < 1e9 * 60 * 10 AS value
-FROM trace_bounds;
+SELECT trace_dur() < 1e9 * 60 * 10 AS value;
 
 -- RAIL_MODE_LOAD seems to get stuck which makes it not very useful so remap it
 -- to RAIL_MODE_ANIMATION so it doesn't dominate the overall RAIL mode.
@@ -214,11 +213,12 @@
   dur,
   1
 FROM (SELECT start_ts AS ts,
-  COALESCE((
+  COALESCE(
+    (
     SELECT MIN(ts)
     FROM slice
     WHERE name = "VSync"
-  ) - start_ts - const.vsync_padding,
+) - start_ts - const.vsync_padding,
   end_ts - start_ts
   ) AS dur
   FROM trace_bounds, const)
diff --git a/src/trace_processor/metrics/sql/trace_metadata.sql b/src/trace_processor/metrics/sql/trace_metadata.sql
index cee4e2d..b963ff2 100644
--- a/src/trace_processor/metrics/sql/trace_metadata.sql
+++ b/src/trace_processor/metrics/sql/trace_metadata.sql
@@ -29,7 +29,7 @@
 DROP VIEW IF EXISTS trace_metadata_output;
 CREATE PERFETTO VIEW trace_metadata_output AS
 SELECT TraceMetadata(
-  'trace_duration_ns', CAST((SELECT end_ts - start_ts FROM trace_bounds) AS INT),
+  'trace_duration_ns', CAST(trace_dur() AS INT),
   'trace_uuid', (SELECT str_value FROM metadata WHERE name = 'trace_uuid'),
   'android_build_fingerprint', (
     SELECT str_value FROM metadata WHERE name = 'android_build_fingerprint'
diff --git a/src/trace_processor/perfetto_sql/prelude/tables.sql b/src/trace_processor/perfetto_sql/prelude/tables.sql
index 9ba3b11..bc01757 100644
--- a/src/trace_processor/perfetto_sql/prelude/tables.sql
+++ b/src/trace_processor/perfetto_sql/prelude/tables.sql
@@ -1,6 +1,3 @@
-CREATE TABLE trace_bounds AS
-SELECT 0 AS start_ts, 0 AS end_ts;
-
 CREATE TABLE power_profile(
   device STRING,
   cpu INT,
diff --git a/src/trace_processor/perfetto_sql/stdlib/BUILD.gn b/src/trace_processor/perfetto_sql/stdlib/BUILD.gn
index da40ef5..fa871e6 100644
--- a/src/trace_processor/perfetto_sql/stdlib/BUILD.gn
+++ b/src/trace_processor/perfetto_sql/stdlib/BUILD.gn
@@ -31,6 +31,7 @@
     "prelude",
     "sched",
     "slices",
+    "time",
   ]
   generated_header = "stdlib.h"
   namespace = "stdlib"
diff --git a/src/trace_processor/perfetto_sql/stdlib/android/battery_stats.sql b/src/trace_processor/perfetto_sql/stdlib/android/battery_stats.sql
index 828400e..ff69029 100644
--- a/src/trace_processor/perfetto_sql/stdlib/android/battery_stats.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/android/battery_stats.sql
@@ -13,8 +13,6 @@
 -- See the License for the specific language governing permissions and
 -- limitations under the License.
 
-INCLUDE PERFETTO MODULE common.timestamps;
-
 -- Converts a battery_stats counter value to human readable string.
 CREATE PERFETTO FUNCTION android_battery_stats_counter_to_string(
   -- The counter track name (e.g. 'battery_stats.audio').
diff --git a/src/trace_processor/perfetto_sql/stdlib/android/binder.sql b/src/trace_processor/perfetto_sql/stdlib/android/binder.sql
index 7ee6dfb..a271398 100644
--- a/src/trace_processor/perfetto_sql/stdlib/android/binder.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/android/binder.sql
@@ -14,7 +14,6 @@
 -- limitations under the License.
 --
 
-INCLUDE PERFETTO MODULE common.timestamps;
 INCLUDE PERFETTO MODULE android.process_metadata;
 
 -- Count Binder transactions per process.
@@ -163,8 +162,8 @@
     process.upid,
     CAST(c.value AS INT) AS value,
     c.ts,
-    IFNULL(LEAD(ts) OVER (PARTITION BY upid ORDER BY ts), trace_bounds.end_ts) AS end_ts
-    FROM counter c, trace_bounds
+    IFNULL(LEAD(ts) OVER (PARTITION BY upid ORDER BY ts), trace_end()) AS end_ts
+    FROM counter c
          JOIN process_counter_track t ON c.track_id = t.id
          JOIN process USING (upid)
    WHERE t.name = 'oom_score_adj';
diff --git a/src/trace_processor/perfetto_sql/stdlib/android/dvfs.sql b/src/trace_processor/perfetto_sql/stdlib/android/dvfs.sql
index 22fe345..d6a43d6 100644
--- a/src/trace_processor/perfetto_sql/stdlib/android/dvfs.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/android/dvfs.sql
@@ -28,8 +28,7 @@
   counter_track.name,
   counter.ts,
   counter.value,
-  LEAD(counter.ts, 1, (SELECT end_ts + 1 FROM trace_bounds))
-  OVER (PARTITION BY counter_track.id ORDER BY counter.ts) - counter.ts AS dur
+  LEAD(counter.ts, 1, trace_end()) OVER (PARTITION BY counter_track.id ORDER BY counter.ts) - counter.ts AS dur
 FROM counter
 JOIN counter_track
   ON counter.track_id = counter_track.id
diff --git a/src/trace_processor/perfetto_sql/stdlib/android/freezer.sql b/src/trace_processor/perfetto_sql/stdlib/android/freezer.sql
index 264fa78..14e3a01 100644
--- a/src/trace_processor/perfetto_sql/stdlib/android/freezer.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/android/freezer.sql
@@ -14,8 +14,6 @@
 -- limitations under the License.
 --
 
-INCLUDE PERFETTO MODULE common.timestamps;
-
 CREATE PERFETTO FUNCTION _extract_freezer_pid(name STRING)
 RETURNS INT
 AS
diff --git a/src/trace_processor/perfetto_sql/stdlib/android/garbage_collection.sql b/src/trace_processor/perfetto_sql/stdlib/android/garbage_collection.sql
index 3baf612..cb16f28 100644
--- a/src/trace_processor/perfetto_sql/stdlib/android/garbage_collection.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/android/garbage_collection.sql
@@ -15,7 +15,6 @@
 --
 
 INCLUDE PERFETTO MODULE common.slices;
-INCLUDE PERFETTO MODULE common.timestamps;
 
 -- Collect all GC slices. There's typically one enclosing slice but sometimes the
 -- CompactionPhase is outside the nesting and we need to include that.
diff --git a/src/trace_processor/perfetto_sql/stdlib/android/input.sql b/src/trace_processor/perfetto_sql/stdlib/android/input.sql
index f344c20..a1d7b11 100644
--- a/src/trace_processor/perfetto_sql/stdlib/android/input.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/android/input.sql
@@ -13,8 +13,6 @@
 -- See the License for the specific language governing permissions and
 -- limitations under the License.
 
-INCLUDE PERFETTO MODULE common.timestamps;
-
 CREATE PERFETTO TABLE _input_message_sent
 AS
 SELECT
diff --git a/src/trace_processor/perfetto_sql/stdlib/android/job_scheduler.sql b/src/trace_processor/perfetto_sql/stdlib/android/job_scheduler.sql
index 71920e5..dc222bf 100644
--- a/src/trace_processor/perfetto_sql/stdlib/android/job_scheduler.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/android/job_scheduler.sql
@@ -14,8 +14,6 @@
 -- limitations under the License.
 --
 
-INCLUDE PERFETTO MODULE common.timestamps;
-
 -- All scheduled jobs and their latencies.
 CREATE PERFETTO TABLE android_job_scheduler_events (
   -- Id of the scheduled job assigned by the app developer.
diff --git a/src/trace_processor/perfetto_sql/stdlib/android/startup/startups_minsdk29.sql b/src/trace_processor/perfetto_sql/stdlib/android/startup/startups_minsdk29.sql
index e10244b..fcc1fa9 100644
--- a/src/trace_processor/perfetto_sql/stdlib/android/startup/startups_minsdk29.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/android/startup/startups_minsdk29.sql
@@ -29,7 +29,7 @@
   ROW_NUMBER()
   OVER(ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS startup_id,
   ts,
-  LEAD(ts, 1, (SELECT end_ts FROM trace_bounds)) OVER(ORDER BY ts) - ts AS dur
+  LEAD(ts, 1, trace_end()) OVER(ORDER BY ts) - ts AS dur
 FROM _activity_intent_received
 ORDER BY ts;
 
diff --git a/src/trace_processor/perfetto_sql/stdlib/android/suspend.sql b/src/trace_processor/perfetto_sql/stdlib/android/suspend.sql
index 60236b1..41ed5f8 100644
--- a/src/trace_processor/perfetto_sql/stdlib/android/suspend.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/android/suspend.sql
@@ -51,21 +51,21 @@
 awake_slice AS (
   -- If we don't have any rows, use the trace bounds.
   SELECT
-    (SELECT start_ts FROM trace_bounds) AS ts,
-    (SELECT end_ts - start_ts FROM trace_bounds) AS dur
+    trace_start() AS ts,
+    trace_dur() AS dur
   WHERE (SELECT COUNT(*) FROM suspend_slice) = 0
   UNION ALL
   -- If we do have rows, create one slice from the trace start to the first suspend.
   SELECT
-    (SELECT start_ts FROM trace_bounds) AS ts,
-    (SELECT min(ts) FROM suspend_slice) - (SELECT start_ts FROM trace_bounds) AS dur
+    trace_start() AS ts,
+    (SELECT min(ts) FROM suspend_slice) - trace_start() AS dur
   WHERE (SELECT COUNT(*) FROM suspend_slice) != 0
   UNION ALL
   -- And then one slice for each suspend, from the end of the suspend to the
   -- start of the next one (or the end of the trace if there is no next one).
   SELECT
     ts + dur AS ts,
-    ifnull(lead(ts) OVER (ORDER BY ts), (SELECT end_ts FROM trace_bounds)) - ts - dur
+    ifnull(lead(ts) OVER (ORDER BY ts), trace_end()) - ts - dur
       AS dur
   FROM suspend_slice
 )
diff --git a/src/trace_processor/perfetto_sql/stdlib/counters/intervals.sql b/src/trace_processor/perfetto_sql/stdlib/counters/intervals.sql
index 4bc69ce..94e6996 100644
--- a/src/trace_processor/perfetto_sql/stdlib/counters/intervals.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/counters/intervals.sql
@@ -14,8 +14,6 @@
 -- limitations under the License.
 --
 
-INCLUDE PERFETTO MODULE common.timestamps;
-
 -- For a given counter timeline (e.g. a single counter track), returns
 -- intervals of time where the counter has the same value.
 --
diff --git a/src/trace_processor/perfetto_sql/stdlib/deprecated/v42/common/timestamps.sql b/src/trace_processor/perfetto_sql/stdlib/deprecated/v42/common/timestamps.sql
index 81b89a4..bff333f 100644
--- a/src/trace_processor/perfetto_sql/stdlib/deprecated/v42/common/timestamps.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/deprecated/v42/common/timestamps.sql
@@ -13,56 +13,23 @@
 -- See the License for the specific language governing permissions and
 -- limitations under the License.
 
---
--- Trace bounds
---
+INCLUDE PERFETTO MODULE time.conversion;
 
--- Fetch start of the trace.
-CREATE PERFETTO FUNCTION trace_start()
--- Start of the trace in nanoseconds.
-RETURNS LONG AS
-SELECT start_ts FROM trace_bounds;
-
--- Fetch end of the trace.
-CREATE PERFETTO FUNCTION trace_end()
--- End of the trace in nanoseconds.
-RETURNS LONG AS
-SELECT end_ts FROM trace_bounds;
-
--- Fetch duration of the trace.
-CREATE PERFETTO FUNCTION trace_dur()
--- Duration of the trace in nanoseconds.
-RETURNS LONG AS
-SELECT trace_end() - trace_start();
-
--- Checks whether two spans are overlapping.
 CREATE PERFETTO FUNCTION is_spans_overlapping(
-  -- Start of first span.
   ts1 LONG,
-  -- End of first span.
   ts_end1 LONG,
-  -- Start of second span.
   ts2 LONG,
-  -- End of second span.
   ts_end2 LONG)
--- Whether two spans are overlapping.
 RETURNS BOOL AS
 SELECT (IIF($ts1 < $ts2, $ts2, $ts1)
       < IIF($ts_end1 < $ts_end2, $ts_end1, $ts_end2));
 
---Return the overlapping duration between two spans.
---If either duration is less than 0 or there's no intersection, 0 is returned
 CREATE PERFETTO FUNCTION spans_overlapping_dur(
-  -- Timestamp of first slice start.
   ts1 LONG,
-  -- Duration of first slice.
   dur1 LONG,
-  -- Timestamp of second slice start.
   ts2 LONG,
-  -- Duration of second slice.
   dur2 LONG
 )
--- Overlapping duration
 RETURNS INT AS
 SELECT
   CASE
@@ -74,76 +41,32 @@
     ELSE $dur2
   END;
 
---
--- Helpers for defining time durations.
---
+-- Renames
 
--- Converts a duration in seconds to nanoseconds, which is the default representation
--- of time durations in trace processor. Provided for consisensy with other functions.
-CREATE PERFETTO FUNCTION ns(
-  -- Time duration in nanoseconds.
-  nanos INT
-)
--- Time duration in nanoseconds.
+CREATE PERFETTO FUNCTION ns(nanos INT)
 RETURNS INT AS
-SELECT $nanos;
+SELECT time_from_ns($nanos);
 
--- Converts a duration in microseconds to nanoseconds, which is the default
--- representation of time durations in trace processor.
-CREATE PERFETTO FUNCTION us(
-  -- Time duration in microseconds.
-  micros INT
-)
--- Time duration in nanoseconds.
+CREATE PERFETTO FUNCTION us(micros INT)
 RETURNS INT AS
-SELECT $micros * 1000;
+SELECT time_from_us($micros);
 
--- Converts a duration in millseconds to nanoseconds, which is the default
--- representation of time durations in trace processor.
-CREATE PERFETTO FUNCTION ms(
-  -- Time duration in milliseconds.
-  millis INT
-)
--- Time duration in nanoseconds.
+CREATE PERFETTO FUNCTION ms(millis INT)
 RETURNS INT AS
-SELECT $millis * 1000 * 1000;
+SELECT time_from_ms($millis);
 
--- Converts a duration in seconds to nanoseconds, which is the default
--- representation of time durations in trace processor.
-CREATE PERFETTO FUNCTION seconds(
-  -- Time duration in seconds.
-  seconds INT
-)
--- Time duration in nanoseconds.
+CREATE PERFETTO FUNCTION seconds(seconds INT)
 RETURNS INT AS
-SELECT $seconds * 1000 * 1000 * 1000;
+SELECT time_from_s($seconds);
 
--- Converts a duration in minutes to nanoseconds, which is the default
--- representation of time durations in trace processor.
-CREATE PERFETTO FUNCTION minutes(
-  -- Time duration in minutes.
-  minutes INT
-)
--- Time duration in nanoseconds.
+CREATE PERFETTO FUNCTION minutes(minutes INT)
 RETURNS INT AS
-SELECT $minutes * 60 * 1000 * 1000 * 1000;
+SELECT time_from_min($minutes);
 
--- Converts a duration in hours to nanoseconds, which is the default
--- representation of time durations in trace processor.
-CREATE PERFETTO FUNCTION hours(
-  -- Time duration in hours.
-  hours INT
-)
--- Time duration in nanoseconds.
+CREATE PERFETTO FUNCTION hours(hours INT)
 RETURNS INT AS
-SELECT $hours * 60 * 60 * 1000 * 1000 * 1000;
+SELECT time_from_hours($hours);
 
--- Converts a duration in days to nanoseconds, which is the default
--- representation of time durations in trace processor.
-CREATE PERFETTO FUNCTION days(
-  -- Time duration in days.
-  days INT
-)
--- Time duration in nanoseconds.
+CREATE PERFETTO FUNCTION days(days INT)
 RETURNS INT AS
-SELECT $days * 24 * 60 * 60 * 1000 * 1000 * 1000;
+SELECT time_from_days($days);
diff --git a/src/trace_processor/perfetto_sql/stdlib/prelude/BUILD.gn b/src/trace_processor/perfetto_sql/stdlib/prelude/BUILD.gn
index 19162d5..03f9cd1 100644
--- a/src/trace_processor/perfetto_sql/stdlib/prelude/BUILD.gn
+++ b/src/trace_processor/perfetto_sql/stdlib/prelude/BUILD.gn
@@ -15,5 +15,8 @@
 import("../../../../../gn/perfetto_sql.gni")
 
 perfetto_sql_source_set("prelude") {
-  sources = [ "slices.sql" ]
+  sources = [
+    "slices.sql",
+    "trace_bounds.sql",
+  ]
 }
diff --git a/src/trace_processor/perfetto_sql/stdlib/prelude/trace_bounds.sql b/src/trace_processor/perfetto_sql/stdlib/prelude/trace_bounds.sql
new file mode 100644
index 0000000..51db48d
--- /dev/null
+++ b/src/trace_processor/perfetto_sql/stdlib/prelude/trace_bounds.sql
@@ -0,0 +1,40 @@
+--
+-- Copyright 2023 The Android Open Source Project
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+--     https://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+
+-- Definition of `trace_bounds` table. The values are being filled by Trace
+-- Processor when parsing the trace. Can't be a Perfetto table because it has
+-- to be mutable. 
+-- It is recommended to depend on the `trace_start()` and `trace_end()`
+-- functions rather than directly on `trace_bounds`.
+CREATE TABLE trace_bounds AS
+SELECT 0 AS start_ts, 0 AS end_ts;
+
+-- Fetch start of the trace.
+CREATE PERFETTO FUNCTION trace_start()
+-- Start of the trace in nanoseconds.
+RETURNS LONG AS
+SELECT start_ts FROM trace_bounds;
+
+-- Fetch end of the trace.
+CREATE PERFETTO FUNCTION trace_end()
+-- End of the trace in nanoseconds.
+RETURNS LONG AS
+SELECT end_ts FROM trace_bounds;
+
+-- Fetch duration of the trace.
+CREATE PERFETTO FUNCTION trace_dur()
+-- Duration of the trace in nanoseconds.
+RETURNS LONG AS
+SELECT trace_end() - trace_start();
\ No newline at end of file
diff --git a/src/trace_processor/perfetto_sql/stdlib/time/BUILD.gn b/src/trace_processor/perfetto_sql/stdlib/time/BUILD.gn
new file mode 100644
index 0000000..da92871
--- /dev/null
+++ b/src/trace_processor/perfetto_sql/stdlib/time/BUILD.gn
@@ -0,0 +1,19 @@
+# Copyright (C) 2022 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("../../../../../gn/perfetto_sql.gni")
+
+perfetto_sql_source_set("time") {
+  sources = [ "conversion.sql" ]
+}
diff --git a/src/trace_processor/perfetto_sql/stdlib/time/conversion.sql b/src/trace_processor/perfetto_sql/stdlib/time/conversion.sql
new file mode 100644
index 0000000..9a284d0
--- /dev/null
+++ b/src/trace_processor/perfetto_sql/stdlib/time/conversion.sql
@@ -0,0 +1,85 @@
+--
+-- Copyright 2024 The Android Open Source Project
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+--     https://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+
+-- Returns the provided nanosecond duration, which is the default
+-- representation of time durations in trace processor. Provided for
+-- consistency with other functions.
+CREATE PERFETTO FUNCTION time_from_ns(
+  -- Time duration in nanoseconds.
+  nanos INT
+)
+-- Time duration in nanoseconds.
+RETURNS INT AS
+SELECT $nanos;
+
+-- Converts a duration in microseconds to nanoseconds, which is the default
+-- representation of time durations in trace processor.
+CREATE PERFETTO FUNCTION time_from_us(
+  -- Time duration in microseconds.
+  micros INT
+)
+-- Time duration in nanoseconds.
+RETURNS INT AS
+SELECT $micros * 1000;
+
+-- Converts a duration in millseconds to nanoseconds, which is the default
+-- representation of time durations in trace processor.
+CREATE PERFETTO FUNCTION time_from_ms(
+  -- Time duration in milliseconds.
+  millis INT
+)
+-- Time duration in nanoseconds.
+RETURNS INT AS
+SELECT $millis * 1000 * 1000;
+
+-- Converts a duration in seconds to nanoseconds, which is the default
+-- representation of time durations in trace processor.
+CREATE PERFETTO FUNCTION time_from_s(
+  -- Time duration in seconds.
+  seconds INT
+)
+-- Time duration in nanoseconds.
+RETURNS INT AS
+SELECT $seconds * 1000 * 1000 * 1000;
+
+-- Converts a duration in minutes to nanoseconds, which is the default
+-- representation of time durations in trace processor.
+CREATE PERFETTO FUNCTION time_from_min(
+  -- Time duration in minutes.
+  minutes INT
+)
+-- Time duration in nanoseconds.
+RETURNS INT AS
+SELECT $minutes * 60 * 1000 * 1000 * 1000;
+
+-- Converts a duration in hours to nanoseconds, which is the default
+-- representation of time durations in trace processor.
+CREATE PERFETTO FUNCTION time_from_hours(
+  -- Time duration in hours.
+  hours INT
+)
+-- Time duration in nanoseconds.
+RETURNS INT AS
+SELECT $hours * 60 * 60 * 1000 * 1000 * 1000;
+
+-- Converts a duration in days to nanoseconds, which is the default
+-- representation of time durations in trace processor.
+CREATE PERFETTO FUNCTION time_from_days(
+  -- Time duration in days.
+  days INT
+)
+-- Time duration in nanoseconds.
+RETURNS INT AS
+SELECT $days * 24 * 60 * 60 * 1000 * 1000 * 1000;
diff --git a/test/trace_processor/diff_tests/metrics/camera/camera-ion-mem-trace_android_camera_unagg.out b/test/trace_processor/diff_tests/metrics/camera/camera-ion-mem-trace_android_camera_unagg.out
index b690d13..84dd261 100644
--- a/test/trace_processor/diff_tests/metrics/camera/camera-ion-mem-trace_android_camera_unagg.out
+++ b/test/trace_processor/diff_tests/metrics/camera/camera-ion-mem-trace_android_camera_unagg.out
@@ -72687,4 +72687,12 @@
     dma_val: 322318336.0
     value: 1277186048.0
   }
+  gc_rss_and_dma {
+    ts: 790258000000
+    gca_rss_val: 622112768.0
+    hal_rss_val: 327274496.0
+    cameraserver_rss_val: 5480448.0
+    dma_val: 0.0
+    value: 954867712.0
+  }
 }
diff --git a/test/trace_processor/diff_tests/metrics/camera/tests.py b/test/trace_processor/diff_tests/metrics/camera/tests.py
index 43a9f86..fecb492 100644
--- a/test/trace_processor/diff_tests/metrics/camera/tests.py
+++ b/test/trace_processor/diff_tests/metrics/camera/tests.py
@@ -30,7 +30,7 @@
           gc_rss_and_dma {
             min: 47779840.0
             max: 2536079360.0
-            avg: 1464706457.7379363
+            avg: 1464706457.7348418
           }
         }
         """))
diff --git a/test/trace_processor/diff_tests/metrics/graphics/gpu_frequency_metric.textproto b/test/trace_processor/diff_tests/metrics/graphics/gpu_frequency_metric.textproto
index 8f0710f..3825a15 100644
--- a/test/trace_processor/diff_tests/metrics/graphics/gpu_frequency_metric.textproto
+++ b/test/trace_processor/diff_tests/metrics/graphics/gpu_frequency_metric.textproto
@@ -42,7 +42,7 @@
       }
     }
     event {
-      timestamp: 200005999999
+      timestamp: 200006000000
       pid: 527
       gpu_frequency {
         gpu_id: 0
diff --git a/test/trace_processor/diff_tests/metrics/graphics/tests.py b/test/trace_processor/diff_tests/metrics/graphics/tests.py
index f5bb896..28a1f66 100644
--- a/test/trace_processor/diff_tests/metrics/graphics/tests.py
+++ b/test/trace_processor/diff_tests/metrics/graphics/tests.py
@@ -101,7 +101,7 @@
           }
           mem_max: 4
           mem_min: 1
-          mem_avg: 2
+          mem_avg: 1
         }
         """))
 
diff --git a/test/trace_processor/diff_tests/parser/power/dvfs_metric.textproto b/test/trace_processor/diff_tests/parser/power/dvfs_metric.textproto
index 8301519..4472456 100644
--- a/test/trace_processor/diff_tests/parser/power/dvfs_metric.textproto
+++ b/test/trace_processor/diff_tests/parser/power/dvfs_metric.textproto
@@ -42,7 +42,7 @@
       }
     }
     event {
-      timestamp: 200005999999
+      timestamp: 200006000000
       pid: 527
       clock_set_rate {
         name: "domain@1"
diff --git a/test/trace_processor/diff_tests/stdlib/android/tests.py b/test/trace_processor/diff_tests/stdlib/android/tests.py
index 5df48e0..edfe5d6 100644
--- a/test/trace_processor/diff_tests/stdlib/android/tests.py
+++ b/test/trace_processor/diff_tests/stdlib/android/tests.py
@@ -919,7 +919,7 @@
          "name","ts","value","dur"
          "domain@1 Frequency",200001000000,400000.000000,2000000
          "domain@1 Frequency",200003000000,1024000.000000,2000000
-         "domain@1 Frequency",200005000000,1024000.000000,1
+         "domain@1 Frequency",200005000000,1024000.000000,0
          """))
 
   def test_android_dvfs_counter_stats(self):
@@ -987,8 +987,8 @@
          """,
         out=Csv("""
          "name","max","min","dur","wgt_avg"
-         "bus_throughput Frequency",1014000.000000,553000.000000,4000000,783499.942375
-         "domain@1 Frequency",1024000.000000,400000.000000,4000000,712000.078000
+         "bus_throughput Frequency",1014000.000000,553000.000000,2000000,783500.000000
+         "domain@1 Frequency",1024000.000000,400000.000000,2000000,712000.000000
          """))
 
   def test_android_dvfs_counter_residency(self):
@@ -998,7 +998,7 @@
             ftrace_events {
               cpu: 0
               event {
-                timestamp: 200001000001
+                timestamp: 200001000000
                 pid: 2
                 clock_set_rate {
                 name : "bus_throughput"
@@ -1006,7 +1006,7 @@
                 }
               }
               event {
-                timestamp: 200003000001
+                timestamp: 200003000000
                 pid: 2
                 clock_set_rate {
                   name: "bus_throughput"
diff --git a/tools/check_sql_metrics.py b/tools/check_sql_metrics.py
index b577b43..73f0d70 100755
--- a/tools/check_sql_metrics.py
+++ b/tools/check_sql_metrics.py
@@ -48,7 +48,7 @@
     '/chrome/gesture_jank.sql': [
         '{{prefix}}_jank_maybe_null_prev_and_next_without_precompute'
     ],
-    '/experimental/frame_times.sql': ['DisplayCompositorPresentationEvents']
+    '/experimental/frame_times.sql': ['DisplayCompositorPresentationEvents'],
 }
 
 
diff --git a/tools/check_sql_modules.py b/tools/check_sql_modules.py
index 7f6f81c..b4ffc1f 100755
--- a/tools/check_sql_modules.py
+++ b/tools/check_sql_modules.py
@@ -34,9 +34,8 @@
 
 # Allowlist path are relative to the stdlib root.
 CREATE_TABLE_ALLOWLIST = {
-    '/android/binder.sql': [
-        '_oom_score'
-    ],
+    '/prelude/trace_bounds.sql': ['trace_bounds'],
+    '/android/binder.sql': ['_oom_score'],
     '/android/monitor_contention.sql': [
         '_isolated', 'android_monitor_contention_chain',
         'android_monitor_contention'
@@ -91,6 +90,11 @@
         sql = f.read()
 
       parsed = parse_file(rel_path, sql)
+
+      # Some modules (i.e. `deprecated`) should not be checked.
+      if not parsed:
+        continue
+
       modules.append((path, sql, parsed))
 
       if args.verbose:
diff --git a/tools/gen_stdlib_docs_json.py b/tools/gen_stdlib_docs_json.py
index 513b932..8ae6044 100755
--- a/tools/gen_stdlib_docs_json.py
+++ b/tools/gen_stdlib_docs_json.py
@@ -71,6 +71,11 @@
     import_key = path.split(".sql")[0].replace("/", ".")
 
     docs = parse_file(path, sql)
+
+    # Some modules (i.e `deprecated`) should not generate docs.
+    if not docs:
+      continue
+
     if len(docs.errors) > 0:
       for e in docs.errors:
         print(e)