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 16DROP TABLE IF EXISTS vsync_missed_callback; 17CREATE TABLE vsync_missed_callback AS 18SELECT CAST(STR_SPLIT(name, 'Callback#', 1) AS INTEGER) AS vsync, 19 MAX(name GLOB '*SF*') as sf_callback_missed, 20 MAX(name GLOB '*HWUI*') as hwui_callback_missed 21FROM slice 22WHERE name GLOB '*FT#Missed*Callback*' 23GROUP BY vsync; 24 25DROP TABLE IF EXISTS android_jank_cuj_frame_timeline; 26CREATE TABLE android_jank_cuj_frame_timeline AS 27WITH actual_timeline_with_vsync AS ( 28 SELECT 29 *, 30 CAST(name AS INTEGER) AS vsync 31 FROM actual_frame_timeline_slice 32 WHERE dur > 0 33) 34SELECT 35 cuj_id, 36 vsync, 37 -- We use MAX to check if at least one of the layers jank_type matches the pattern 38 MAX(jank_type GLOB '*App Deadline Missed*') AS app_missed, 39 -- We use MAX to check if at least one of the layers jank_type matches the pattern 40 MAX( 41 jank_type GLOB '*SurfaceFlinger CPU Deadline Missed*' 42 OR jank_type GLOB '*SurfaceFlinger GPU Deadline Missed*' 43 OR jank_type GLOB '*SurfaceFlinger Scheduling*' 44 OR jank_type GLOB '*Prediction Error*' 45 OR jank_type GLOB '*Display HAL*') AS sf_missed, 46 IFNULL(MAX(sf_callback_missed), 0) AS sf_callback_missed, 47 IFNULL(MAX(hwui_callback_missed), 0) AS hwui_callback_missed, 48 -- We use MIN to check if ALL layers finished on time 49 MIN(on_time_finish) AS on_time_finish, 50 MAX(timeline.ts + timeline.dur) AS ts_end_actual, 51 MAX(timeline.dur) AS dur, 52 -- At the moment of writing we expect to see at most one expected_frame_timeline_slice 53 -- for a given vsync but using MAX here in case this changes in the future. 54 -- In case expected timeline is missing, as a fallback we use the typical frame deadline 55 -- for 60Hz. 56 COALESCE(MAX(expected.dur), 16600000) AS dur_expected, 57 COUNT(DISTINCT timeline.layer_name) as number_of_layers_for_frame, 58 -- we use MAX to get at least one of the frame's layer names 59 MAX(timeline.layer_name) as frame_layer_name 60FROM android_jank_cuj_vsync_boundary boundary 61JOIN actual_timeline_with_vsync timeline 62 ON boundary.upid = timeline.upid 63 AND vsync >= vsync_min 64 AND vsync <= vsync_max 65LEFT JOIN expected_frame_timeline_slice expected 66 ON expected.upid = timeline.upid AND expected.name = timeline.name 67LEFT JOIN vsync_missed_callback missed_callback USING(vsync) 68WHERE 69 boundary.layer_id IS NULL 70 OR ( 71 timeline.layer_name GLOB '*#*' 72 AND boundary.layer_id 73 = CAST(STR_SPLIT(timeline.layer_name, '#', 1) AS INTEGER)) 74GROUP BY cuj_id, vsync; 75 76DROP TABLE IF EXISTS android_jank_cuj_layer_name; 77CREATE TABLE android_jank_cuj_layer_name AS 78SELECT 79 cuj_id, 80 MAX(frame_layer_name) as layer_name 81FROM android_jank_cuj_frame_timeline timeline 82GROUP BY cuj_id 83-- Return only cujs where the max number of layers for all frames in the whole cuj equals 1, 84-- this is to infer the layer name if the cuj marker for layer id is not present 85HAVING MAX(number_of_layers_for_frame) = 1; 86 87-- Matches slices and boundaries to compute estimated frame boundaries across 88-- all threads. Joins with the actual timeline to figure out which frames missed 89-- the deadline and whether the app process or SF are at fault. 90DROP TABLE IF EXISTS android_jank_cuj_frame; 91CREATE TABLE android_jank_cuj_frame AS 92WITH frame_base AS ( 93 SELECT 94 cuj_id, 95 ROW_NUMBER() OVER (PARTITION BY cuj_id ORDER BY do_frame.vsync ASC) AS frame_number, 96 vsync, 97 boundary.ts, 98 boundary.ts_expected, 99 boundary.ts_do_frame_start, 100 COUNT(fence_idx) AS gpu_fence_count, 101 COUNT(fence_idx) > 0 AS drew_anything 102 FROM android_jank_cuj_do_frame_slice do_frame 103 JOIN android_jank_cuj_main_thread_frame_boundary boundary USING (cuj_id, vsync) 104 JOIN android_jank_cuj_draw_frame_slice draw_frame USING (cuj_id, vsync) 105 LEFT JOIN android_jank_cuj_gpu_completion_fence fence USING (cuj_id, vsync) 106 WHERE draw_frame.id = fence.draw_frame_slice_id 107 GROUP BY cuj_id, vsync, boundary.ts, boundary.ts_do_frame_start 108) 109SELECT 110 frame_base.*, 111 app_missed, 112 sf_missed, 113 sf_callback_missed, 114 hwui_callback_missed, 115 on_time_finish, 116 ts_end_actual - ts AS dur, 117 ts_end_actual - ts_do_frame_start AS dur_unadjusted, 118 dur_expected, 119 ts_end_actual AS ts_end 120FROM frame_base 121JOIN android_jank_cuj_frame_timeline USING (cuj_id, vsync); 122 123-- Similar to `android_jank_cuj_frame` computes overall SF frame boundaries. 124-- The computation is somewhat simpler as most of SF work happens within the duration of 125-- the commit/composite slices on the main thread. 126DROP TABLE IF EXISTS android_jank_cuj_sf_frame; 127CREATE TABLE android_jank_cuj_sf_frame AS 128SELECT 129 cuj_id, 130 ROW_NUMBER() OVER (PARTITION BY cuj_id ORDER BY vsync ASC) AS frame_number, 131 vsync, 132 boundary.ts, 133 boundary.ts_main_thread_start, 134 boundary.ts_end, 135 boundary.dur, 136 actual_timeline.jank_tag = 'Self Jank' AS sf_missed, 137 NULL AS app_missed, -- for simplicity align schema with android_jank_cuj_frame 138 jank_tag, 139 jank_type, 140 prediction_type, 141 present_type, 142 gpu_composition, 143 -- In case expected timeline is missing, as a fallback we use the typical frame deadline 144 -- for 60Hz. 145 -- See similar expression in android_jank_cuj_frame_timeline. 146 COALESCE(expected_timeline.dur, 16600000) AS dur_expected 147FROM android_jank_cuj_sf_main_thread_frame_boundary boundary 148JOIN android_jank_cuj_sf_process sf_process 149JOIN actual_frame_timeline_slice actual_timeline 150 ON actual_timeline.upid = sf_process.upid 151 AND boundary.vsync = CAST(actual_timeline.name AS INTEGER) 152LEFT JOIN expected_frame_timeline_slice expected_timeline 153 ON expected_timeline.upid = actual_timeline.upid 154 AND expected_timeline.name = actual_timeline.name; 155