Handle latency CUJ state (as cancelled or timeout) (#5376)
in the stdlib all latency CUJs were considered as completed sucessfully,
even if some were not. This fixes it taking into account also the
optional instant event.
Bug: 498209719
diff --git a/src/trace_processor/perfetto_sql/stdlib/android/cujs/sysui_cujs.sql b/src/trace_processor/perfetto_sql/stdlib/android/cujs/sysui_cujs.sql
index 015b22d..3711b29 100644
--- a/src/trace_processor/perfetto_sql/stdlib/android/cujs/sysui_cujs.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/android/cujs/sysui_cujs.sql
@@ -142,6 +142,34 @@
ORDER BY
ts ASC;
+-- Track IDs for all tracks named after Latency CUJs.
+CREATE PERFETTO TABLE _latency_cuj_tracks AS
+SELECT
+ id,
+ name
+FROM track
+WHERE
+ name GLOB 'L<*>';
+
+-- Markers (cancel, timeout) related to Latency CUJ slices.
+CREATE PERFETTO TABLE _latency_cuj_markers AS
+SELECT
+ cuj_slice.id AS cuj_slice_id,
+ CASE WHEN s.name = 'cancel' THEN 'cancel' ELSE 'timeout' END AS marker_type
+FROM slice AS cuj_slice
+JOIN _latency_cuj_tracks AS t
+ ON t.name = cuj_slice.name
+JOIN slice AS s
+ ON s.track_id = t.id
+WHERE
+ s.dur = 0
+ AND s.ts >= cuj_slice.ts
+ AND s.ts <= cuj_slice.ts + cuj_slice.dur
+ AND cuj_slice.name GLOB 'L<*>'
+ AND (
+ s.name = 'cancel' OR s.name = 'timeout'
+ );
+
-- Table tracking all latency CUJs information.
CREATE PERFETTO TABLE android_sysui_latency_cujs (
-- Unique incremental ID for each CUJ.
@@ -179,16 +207,32 @@
ts,
ts + dur AS ts_end,
dur,
- 'completed' AS state
+ CASE
+ WHEN EXISTS(
+ SELECT
+ 1
+ FROM _latency_cuj_markers AS m
+ WHERE
+ m.cuj_slice_id = slice.id AND m.marker_type = 'cancel'
+ )
+ THEN 'canceled'
+ WHEN EXISTS(
+ SELECT
+ 1
+ FROM _latency_cuj_markers AS m
+ WHERE
+ m.cuj_slice_id = slice.id AND m.marker_type = 'timeout'
+ )
+ THEN 'timeout'
+ ELSE 'completed'
+ END AS state
FROM slice
JOIN process_track
ON slice.track_id = process_track.id
JOIN process
USING (upid)
WHERE
- -- TODO(b/447577048): Add filtering support for completed/canceled latency CUJs.
- slice.name GLOB 'L<*>'
- AND dur > 0;
+ slice.name GLOB 'L<*>' AND dur > 0;
-- Table tracking all jank/latency CUJs information.
CREATE PERFETTO TABLE android_jank_latency_cujs (
diff --git a/test/trace_processor/diff_tests/stdlib/android/latency_cujs_state_trace.py b/test/trace_processor/diff_tests/stdlib/android/latency_cujs_state_trace.py
new file mode 100644
index 0000000..41f7ed7
--- /dev/null
+++ b/test/trace_processor/diff_tests/stdlib/android/latency_cujs_state_trace.py
@@ -0,0 +1,74 @@
+#!/usr/bin/env python3
+# Copyright (C) 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
+#
+# 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 synth_common
+import sys
+
+SYSUI_PID = 5000
+SYSUI_UI_TID = 5020
+
+
+def setup_trace():
+ trace = synth_common.create_trace()
+ trace.add_packet()
+ trace.add_package_list(
+ ts=0, name="com.android.systemui", uid=10001, version_code=1)
+ trace.add_process(
+ pid=SYSUI_PID, ppid=SYSUI_PID, cmdline="com.android.systemui", uid=10001)
+ trace.add_thread(
+ tid=SYSUI_PID, tgid=SYSUI_PID, cmdline="MainThread", name="MainThread")
+ trace.add_ftrace_packet(cpu=0)
+ return trace
+
+
+trace = setup_trace()
+
+# CUJ 1: Completed
+trace.add_async_atrace_for_thread(
+ ts=10_000_000,
+ ts_end=20_000_000,
+ buf="L<CUJ_COMPLETED>",
+ pid=SYSUI_PID,
+ tid=SYSUI_UI_TID)
+
+# CUJ 2: Canceled
+trace.add_async_atrace_for_thread(
+ ts=30_000_000,
+ ts_end=40_000_000,
+ buf="L<CUJ_CANCELED>",
+ pid=SYSUI_PID,
+ tid=SYSUI_UI_TID)
+trace.add_atrace_instant_for_track(
+ ts=35_000_000,
+ buf="cancel",
+ pid=SYSUI_PID,
+ tid=SYSUI_UI_TID,
+ track_name="L<CUJ_CANCELED>")
+
+# CUJ 3: Timeout
+trace.add_async_atrace_for_thread(
+ ts=50_000_000,
+ ts_end=60_000_000,
+ buf="L<CUJ_TIMEOUT>",
+ pid=SYSUI_PID,
+ tid=SYSUI_UI_TID)
+trace.add_atrace_instant_for_track(
+ ts=55_000_000,
+ buf="timeout",
+ pid=SYSUI_PID,
+ tid=SYSUI_UI_TID,
+ track_name="L<CUJ_TIMEOUT>")
+
+sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/diff_tests/stdlib/android/sysui_cujs_test.py b/test/trace_processor/diff_tests/stdlib/android/sysui_cujs_test.py
index 7b681e1..8df5af8 100644
--- a/test/trace_processor/diff_tests/stdlib/android/sysui_cujs_test.py
+++ b/test/trace_processor/diff_tests/stdlib/android/sysui_cujs_test.py
@@ -53,3 +53,19 @@
1,1,"com.android.systemui","L<IGNORED_CUJ_1>","IGNORED_CUJ_1",53,150000000,155000000,5000000,"completed"
2,1,"com.android.systemui","L<IGNORED_CUJ_2>","IGNORED_CUJ_2",58,156000000,160000000,4000000,"completed"
"""))
+
+ def test_android_sysui_latency_cujs_state(self):
+ return DiffTestBlueprint(
+ trace=Path('latency_cujs_state_trace.py'),
+ query="""
+ INCLUDE PERFETTO MODULE android.cujs.sysui_cujs;
+ SELECT cuj_name, state
+ FROM android_sysui_latency_cujs
+ ORDER BY cuj_name;
+ """,
+ out=Csv("""
+ "cuj_name","state"
+ "CUJ_CANCELED","canceled"
+ "CUJ_COMPLETED","completed"
+ "CUJ_TIMEOUT","timeout"
+ """))