• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1--
2-- Copyright 2022 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--     https://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
16SELECT CREATE_FUNCTION(
17  'VSYNC_FROM_NAME(slice_name STRING)',
18  'STRING',
19  'SELECT CAST(STR_SPLIT($slice_name, " ", 1) AS INTEGER)'
20);
21
22SELECT CREATE_FUNCTION(
23  'GPU_COMPLETION_FENCE_ID_FROM_NAME(slice_name STRING)',
24  'STRING',
25  'SELECT
26    CASE
27      WHEN
28        $slice_name GLOB "GPU completion fence *"
29      THEN
30        CAST(STR_SPLIT($slice_name, " ", 3) AS INTEGER)
31      WHEN
32        $slice_name GLOB "Trace GPU completion fence *"
33      THEN
34        CAST(STR_SPLIT($slice_name, " ", 4) AS INTEGER)
35      WHEN
36        $slice_name GLOB "waiting for GPU completion *"
37      THEN
38        CAST(STR_SPLIT($slice_name, " ", 4) AS INTEGER)
39      WHEN
40        $slice_name GLOB "Trace HWC release fence *"
41      THEN
42        CAST(STR_SPLIT($slice_name, " ", 4) AS INTEGER)
43      WHEN
44        $slice_name GLOB "waiting for HWC release *"
45      THEN
46        CAST(STR_SPLIT($slice_name, " ", 4) AS INTEGER)
47      ELSE NULL
48    END
49  '
50);
51
52-- Find Choreographer#doFrame slices that are between the CUJ markers.
53-- We extract vsync IDs from doFrame slice names and use these as the source
54-- of truth that allow us to get correct slices on the other threads.
55DROP TABLE IF EXISTS android_jank_cuj_do_frame_slice;
56CREATE TABLE android_jank_cuj_do_frame_slice AS
57SELECT
58  cuj.cuj_id,
59  main_thread.upid,
60  main_thread.utid,
61  slice.*,
62  slice.ts + slice.dur AS ts_end,
63  VSYNC_FROM_NAME(slice.name) AS vsync
64FROM android_jank_cuj cuj
65JOIN slice
66  ON slice.ts + slice.dur >= cuj.ts AND slice.ts <= cuj.ts_end
67JOIN android_jank_cuj_main_thread main_thread
68  ON cuj.cuj_id = main_thread.cuj_id
69    AND main_thread.track_id = slice.track_id
70WHERE
71  slice.name GLOB 'Choreographer#doFrame*'
72-- Ignore child slice e.g. "Choreographer#doFrame - resynced to 1234 in 20.0ms"
73  AND slice.name not GLOB '*resynced*'
74  AND slice.dur > 0;
75
76
77-- Store render thread DrawFrames by matching in the vsync IDs extracted from
78-- doFrame slices. In case of multiple layers being drawn, there might be
79-- multiple DrawFrames for a single vsync.
80DROP TABLE IF EXISTS android_jank_cuj_draw_frame_slice;
81CREATE TABLE android_jank_cuj_draw_frame_slice AS
82SELECT
83  cuj_id,
84  render_thread.upid,
85  render_thread.utid,
86  slice.*,
87  slice.ts + slice.dur AS ts_end,
88  VSYNC_FROM_NAME(slice.name) AS vsync
89FROM android_jank_cuj_do_frame_slice do_frame
90JOIN android_jank_cuj_render_thread render_thread USING (cuj_id)
91JOIN slice
92  ON slice.track_id = render_thread.track_id
93WHERE slice.name GLOB 'DrawFrame*'
94  AND VSYNC_FROM_NAME(slice.name) = do_frame.vsync
95  AND slice.dur > 0;
96
97-- Find descendants of DrawFrames which contain the GPU completion fence ID that
98-- is used for signaling that the GPU finished drawing.
99DROP TABLE IF EXISTS android_jank_cuj_gpu_completion_fence;
100CREATE TABLE android_jank_cuj_gpu_completion_fence AS
101SELECT
102  cuj_id,
103  vsync,
104  draw_frame.id AS draw_frame_slice_id,
105  GPU_COMPLETION_FENCE_ID_FROM_NAME(fence.name) AS fence_idx
106FROM android_jank_cuj_draw_frame_slice draw_frame
107JOIN descendant_slice(draw_frame.id) fence
108  ON fence.name GLOB '*GPU completion fence*';
109
110-- Similarly find descendants of DrawFrames which have the HWC release fence ID
111DROP TABLE IF EXISTS android_jank_cuj_hwc_release_fence;
112CREATE TABLE android_jank_cuj_hwc_release_fence AS
113SELECT
114  cuj_id,
115  vsync,
116  draw_frame.id AS draw_frame_slice_id,
117  GPU_COMPLETION_FENCE_ID_FROM_NAME(fence.name) AS fence_idx
118FROM android_jank_cuj_draw_frame_slice draw_frame
119JOIN descendant_slice(draw_frame.id) fence
120  ON fence.name GLOB '*HWC release fence *';
121
122-- Find HWC release slices which indicate when the HWC released the buffer.
123DROP TABLE IF EXISTS android_jank_cuj_hwc_release_slice;
124CREATE TABLE android_jank_cuj_hwc_release_slice AS
125SELECT
126  fence.cuj_id,
127  vsync,
128  slice.*,
129  slice.ts + slice.dur AS ts_end,
130  fence.fence_idx,
131  draw_frame_slice_id
132FROM android_jank_cuj_hwc_release_thread hwc_release_thread
133JOIN slice USING (track_id)
134JOIN android_jank_cuj_hwc_release_fence fence
135  ON fence.cuj_id = hwc_release_thread.cuj_id
136    AND fence.fence_idx = GPU_COMPLETION_FENCE_ID_FROM_NAME(slice.name)
137WHERE
138  slice.name GLOB 'waiting for HWC release *'
139  AND slice.dur > 0;
140
141-- Find GPU completion slices which indicate when the GPU finished drawing.
142DROP TABLE IF EXISTS android_jank_cuj_gpu_completion_slice;
143CREATE TABLE android_jank_cuj_gpu_completion_slice AS
144SELECT
145  fence.cuj_id,
146  vsync,
147  slice.*,
148  slice.ts + slice.dur AS ts_end,
149  hwc_release.ts_end AS hwc_release_ts_end,
150  fence.fence_idx
151FROM android_jank_cuj_gpu_completion_thread gpu_completion_thread
152JOIN slice USING (track_id)
153JOIN android_jank_cuj_gpu_completion_fence fence
154  ON fence.cuj_id = gpu_completion_thread.cuj_id
155  AND fence.fence_idx = GPU_COMPLETION_FENCE_ID_FROM_NAME(slice.name)
156LEFT JOIN android_jank_cuj_hwc_release_slice hwc_release
157  USING (cuj_id, vsync, draw_frame_slice_id)
158WHERE
159  slice.name GLOB 'waiting for GPU completion *'
160  AND slice.dur > 0;
161
162-- Match the frame timeline on the app side with the frame timeline on the SF side.
163-- This way we get the vsyncs IDs of SF frames within the CUJ.
164-- Note that there might be multiple SF vsync IDs that match a single App vsync ID, e.g.
165-- if one App layer produced a frame later and it was picked up by the next SF frame.
166DROP TABLE IF EXISTS android_jank_cuj_app_to_sf_match;
167CREATE TABLE android_jank_cuj_app_to_sf_match AS
168SELECT
169  cuj_id,
170  do_frame.upid AS app_upid,
171  do_frame.vsync AS app_vsync,
172  sf_process.upid AS sf_upid,
173  CAST(sf_timeline.name AS INTEGER) AS sf_vsync
174FROM android_jank_cuj_do_frame_slice do_frame
175JOIN actual_frame_timeline_slice app_timeline
176  ON do_frame.upid = app_timeline.upid
177    AND do_frame.vsync = CAST(app_timeline.name AS INTEGER)
178JOIN directly_connected_flow(app_timeline.id) flow
179  ON flow.slice_in = app_timeline.id
180JOIN actual_frame_timeline_slice sf_timeline
181  ON flow.slice_out = sf_timeline.id
182JOIN android_jank_cuj_sf_process sf_process
183  ON sf_timeline.upid = sf_process.upid
184-- In cases where there are multiple layers drawn we would have separate frame timeline
185-- slice for each of the layers. GROUP BY to deduplicate these rows.
186GROUP BY cuj_id, app_upid, app_vsync, sf_upid, sf_vsync;
187
188SELECT CREATE_VIEW_FUNCTION(
189  'ANDROID_JANK_CUJ_SF_MAIN_THREAD_SLICE(slice_name_glob STRING)',
190  'cuj_id INT, utid INT, vsync INT, id INT, name STRING, ts LONG, dur LONG, ts_end LONG',
191  '
192  WITH sf_vsync AS (
193    SELECT DISTINCT cuj_id, sf_vsync AS vsync
194    FROM android_jank_cuj_app_to_sf_match)
195  SELECT
196    cuj_id,
197    utid,
198    sf_vsync.vsync,
199    slice.id,
200    slice.name,
201    slice.ts,
202    slice.dur,
203    slice.ts + slice.dur AS ts_end
204  FROM slice
205  JOIN android_jank_cuj_sf_main_thread main_thread USING (track_id)
206  JOIN sf_vsync
207    ON VSYNC_FROM_NAME(slice.name) = sf_vsync.vsync
208  WHERE slice.name GLOB $slice_name_glob AND slice.dur > 0
209  ORDER BY cuj_id, vsync;
210  '
211);
212
213DROP TABLE IF EXISTS android_jank_cuj_sf_commit_slice;
214CREATE TABLE android_jank_cuj_sf_commit_slice AS
215SELECT * FROM ANDROID_JANK_CUJ_SF_MAIN_THREAD_SLICE('commit *');
216
217DROP TABLE IF EXISTS android_jank_cuj_sf_composite_slice;
218CREATE TABLE android_jank_cuj_sf_composite_slice AS
219SELECT * FROM ANDROID_JANK_CUJ_SF_MAIN_THREAD_SLICE('composite *');
220
221-- Older builds do not have the commit/composite but onMessageInvalidate instead
222DROP TABLE IF EXISTS android_jank_cuj_sf_on_message_invalidate_slice;
223CREATE TABLE android_jank_cuj_sf_on_message_invalidate_slice AS
224SELECT * FROM ANDROID_JANK_CUJ_SF_MAIN_THREAD_SLICE('onMessageInvalidate *');
225
226DROP VIEW IF EXISTS android_jank_cuj_sf_root_slice;
227CREATE VIEW android_jank_cuj_sf_root_slice AS
228SELECT * FROM android_jank_cuj_sf_commit_slice
229UNION ALL
230SELECT * FROM android_jank_cuj_sf_composite_slice
231UNION ALL
232SELECT * FROM android_jank_cuj_sf_on_message_invalidate_slice;
233
234-- Find descendants of SF main thread slices which contain the GPU completion fence ID that
235-- is used for signaling that the GPU finished drawing.
236DROP TABLE IF EXISTS android_jank_cuj_sf_gpu_completion_fence;
237CREATE TABLE android_jank_cuj_sf_gpu_completion_fence AS
238SELECT
239  cuj_id,
240  vsync,
241  sf_root_slice.id AS sf_root_slice_id,
242  GPU_COMPLETION_FENCE_ID_FROM_NAME(fence.name) AS fence_idx
243FROM android_jank_cuj_sf_root_slice sf_root_slice
244JOIN descendant_slice(sf_root_slice.id) fence
245  ON fence.name GLOB '*GPU completion fence*';
246
247-- Find GPU completion slices which indicate when the GPU finished drawing.
248DROP TABLE IF EXISTS android_jank_cuj_sf_gpu_completion_slice;
249CREATE TABLE android_jank_cuj_sf_gpu_completion_slice AS
250SELECT
251  fence.cuj_id,
252  vsync,
253  slice.*,
254  slice.ts + slice.dur AS ts_end,
255  fence.fence_idx
256FROM android_jank_cuj_sf_gpu_completion_fence fence
257JOIN android_jank_cuj_sf_gpu_completion_thread gpu_completion_thread
258JOIN slice
259  ON slice.track_id = gpu_completion_thread.track_id
260    AND fence.fence_idx = GPU_COMPLETION_FENCE_ID_FROM_NAME(slice.name)
261WHERE
262  slice.name GLOB 'waiting for GPU completion *'
263  AND slice.dur > 0;
264
265
266-- Find REThreaded::drawLayers on RenderEngine thread.
267-- These will be only relevant if SF is doing client composition so we check if
268-- the drawLayers slice is completely within the bounds of composeSurfaces on SF
269-- main thread.
270DROP TABLE IF EXISTS android_jank_cuj_sf_draw_layers_slice;
271CREATE TABLE android_jank_cuj_sf_draw_layers_slice AS
272WITH compose_surfaces AS (
273  SELECT
274    cuj_id,
275    vsync,
276    sf_root_slice.id AS sf_root_slice_id,
277    compose_surfaces.ts,
278    compose_surfaces.ts + compose_surfaces.dur AS ts_end
279  FROM android_jank_cuj_sf_root_slice sf_root_slice
280  JOIN descendant_slice(sf_root_slice.id) compose_surfaces
281    ON compose_surfaces.name = 'composeSurfaces'
282)
283SELECT
284  cuj_id,
285  re_thread.utid,
286  vsync,
287  draw_layers.*,
288  draw_layers.ts + draw_layers.dur AS ts_end,
289  -- Store composeSurfaces ts as this will simplify calculating frame boundaries
290  compose_surfaces.ts AS ts_compose_surfaces
291FROM compose_surfaces
292JOIN android_jank_cuj_sf_render_engine_thread re_thread
293JOIN slice draw_layers
294  ON draw_layers.track_id = re_thread.track_id
295    AND draw_layers.ts >= compose_surfaces.ts
296    AND draw_layers.ts + draw_layers.dur <= compose_surfaces.ts_end
297WHERE
298  draw_layers.name = 'REThreaded::drawLayers'
299  AND draw_layers.dur > 0;
300