1-- 2-- Copyright 2023 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 17INCLUDE PERFETTO MODULE android.binder_breakdown; 18INCLUDE PERFETTO MODULE linux.cpu.utilization.thread; 19INCLUDE PERFETTO MODULE linux.cpu.utilization.slice; 20INCLUDE PERFETTO MODULE slices.with_context; 21INCLUDE PERFETTO MODULE slices.cpu_time; 22INCLUDE PERFETTO MODULE slices.flat_slices; 23 24SELECT RUN_METRIC('android/android_cpu.sql'); 25SELECT RUN_METRIC('android/android_powrails.sql'); 26 27-- Attaching thread proto with media thread name 28DROP VIEW IF EXISTS core_type_proto_per_thread_name; 29CREATE PERFETTO VIEW core_type_proto_per_thread_name AS 30SELECT 31utid, 32thread.name AS thread_name, 33core_type_proto_per_thread.proto AS proto 34FROM core_type_proto_per_thread 35JOIN thread using(utid) 36WHERE thread.name = 'MediaCodec_loop' OR 37 thread.name = 'CodecLooper' 38GROUP BY thread.name; 39 40-- All process that has codec thread 41DROP TABLE IF EXISTS android_codec_process; 42CREATE PERFETTO TABLE android_codec_process AS 43SELECT 44 utid, 45 upid, 46 process.name AS process_name 47FROM thread 48JOIN process using(upid) 49WHERE thread.name = 'MediaCodec_loop' OR 50 thread.name = 'CodecLooper' 51GROUP BY process_name, thread.name; 52 53-- Getting cpu cycles for the threads 54DROP VIEW IF EXISTS cpu_cycles_runtime; 55CREATE PERFETTO VIEW cpu_cycles_runtime AS 56SELECT 57 utid, 58 megacycles, 59 runtime, 60 proto, 61 process_name, 62 thread_name 63FROM android_codec_process 64JOIN cpu_cycles_per_thread using(utid) 65JOIN core_type_proto_per_thread_name using(utid); 66 67-- Traces are collected using specific traits in codec framework. These traits 68-- are mapped to actual names of slices and then combined with other tables to 69-- give out the total_cpu and cpu_running time. 70 71-- Utility function to trim codec trace string: extract the string demilited 72-- by the limiter. 73CREATE OR REPLACE PERFETTO FUNCTION extract_codec_string(slice_name STRING, limiter STRING) 74RETURNS STRING AS 75SELECT CASE 76 -- Delimit with the first occurrence 77 WHEN instr($slice_name, $limiter) > 0 78 THEN substr($slice_name, 1, instr($slice_name, $limiter) - 1) 79 ELSE $slice_name 80END; 81 82CREATE OR REPLACE PERFETTO FUNCTION extract_codec_string_after(slice_name STRING, limiter STRING) 83RETURNS STRING AS 84SELECT CASE 85 -- Delimit with the first occurrence 86 WHEN instr($slice_name, $limiter) > 0 87 THEN substr($slice_name, instr($slice_name, $limiter) + length($limiter), length($slice_name)) 88 ELSE $slice_name 89END; 90 91-- Traits strings from codec framework 92DROP TABLE IF EXISTS trace_trait_table; 93CREATE TABLE trace_trait_table(trace_trait TEXT UNIQUE); 94INSERT INTO trace_trait_table VALUES 95 ('MediaCodec::*'), 96 ('CCodec::*'), 97 ('CCodecBufferChannel::*'), 98 ('C2PooledBlockPool::*'), 99 ('C2hal::*'), 100 ('ACodec::*'), 101 ('FrameDecoder::*'), 102 ('*android.hardware.media.c2.*'), 103 ('*android.hardware.drm.ICryptoPlugin*'); 104 105-- Maps traits to slice strings. Any string with '@' is considered to indicate 106-- the same trace with different information.Hence those strings are delimited 107-- using '@' and considered as part of single slice. 108 109-- View to hold slice ids(sid) and the assigned slice ids for codec slices. 110DROP TABLE IF EXISTS codec_slices; 111CREATE PERFETTO TABLE codec_slices AS 112WITH 113 __codec_slices AS ( 114 SELECT DISTINCT 115 IIF(instr(name, 'android.hardware.') > 0, 116 extract_codec_string_after(name, 'android.hardware.'), 117 extract_codec_string(name, '(')) AS codec_string, 118 slice.id AS sid, 119 slice.name AS sname 120 FROM slice 121 JOIN trace_trait_table ON slice.name GLOB trace_trait 122 ), 123 _codec_slices AS ( 124 SELECT DISTINCT codec_string, 125 ROW_NUMBER() OVER() AS codec_slice_idx 126 FROM __codec_slices 127 GROUP BY codec_string 128 ) 129SELECT 130 codec_slice_idx, 131 a.codec_string, 132 sid 133FROM __codec_slices a 134JOIN _codec_slices b USING(codec_string); 135 136-- Combine slice and and cpu dur and cycles info 137DROP TABLE IF EXISTS codec_slice_cpu_running; 138CREATE PERFETTO TABLE codec_slice_cpu_running AS 139SELECT 140 codec_string, 141 MIN(ts) AS min_ts, 142 MAX(ts + t.dur) AS max_ts, 143 SUM(t.dur) AS sum_dur_ns, 144 SUM(ct.cpu_time) AS cpu_run_ns, 145 AVG(t.dur) AS avg_dur_ns, 146 CAST(SUM(millicycles) AS INT64) AS cpu_cycles, 147 CAST(SUM(megacycles) AS INT64) AS cpu_mega_cycles, 148 IIF(INSTR(cc.thread_name, 'binder') > 0, 149 'binder', cc.thread_name) as thread_name_mod, 150 cc.process_name as process_name, 151 COUNT (*) as count 152FROM codec_slices 153JOIN thread_slice t ON(sid = t.id) 154JOIN thread_slice_cpu_cycles cc ON(sid = cc.id) 155JOIN thread_slice_cpu_time ct ON(sid = ct.id) 156GROUP BY codec_slice_idx, thread_name_mod, cc.process_name; 157 158-- Codec framework message latencies 159DROP TABLE IF EXISTS fwk_looper_msg_latency; 160CREATE PERFETTO TABLE fwk_looper_msg_latency AS 161SELECT 162 slice.name AS normalized_name, 163 NULL AS process_name, 164 extract_codec_string(slice.name,'::') AS thread_name, 165 COUNT(*) AS count, 166 MAX(slice.dur/1e3) AS max_us, 167 MIN(slice.dur/1e3) AS min_us, 168 AVG(slice.dur)/1e3 AS avg_us, 169 SUM(slice.dur)/1e3 AS agg_us 170FROM slice 171WHERE slice.name GLOB '*::Looper_msg*' 172GROUP BY slice.name, thread_name, process_name; 173 174-- Qualifying individual slice latency 175DROP TABLE IF EXISTS latency_codec_slices; 176CREATE PERFETTO TABLE latency_codec_slices AS 177WITH 178 _filtered_raw_codec_flattened_slices AS( 179 SELECT 180 IIF(instr(name, 'android.hardware.') > 0, 181 extract_codec_string_after(name, 'android.hardware.'), 182 extract_codec_string(name, '(')) AS normalized_name, 183 slice_id, 184 root_id, 185 dur, 186 IIF(INSTR(thread_name, 'binder') > 0, 187 'binder', thread_name) as thread_name, 188 process_name, 189 depth 190 FROM _slice_flattened 191 JOIN trace_trait_table ON name GLOB trace_trait 192 ), 193 _filtered_agg_codec_flattened_slices AS( 194 SELECT 195 root_id, 196 normalized_name, 197 process_name, 198 thread_name, 199 SUM(dur)/1e3 AS _agg_us 200 FROM _filtered_raw_codec_flattened_slices 201 GROUP BY slice_id, root_id 202 ORDER BY depth) 203SELECT 204 normalized_name, 205 process_name, 206 thread_name, 207 COUNT(*) as count, 208 MAX(_agg_us) as max_us, 209 MIN(_agg_us) as min_us, 210 AVG(_agg_us) as avg_us, 211 SUM(_agg_us) as agg_us 212 FROM _filtered_agg_codec_flattened_slices 213 GROUP BY normalized_name, thread_name, process_name 214UNION ALL 215SELECT 216 normalized_name as codec_string, 217 process_name, 218 thread_name, 219 count, 220 max_us, 221 min_us, 222 avg_us, 223 agg_us 224 FROM fwk_looper_msg_latency; 225 226-- POWER consumed during codec use. 227DROP VIEW IF EXISTS codec_power_mw; 228CREATE PERFETTO VIEW codec_power_mw AS 229SELECT 230 AndroidCodecMetrics_Rail_Info ( 231 'energy', tot_used_power, 232 'power_mw', tot_used_power / (powrail_end_ts - powrail_start_ts) 233 ) AS proto, 234 name 235FROM avg_used_powers; 236 237-- Generate proto for the trace 238DROP VIEW IF EXISTS metrics_per_slice_type; 239CREATE PERFETTO VIEW metrics_per_slice_type AS 240SELECT 241 COALESCE(codec_string, normalized_name) as codec_string, 242 COALESCE(rslice.process_name, lat.process_name) as process_name, 243 COALESCE(lat.thread_name, rslice.thread_name_mod) as thread_name, 244 max_us, 245 min_us, 246 avg_us, 247 agg_us, 248 lat.count AS count, 249 AndroidCodecMetrics_Detail( 250 'total_cpu_ns', CAST(sum_dur_ns AS INT64), 251 'running_cpu_ns', CAST(cpu_run_ns AS INT64), 252 'avg_running_cpu_ns', CAST((cpu_run_ns/rslice.count) AS INT64), 253 'avg_time_ns', CAST(avg_dur_ns AS INT64), 254 'total_cpu_cycles', CAST(cpu_cycles AS INT64), 255 'avg_cpu_cycles', CAST((cpu_cycles/rslice.count) AS INT64), 256 'count', rslice.count, 257 'self', AndroidCodecMetrics_Detail_Latency ( 258 'max_us', CAST(max_us AS INT64), 259 'min_us', CAST(min_us AS INT64), 260 'avg_us', CAST(avg_us AS INT64), 261 'agg_us', CAST(agg_us AS INT64), 262 'count', lat.count 263 ) 264 ) AS proto 265FROM latency_codec_slices lat 266FULL JOIN codec_slice_cpu_running rslice 267ON codec_string = lat.normalized_name 268AND lat.thread_name = rslice.thread_name_mod 269AND lat.process_name = rslice.process_name; 270 271-- Generating codec framework cpu metric 272DROP VIEW IF EXISTS codec_metrics_output; 273CREATE PERFETTO VIEW codec_metrics_output AS 274SELECT AndroidCodecMetrics ( 275 'cpu_usage', ( 276 SELECT RepeatedField( 277 AndroidCodecMetrics_CpuUsage( 278 'process_name', process_name, 279 'thread', AndroidCodecMetrics_CpuUsage_ThreadInfo( 280 'name', thread_name, 281 'info', AndroidCodecMetrics_CpuUsage_ThreadInfo_Details( 282 'thread_cpu_ns', CAST((runtime) AS INT64), 283 'core_data', proto 284 ) 285 ) 286 ) 287 ) FROM cpu_cycles_runtime 288 ), 289 'codec_function', ( 290 SELECT RepeatedField ( 291 AndroidCodecMetrics_CodecFunction( 292 'codec_string', codec_string, 293 'process', AndroidCodecMetrics_CodecFunction_Process( 294 'name', process_name, 295 'thread', AndroidCodecMetrics_CodecFunction_Process_Thread( 296 'name', thread_name, 297 'detail', metrics_per_slice_type.proto 298 ) 299 ) 300 ) 301 ) FROM metrics_per_slice_type 302 ), 303 'energy', ( 304 AndroidCodecMetrics_Energy( 305 'total_energy', (SELECT SUM(tot_used_power) FROM avg_used_powers), 306 'duration', (SELECT MAX(powrail_end_ts) - MIN(powrail_start_ts) FROM avg_used_powers), 307 'power_mw', (SELECT SUM(tot_used_power) / (MAX(powrail_end_ts) - MIN(powrail_start_ts)) FROM avg_used_powers), 308 'rail', ( 309 SELECT RepeatedField ( 310 AndroidCodecMetrics_Rail ( 311 'name', name, 312 'info', codec_power_mw.proto 313 ) 314 ) FROM codec_power_mw 315 ) 316 ) 317 ) 318); 319