1-- 2-- Copyright 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-- 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-- 16 17-- Table of suspended and awake slices. 18-- 19-- Selects either the minimal or full ftrace source depending on what's 20-- available, marks suspended periods, and complements them to give awake 21-- periods. 22CREATE PERFETTO TABLE android_suspend_state ( 23 -- Timestamp 24 ts TIMESTAMP, 25 -- Duration 26 dur DURATION, 27 -- 'awake' or 'suspended' 28 power_state STRING 29) AS 30WITH 31 suspend_slice_from_minimal AS ( 32 SELECT 33 ts, 34 dur 35 FROM track AS t 36 JOIN slice AS s 37 ON s.track_id = t.id 38 WHERE 39 t.name = 'Suspend/Resume Minimal' 40 ), 41 suspend_slice AS ( 42 SELECT 43 ts, 44 dur 45 FROM suspend_slice_from_minimal 46 UNION ALL 47 SELECT 48 ts, 49 dur 50 FROM slice 51 JOIN track 52 ON slice.track_id = track.id 53 WHERE 54 track.name = 'Suspend/Resume Latency' 55 AND ( 56 slice.name = 'syscore_resume(0)' OR slice.name = 'timekeeping_freeze(0)' 57 ) 58 AND dur != -1 59 AND NOT EXISTS( 60 SELECT 61 * 62 FROM suspend_slice_from_minimal 63 ) 64 ), 65 awake_slice AS ( 66 -- If we don't have any rows, use the trace bounds if bounds are defined. 67 SELECT 68 trace_start() AS ts, 69 trace_dur() AS dur 70 WHERE 71 ( 72 SELECT 73 count(*) 74 FROM suspend_slice 75 ) = 0 AND dur > 0 76 UNION ALL 77 -- If we do have rows, create one slice from the trace start to the first suspend. 78 SELECT 79 trace_start() AS ts, 80 ( 81 SELECT 82 min(ts) 83 FROM suspend_slice 84 ) - trace_start() AS dur 85 WHERE 86 ( 87 SELECT 88 count(*) 89 FROM suspend_slice 90 ) != 0 91 UNION ALL 92 -- And then one slice for each suspend, from the end of the suspend to the 93 -- start of the next one (or the end of the trace if there is no next one). 94 SELECT 95 ts + dur AS ts, 96 coalesce(lead(ts) OVER (ORDER BY ts), trace_end()) - ts - dur AS dur 97 FROM suspend_slice 98 ) 99SELECT 100 ts, 101 dur, 102 'awake' AS power_state 103FROM awake_slice 104UNION ALL 105SELECT 106 ts, 107 dur, 108 'suspended' AS power_state 109FROM suspend_slice 110ORDER BY 111 ts; 112 113-- Order by will cause Perfetto table to index by ts.; 114 115-- Extracts the duration without counting CPU suspended time from an event. 116-- This is the same as converting an event duration from wall clock to monotonic clock. 117-- If there was no CPU suspend, the result is same as |dur|. 118CREATE PERFETTO FUNCTION _extract_duration_without_suspend( 119 -- Timestamp of event. 120 ts TIMESTAMP, 121 -- Duration of event. 122 dur DURATION 123) 124RETURNS LONG AS 125SELECT 126 to_monotonic($ts + $dur) - to_monotonic($ts); 127