diff --git a/Android.bp b/Android.bp index 1c857f4bda..89a480a97c 100644 --- a/Android.bp +++ b/Android.bp @@ -16420,6 +16420,8 @@ genrule { "src/trace_processor/perfetto_sql/stdlib/android/oom_adjuster.sql", "src/trace_processor/perfetto_sql/stdlib/android/power_rails.sql", "src/trace_processor/perfetto_sql/stdlib/android/process_metadata.sql", + "src/trace_processor/perfetto_sql/stdlib/android/profiling_manager/startup.sql", + "src/trace_processor/perfetto_sql/stdlib/android/profiling_manager/util.sql", "src/trace_processor/perfetto_sql/stdlib/android/screen_state.sql", "src/trace_processor/perfetto_sql/stdlib/android/screenshots.sql", "src/trace_processor/perfetto_sql/stdlib/android/services.sql", diff --git a/BUILD b/BUILD index 24c32bab1a..c68c3e2827 100644 --- a/BUILD +++ b/BUILD @@ -3527,6 +3527,15 @@ perfetto_filegroup( ], ) +# GN target: //src/trace_processor/perfetto_sql/stdlib/android/profiling_manager:profiling_manager +perfetto_filegroup( + name = "src_trace_processor_perfetto_sql_stdlib_android_profiling_manager_profiling_manager", + srcs = [ + "src/trace_processor/perfetto_sql/stdlib/android/profiling_manager/startup.sql", + "src/trace_processor/perfetto_sql/stdlib/android/profiling_manager/util.sql", + ], +) + # GN target: //src/trace_processor/perfetto_sql/stdlib/android/startup:startup perfetto_filegroup( name = "src_trace_processor_perfetto_sql_stdlib_android_startup_startup", @@ -3937,6 +3946,7 @@ perfetto_cc_amalgamated_sql( ":src_trace_processor_perfetto_sql_stdlib_android_memory_heap_graph_heap_graph", ":src_trace_processor_perfetto_sql_stdlib_android_memory_heap_profile_heap_profile", ":src_trace_processor_perfetto_sql_stdlib_android_memory_memory", + ":src_trace_processor_perfetto_sql_stdlib_android_profiling_manager_profiling_manager", ":src_trace_processor_perfetto_sql_stdlib_android_startup_startup", ":src_trace_processor_perfetto_sql_stdlib_android_winscope_winscope", ":src_trace_processor_perfetto_sql_stdlib_appleos_appleos", diff --git a/src/trace_processor/perfetto_sql/stdlib/android/BUILD.gn b/src/trace_processor/perfetto_sql/stdlib/android/BUILD.gn index 6b35ce7a1b..b6932147b4 100644 --- a/src/trace_processor/perfetto_sql/stdlib/android/BUILD.gn +++ b/src/trace_processor/perfetto_sql/stdlib/android/BUILD.gn @@ -25,6 +25,7 @@ perfetto_sql_source_set("android") { "frames", "gpu", "memory", + "profiling_manager", "startup", "winscope", ] diff --git a/src/trace_processor/perfetto_sql/stdlib/android/profiling_manager/BUILD.gn b/src/trace_processor/perfetto_sql/stdlib/android/profiling_manager/BUILD.gn new file mode 100644 index 0000000000..a8a88360ed --- /dev/null +++ b/src/trace_processor/perfetto_sql/stdlib/android/profiling_manager/BUILD.gn @@ -0,0 +1,22 @@ +# Copyright (C) 2026 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("profiling_manager") { + sources = [ + "startup.sql", + "util.sql", + ] +} diff --git a/src/trace_processor/perfetto_sql/stdlib/android/profiling_manager/startup.sql b/src/trace_processor/perfetto_sql/stdlib/android/profiling_manager/startup.sql new file mode 100644 index 0000000000..f83f13e666 --- /dev/null +++ b/src/trace_processor/perfetto_sql/stdlib/android/profiling_manager/startup.sql @@ -0,0 +1,52 @@ +-- +-- Copyright 2026 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. + +INCLUDE PERFETTO MODULE android.profiling_manager.util; + +-- Provides cold startups for redacted traces +-- Note: Redacted traces contain a subset of slices compare to a regular perfetto trace as they contain information only about the process +-- starting its own profiling, thus, queries in this section may omit process information as its assumed that slices belong +-- to the single profiled process. +CREATE PERFETTO TABLE android_profiling_manager_cold_startup ( + -- Initial timestamp for startup from apps perspective + ts TIMESTAMP, + -- slice name to identify the startup + name STRING, + -- duration in nanoseconds + dur DURATION, + -- Checkpoint where startup is marked as finished. Two cases: + -- TTFF (Time to first frame): Startup marked as finished after first frame done + -- TTI (Time to interactive): Startup marked as finished after app calls Activity#reportFullyDrawn() + startup_checkpoint STRING +) AS +WITH + startups AS ( + SELECT + ts, + 'app_startup_ttff' AS name, + dur, + 'TTFF' AS startup_checkpoint + FROM _android_generate_start_to_end_slices('bindApplication', 'Choreographer#doFrame [0-9]*', TRUE) + UNION ALL + SELECT + ts, + 'app_startup_tti' AS name, + dur, + 'TTI' AS startup_checkpoint + FROM _android_generate_start_to_end_slices('bindApplication', 'reportFullyDrawn*', TRUE) + ) +SELECT + * +FROM startups; diff --git a/src/trace_processor/perfetto_sql/stdlib/android/profiling_manager/util.sql b/src/trace_processor/perfetto_sql/stdlib/android/profiling_manager/util.sql new file mode 100644 index 0000000000..dd52a66f0c --- /dev/null +++ b/src/trace_processor/perfetto_sql/stdlib/android/profiling_manager/util.sql @@ -0,0 +1,55 @@ +-- +-- Copyright 2026 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 an artificially generated slice for each pair of (matched(startSlicePattern), matched(endSlicePattern)) +-- Caveat: If multiple slices match endSlicePattern it will only return one per start slice and it will be closest slice in the timeline. +CREATE PERFETTO FUNCTION _android_generate_start_to_end_slices( + -- GLOB pattern to find the start slices + start_pattern STRING, + -- GLOB pattern to find the matching end slice for each slice matched by startSlicePattern + end_pattern STRING, + -- Whether the generated slice should include the duration of the end slice or not + inclusive BOOL +) +RETURNS TABLE ( + -- slice name + name STRING, + -- slice timestamp + ts LONG, + -- slice duration in nanoseconds + dur LONG +) AS +SELECT + s.name, + s.ts, + -- Calculate duration by looking ahead for the nearest end slice + ( + SELECT + e.ts + iif($inclusive, e.dur, 0) + FROM slice AS e + WHERE + e.name GLOB $end_pattern + -- Ensure the end slice occurs after the start slice + -- Ensure the end slice occurs after the start slice + AND e.ts > s.ts + ORDER BY + e.ts ASC + LIMIT 1 + ) - s.ts AS dur +FROM slice AS s +WHERE + s.name GLOB $start_pattern + -- Filter out start slices that did not find a matching end slice (where dur becomes NULL) + AND dur IS NOT NULL; diff --git a/test/data/redacted-startup.pb.sha256 b/test/data/redacted-startup.pb.sha256 new file mode 100644 index 0000000000..efbd69a76f --- /dev/null +++ b/test/data/redacted-startup.pb.sha256 @@ -0,0 +1 @@ +4c0997d6021f94f94fe9dc495b43a047471aff79f8d43a0fe3132998b03c2dc8 \ No newline at end of file diff --git a/test/trace_processor/diff_tests/stdlib/android/tests.py b/test/trace_processor/diff_tests/stdlib/android/tests.py index 4153aabae8..cee51b8372 100644 --- a/test/trace_processor/diff_tests/stdlib/android/tests.py +++ b/test/trace_processor/diff_tests/stdlib/android/tests.py @@ -1906,3 +1906,16 @@ def test_android_suspend_state_no_events(self): 100000000000,8000000000,"awake",0 100000000000,8000000000,"awake",1 """)) + + def test_android_redacted_startup_has_cold_startup_data(self): + return DiffTestBlueprint( + trace=DataPath('redacted-startup.pb'), + query=""" + INCLUDE PERFETTO MODULE android.profiling_manager.startup; + SELECT * FROM android_profiling_manager_cold_startup; + """, + out=Csv(""" + "ts","name","dur","startup_checkpoint" + 1883713423201,"app_startup_ttff",57720540,"TTFF" + 1883713423201,"app_startup_tti",39962036,"TTI" + """)) \ No newline at end of file