1#!/usr/bin/env python3
2# Copyright (C) 2024 The Android Open Source Project
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8#      http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16import synth_common
17from os import sys
18
19CUJ_PID = 5000
20CUJ_MAIN_TID = 5000
21CUJ_UI_TID = 5020
22BACK_PANEL_UI_THREAD_TID = 5040
23
24PROCESS_TRACK = 1234
25CUJ_ASYNC_TRACK = 535
26CUJ_HARDCODED_UI_THREAD_ASYNC_TRACK = 536
27LAYER = "TX - some_layer#0"
28
29
30def add_ui_thread_atrace(trace, ts, ts_end, buf, tid):
31  trace.add_atrace_begin(ts=ts, tid=tid, pid=CUJ_PID, buf=buf)
32  trace.add_atrace_end(ts=ts_end, tid=tid, pid=CUJ_PID)
33
34
35def add_instant_event_in_thread(trace, ts, buf, pid, tid):
36  trace.add_atrace_instant(ts=ts, tid=tid, pid=pid, buf=buf)
37
38
39def add_frame(trace, vsync, ts_do_frame, ts_end_do_frame, tid):
40  add_ui_thread_atrace(
41      trace,
42      ts=ts_do_frame,
43      ts_end=ts_end_do_frame,
44      buf="Choreographer#doFrame %d" % vsync,
45      tid=tid)
46
47
48def add_expected_surface_frame_events(ts, dur, token):
49  trace.add_expected_surface_frame_start_event(
50      ts=ts,
51      cookie=100000 + token,
52      token=token,
53      display_frame_token=100 + token,
54      pid=CUJ_PID,
55      layer_name='')
56  trace.add_frame_end_event(ts=ts + dur, cookie=100000 + token)
57
58
59def add_actual_surface_frame_events(ts, dur, token):
60  cookie = token + 1
61  trace.add_actual_surface_frame_start_event(
62      ts=ts,
63      cookie=100002 + cookie,
64      token=token,
65      display_frame_token=token + 100,
66      pid=CUJ_PID,
67      present_type=1,
68      on_time_finish=1,
69      gpu_composition=0,
70      jank_type=1,
71      prediction_type=3,
72      layer_name=LAYER)
73  trace.add_frame_end_event(ts=ts + dur, cookie=100002 + cookie)
74
75
76def setup_trace():
77  trace = synth_common.create_trace()
78  trace.add_packet()
79  package_name = "com.google.android.with.custom.ui.thread"
80  uid = 10001
81  trace.add_package_list(ts=0, name=package_name, uid=uid, version_code=1)
82  trace.add_process(pid=CUJ_PID, ppid=1, cmdline=package_name, uid=uid)
83  trace.add_thread(
84      tid=CUJ_MAIN_TID, tgid=CUJ_PID, cmdline="MainThread", name="MainThread")
85  trace.add_thread(
86      tid=CUJ_UI_TID, tgid=CUJ_PID, cmdline="UIThread", name="UIThread")
87  trace.add_thread(
88      tid=BACK_PANEL_UI_THREAD_TID,
89      tgid=CUJ_PID,
90      cmdline="BackPanelUiThre",
91      name="BackPanelUiThre")
92  trace.add_process_track_descriptor(PROCESS_TRACK, pid=CUJ_PID)
93  trace.add_track_descriptor(CUJ_ASYNC_TRACK, parent=PROCESS_TRACK)
94  trace.add_track_descriptor(
95      CUJ_HARDCODED_UI_THREAD_ASYNC_TRACK, parent=PROCESS_TRACK)
96  trace.add_ftrace_packet(cpu=0)
97  return trace
98
99
100def setup_cujs(trace):
101  # CUJ to test the new behaviour, where the ui thread is get from an instant
102  # event.
103  cuj_name = "J<CUJ_NAME>"
104  # Tests the deprecated behaviour where the ui thread is get from an hardcoded
105  # list.
106  back_panel_cuj = "J<BACK_PANEL_ARROW>"
107
108  # UI Thread marker, soon after cuj start
109  add_instant_event_in_thread(
110      trace,
111      ts=5_000_001,
112      buf=cuj_name + "#UIThread",
113      pid=CUJ_PID,
114      tid=CUJ_UI_TID)
115
116  # The following is a blocking call during theh cuj, on the cuj ui thread.
117  # It is expected to appear in the output
118  trace.add_atrace_begin(
119      ts=14_000_000, buf="measure", tid=CUJ_UI_TID, pid=CUJ_PID)
120  trace.add_atrace_end(ts=16_000_000, tid=CUJ_UI_TID, pid=CUJ_PID)
121  # The following is not expected in the output as it's in another thread!
122  trace.add_atrace_begin(
123      ts=14_000_000, buf="layout", tid=CUJ_MAIN_TID, pid=CUJ_PID)
124  trace.add_atrace_end(ts=16_000_000, tid=CUJ_MAIN_TID, pid=CUJ_PID)
125
126  trace.add_atrace_begin(
127      ts=15_000_000, buf="animation", tid=BACK_PANEL_UI_THREAD_TID, pid=CUJ_PID)
128  trace.add_atrace_end(ts=17_000_000, tid=BACK_PANEL_UI_THREAD_TID, pid=CUJ_PID)
129
130  add_frame(
131      trace,
132      vsync=10,
133      ts_do_frame=10_000_000,
134      ts_end_do_frame=18_000_000,
135      tid=CUJ_UI_TID)
136
137  add_frame(
138      trace,
139      vsync=20,
140      ts_do_frame=10_000_000,
141      ts_end_do_frame=18_000_000,
142      tid=BACK_PANEL_UI_THREAD_TID)
143
144  trace.add_track_event_slice_begin(
145      ts=5_000_000, track=CUJ_ASYNC_TRACK, name=cuj_name)
146  trace.add_track_event_slice_end(ts=20_000_000, track=CUJ_ASYNC_TRACK)
147
148  trace.add_track_event_slice_begin(
149      ts=5_000_000,
150      track=CUJ_HARDCODED_UI_THREAD_ASYNC_TRACK,
151      name=back_panel_cuj)
152  trace.add_track_event_slice_end(
153      ts=20_000_000, track=CUJ_HARDCODED_UI_THREAD_ASYNC_TRACK)
154
155  add_expected_surface_frame_events(ts=0, dur=16_000_000, token=10)
156  add_actual_surface_frame_events(ts=0, dur=16_000_000, token=10)
157
158  add_expected_surface_frame_events(ts=0, dur=16_000_000, token=20)
159  add_actual_surface_frame_events(ts=0, dur=16_000_000, token=20)
160
161
162trace = setup_trace()
163setup_cujs(trace)
164sys.stdout.buffer.write(trace.trace.SerializeToString())
165