1*6dbdd20aSAndroid Build Coastguard Worker// Copyright (C) 2023 The Android Open Source Project 2*6dbdd20aSAndroid Build Coastguard Worker// 3*6dbdd20aSAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License"); 4*6dbdd20aSAndroid Build Coastguard Worker// you may not use this file except in compliance with the License. 5*6dbdd20aSAndroid Build Coastguard Worker// You may obtain a copy of the License at 6*6dbdd20aSAndroid Build Coastguard Worker// 7*6dbdd20aSAndroid Build Coastguard Worker// http://www.apache.org/licenses/LICENSE-2.0 8*6dbdd20aSAndroid Build Coastguard Worker// 9*6dbdd20aSAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software 10*6dbdd20aSAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS, 11*6dbdd20aSAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*6dbdd20aSAndroid Build Coastguard Worker// See the License for the specific language governing permissions and 13*6dbdd20aSAndroid Build Coastguard Worker// limitations under the License. 14*6dbdd20aSAndroid Build Coastguard Worker 15*6dbdd20aSAndroid Build Coastguard Workerimport {NUM, STR} from '../../trace_processor/query_result'; 16*6dbdd20aSAndroid Build Coastguard Workerimport {Trace} from '../../public/trace'; 17*6dbdd20aSAndroid Build Coastguard Workerimport {PerfettoPlugin} from '../../public/plugin'; 18*6dbdd20aSAndroid Build Coastguard Workerimport {addDebugSliceTrack} from '../../components/tracks/debug_tracks'; 19*6dbdd20aSAndroid Build Coastguard Worker 20*6dbdd20aSAndroid Build Coastguard Workerexport default class implements PerfettoPlugin { 21*6dbdd20aSAndroid Build Coastguard Worker static readonly id = 'dev.perfetto.AndroidClientServer'; 22*6dbdd20aSAndroid Build Coastguard Worker async onTraceLoad(ctx: Trace): Promise<void> { 23*6dbdd20aSAndroid Build Coastguard Worker ctx.commands.registerCommand({ 24*6dbdd20aSAndroid Build Coastguard Worker id: 'dev.perfetto.AndroidClientServer#ThreadRuntimeIPC', 25*6dbdd20aSAndroid Build Coastguard Worker name: 'Show dependencies in client server model', 26*6dbdd20aSAndroid Build Coastguard Worker callback: async (sliceId) => { 27*6dbdd20aSAndroid Build Coastguard Worker if (sliceId === undefined) { 28*6dbdd20aSAndroid Build Coastguard Worker sliceId = prompt('Enter a slice id', ''); 29*6dbdd20aSAndroid Build Coastguard Worker if (sliceId === null) return; 30*6dbdd20aSAndroid Build Coastguard Worker } 31*6dbdd20aSAndroid Build Coastguard Worker await ctx.engine.query(` 32*6dbdd20aSAndroid Build Coastguard Worker include perfetto module android.binder; 33*6dbdd20aSAndroid Build Coastguard Worker include perfetto module graphs.search; 34*6dbdd20aSAndroid Build Coastguard Worker 35*6dbdd20aSAndroid Build Coastguard Worker create or replace perfetto table __binder_for_slice_${sliceId} as 36*6dbdd20aSAndroid Build Coastguard Worker with s as materialized ( 37*6dbdd20aSAndroid Build Coastguard Worker select slice.id, ts, ts + dur as ts_end, dur, upid 38*6dbdd20aSAndroid Build Coastguard Worker from thread_slice slice 39*6dbdd20aSAndroid Build Coastguard Worker where slice.id = ${sliceId} 40*6dbdd20aSAndroid Build Coastguard Worker ), 41*6dbdd20aSAndroid Build Coastguard Worker child_binder_txns_for_slice as materialized ( 42*6dbdd20aSAndroid Build Coastguard Worker select 43*6dbdd20aSAndroid Build Coastguard Worker (select id from s) as source_node_id, 44*6dbdd20aSAndroid Build Coastguard Worker binder_txn_id as dest_node_id 45*6dbdd20aSAndroid Build Coastguard Worker from descendant_slice((select id from s)) as desc 46*6dbdd20aSAndroid Build Coastguard Worker join android_binder_txns txns on desc.id = txns.binder_txn_id 47*6dbdd20aSAndroid Build Coastguard Worker ), 48*6dbdd20aSAndroid Build Coastguard Worker binder_txns_in_slice_intervals as materialized ( 49*6dbdd20aSAndroid Build Coastguard Worker select 50*6dbdd20aSAndroid Build Coastguard Worker binder_txn_id as source_node_id, 51*6dbdd20aSAndroid Build Coastguard Worker binder_reply_id as dest_node_id 52*6dbdd20aSAndroid Build Coastguard Worker from android_binder_txns 53*6dbdd20aSAndroid Build Coastguard Worker where client_ts > (select ts from s) 54*6dbdd20aSAndroid Build Coastguard Worker and client_ts < (select ts + dur from s) 55*6dbdd20aSAndroid Build Coastguard Worker ), 56*6dbdd20aSAndroid Build Coastguard Worker nested_binder_txns_in_slice_interval as materialized ( 57*6dbdd20aSAndroid Build Coastguard Worker select 58*6dbdd20aSAndroid Build Coastguard Worker parent.binder_reply_id as source_node_id, 59*6dbdd20aSAndroid Build Coastguard Worker child.binder_txn_id as dest_node_id 60*6dbdd20aSAndroid Build Coastguard Worker from android_binder_txns parent 61*6dbdd20aSAndroid Build Coastguard Worker join descendant_slice(parent.binder_reply_id) desc 62*6dbdd20aSAndroid Build Coastguard Worker join android_binder_txns child on desc.id = child.binder_txn_id 63*6dbdd20aSAndroid Build Coastguard Worker where parent.server_ts > (select ts from s) 64*6dbdd20aSAndroid Build Coastguard Worker and parent.server_ts < (select ts + dur from s) 65*6dbdd20aSAndroid Build Coastguard Worker ), 66*6dbdd20aSAndroid Build Coastguard Worker all_binder_txns_considered as materialized ( 67*6dbdd20aSAndroid Build Coastguard Worker select * from child_binder_txns_for_slice 68*6dbdd20aSAndroid Build Coastguard Worker union 69*6dbdd20aSAndroid Build Coastguard Worker select * from binder_txns_in_slice_intervals 70*6dbdd20aSAndroid Build Coastguard Worker union 71*6dbdd20aSAndroid Build Coastguard Worker select * from nested_binder_txns_in_slice_interval 72*6dbdd20aSAndroid Build Coastguard Worker ) 73*6dbdd20aSAndroid Build Coastguard Worker select 74*6dbdd20aSAndroid Build Coastguard Worker dfs.node_id as id, 75*6dbdd20aSAndroid Build Coastguard Worker coalesce(client.client_ts, server.client_ts, slice.ts) as ts, 76*6dbdd20aSAndroid Build Coastguard Worker coalesce(client.client_dur, server.client_dur, slice.dur) as dur, 77*6dbdd20aSAndroid Build Coastguard Worker coalesce( 78*6dbdd20aSAndroid Build Coastguard Worker client.aidl_name, 79*6dbdd20aSAndroid Build Coastguard Worker server.aidl_name, 80*6dbdd20aSAndroid Build Coastguard Worker iif( 81*6dbdd20aSAndroid Build Coastguard Worker server.binder_reply_id is not null, 82*6dbdd20aSAndroid Build Coastguard Worker coalesce( 83*6dbdd20aSAndroid Build Coastguard Worker server.server_process, 84*6dbdd20aSAndroid Build Coastguard Worker server.server_thread, 85*6dbdd20aSAndroid Build Coastguard Worker 'Unknown server' 86*6dbdd20aSAndroid Build Coastguard Worker ), 87*6dbdd20aSAndroid Build Coastguard Worker slice.name 88*6dbdd20aSAndroid Build Coastguard Worker ) 89*6dbdd20aSAndroid Build Coastguard Worker ) name, 90*6dbdd20aSAndroid Build Coastguard Worker coalesce( 91*6dbdd20aSAndroid Build Coastguard Worker client.client_utid, 92*6dbdd20aSAndroid Build Coastguard Worker server.server_utid, 93*6dbdd20aSAndroid Build Coastguard Worker thread_track.utid 94*6dbdd20aSAndroid Build Coastguard Worker ) as utid, 95*6dbdd20aSAndroid Build Coastguard Worker case 96*6dbdd20aSAndroid Build Coastguard Worker when client.binder_txn_id is not null then 'client' 97*6dbdd20aSAndroid Build Coastguard Worker when server.binder_reply_id is not null then 'server' 98*6dbdd20aSAndroid Build Coastguard Worker else 'slice' 99*6dbdd20aSAndroid Build Coastguard Worker end as slice_type, 100*6dbdd20aSAndroid Build Coastguard Worker coalesce(client.is_sync, server.is_sync, true) as is_sync 101*6dbdd20aSAndroid Build Coastguard Worker from graph_reachable_dfs!( 102*6dbdd20aSAndroid Build Coastguard Worker all_binder_txns_considered, 103*6dbdd20aSAndroid Build Coastguard Worker (select id as node_id from s) 104*6dbdd20aSAndroid Build Coastguard Worker ) dfs 105*6dbdd20aSAndroid Build Coastguard Worker join slice on dfs.node_id = slice.id 106*6dbdd20aSAndroid Build Coastguard Worker join thread_track on slice.track_id = thread_track.id 107*6dbdd20aSAndroid Build Coastguard Worker left join android_binder_txns client on dfs.node_id = client.binder_txn_id 108*6dbdd20aSAndroid Build Coastguard Worker left join android_binder_txns server on dfs.node_id = server.binder_reply_id 109*6dbdd20aSAndroid Build Coastguard Worker order by ts; 110*6dbdd20aSAndroid Build Coastguard Worker `); 111*6dbdd20aSAndroid Build Coastguard Worker await ctx.engine.query(` 112*6dbdd20aSAndroid Build Coastguard Worker include perfetto module intervals.intersect; 113*6dbdd20aSAndroid Build Coastguard Worker 114*6dbdd20aSAndroid Build Coastguard Worker create or replace perfetto table __enhanced_binder_for_slice_${sliceId} as 115*6dbdd20aSAndroid Build Coastguard Worker with foo as ( 116*6dbdd20aSAndroid Build Coastguard Worker select 117*6dbdd20aSAndroid Build Coastguard Worker bfs.id as binder_id, 118*6dbdd20aSAndroid Build Coastguard Worker bfs.name as binder_name, 119*6dbdd20aSAndroid Build Coastguard Worker ii.ts, 120*6dbdd20aSAndroid Build Coastguard Worker ii.dur, 121*6dbdd20aSAndroid Build Coastguard Worker tstate.utid, 122*6dbdd20aSAndroid Build Coastguard Worker thread.upid, 123*6dbdd20aSAndroid Build Coastguard Worker tstate.cpu, 124*6dbdd20aSAndroid Build Coastguard Worker tstate.state, 125*6dbdd20aSAndroid Build Coastguard Worker tstate.io_wait, 126*6dbdd20aSAndroid Build Coastguard Worker ( 127*6dbdd20aSAndroid Build Coastguard Worker select name 128*6dbdd20aSAndroid Build Coastguard Worker from thread_slice tslice 129*6dbdd20aSAndroid Build Coastguard Worker where tslice.utid = tstate.utid and tslice.ts < ii.ts 130*6dbdd20aSAndroid Build Coastguard Worker order by ts desc 131*6dbdd20aSAndroid Build Coastguard Worker limit 1 132*6dbdd20aSAndroid Build Coastguard Worker ) as enclosing_slice_name 133*6dbdd20aSAndroid Build Coastguard Worker from _interval_intersect!( 134*6dbdd20aSAndroid Build Coastguard Worker ( 135*6dbdd20aSAndroid Build Coastguard Worker select id, ts, dur 136*6dbdd20aSAndroid Build Coastguard Worker from __binder_for_slice_${sliceId} 137*6dbdd20aSAndroid Build Coastguard Worker where slice_type IN ('slice', 'server') 138*6dbdd20aSAndroid Build Coastguard Worker and is_sync 139*6dbdd20aSAndroid Build Coastguard Worker and dur > 0 140*6dbdd20aSAndroid Build Coastguard Worker ), 141*6dbdd20aSAndroid Build Coastguard Worker ( 142*6dbdd20aSAndroid Build Coastguard Worker select id, ts, dur 143*6dbdd20aSAndroid Build Coastguard Worker from thread_state tstate 144*6dbdd20aSAndroid Build Coastguard Worker where 145*6dbdd20aSAndroid Build Coastguard Worker tstate.utid in ( 146*6dbdd20aSAndroid Build Coastguard Worker select distinct utid 147*6dbdd20aSAndroid Build Coastguard Worker from __binder_for_slice_${sliceId} 148*6dbdd20aSAndroid Build Coastguard Worker where 149*6dbdd20aSAndroid Build Coastguard Worker slice_type IN ('slice', 'server') 150*6dbdd20aSAndroid Build Coastguard Worker and is_sync 151*6dbdd20aSAndroid Build Coastguard Worker and dur > 0 152*6dbdd20aSAndroid Build Coastguard Worker ) 153*6dbdd20aSAndroid Build Coastguard Worker and dur > 0 154*6dbdd20aSAndroid Build Coastguard Worker ), 155*6dbdd20aSAndroid Build Coastguard Worker () 156*6dbdd20aSAndroid Build Coastguard Worker ) ii 157*6dbdd20aSAndroid Build Coastguard Worker join __binder_for_slice_${sliceId} bfs on ii.id_0 = bfs.id 158*6dbdd20aSAndroid Build Coastguard Worker join thread_state tstate on ii.id_1 = tstate.id 159*6dbdd20aSAndroid Build Coastguard Worker join thread using (utid) 160*6dbdd20aSAndroid Build Coastguard Worker where bfs.utid = tstate.utid 161*6dbdd20aSAndroid Build Coastguard Worker ) 162*6dbdd20aSAndroid Build Coastguard Worker select 163*6dbdd20aSAndroid Build Coastguard Worker *, 164*6dbdd20aSAndroid Build Coastguard Worker case 165*6dbdd20aSAndroid Build Coastguard Worker when state = 'S' and enclosing_slice_name = 'binder transaction' then 'Waiting for server' 166*6dbdd20aSAndroid Build Coastguard Worker when state = 'S' and enclosing_slice_name GLOB 'Lock*' then 'Waiting for lock' 167*6dbdd20aSAndroid Build Coastguard Worker when state = 'S' and enclosing_slice_name GLOB 'Monitor*' then 'Waiting for contention' 168*6dbdd20aSAndroid Build Coastguard Worker when state = 'S' then 'Sleeping' 169*6dbdd20aSAndroid Build Coastguard Worker when state = 'R' then 'Waiting for CPU' 170*6dbdd20aSAndroid Build Coastguard Worker when state = 'Running' then 'Running on CPU ' || foo.cpu 171*6dbdd20aSAndroid Build Coastguard Worker when state GLOB 'R*' then 'Runnable' 172*6dbdd20aSAndroid Build Coastguard Worker when state GLOB 'D*' and io_wait then 'IO' 173*6dbdd20aSAndroid Build Coastguard Worker when state GLOB 'D*' and not io_wait then 'Unint-sleep' 174*6dbdd20aSAndroid Build Coastguard Worker end as name 175*6dbdd20aSAndroid Build Coastguard Worker from foo 176*6dbdd20aSAndroid Build Coastguard Worker order by binder_id; 177*6dbdd20aSAndroid Build Coastguard Worker `); 178*6dbdd20aSAndroid Build Coastguard Worker 179*6dbdd20aSAndroid Build Coastguard Worker const res = await ctx.engine.query(` 180*6dbdd20aSAndroid Build Coastguard Worker select id, name 181*6dbdd20aSAndroid Build Coastguard Worker from __binder_for_slice_${sliceId} bfs 182*6dbdd20aSAndroid Build Coastguard Worker where slice_type IN ('slice', 'server') 183*6dbdd20aSAndroid Build Coastguard Worker and dur > 0 184*6dbdd20aSAndroid Build Coastguard Worker order by ts 185*6dbdd20aSAndroid Build Coastguard Worker `); 186*6dbdd20aSAndroid Build Coastguard Worker const it = res.iter({ 187*6dbdd20aSAndroid Build Coastguard Worker id: NUM, 188*6dbdd20aSAndroid Build Coastguard Worker name: STR, 189*6dbdd20aSAndroid Build Coastguard Worker }); 190*6dbdd20aSAndroid Build Coastguard Worker for (; it.valid(); it.next()) { 191*6dbdd20aSAndroid Build Coastguard Worker await addDebugSliceTrack({ 192*6dbdd20aSAndroid Build Coastguard Worker trace: ctx, 193*6dbdd20aSAndroid Build Coastguard Worker data: { 194*6dbdd20aSAndroid Build Coastguard Worker sqlSource: ` 195*6dbdd20aSAndroid Build Coastguard Worker SELECT ts, dur, name 196*6dbdd20aSAndroid Build Coastguard Worker FROM __enhanced_binder_for_slice_${sliceId} 197*6dbdd20aSAndroid Build Coastguard Worker WHERE binder_id = ${it.id} 198*6dbdd20aSAndroid Build Coastguard Worker `, 199*6dbdd20aSAndroid Build Coastguard Worker }, 200*6dbdd20aSAndroid Build Coastguard Worker title: it.name, 201*6dbdd20aSAndroid Build Coastguard Worker }); 202*6dbdd20aSAndroid Build Coastguard Worker } 203*6dbdd20aSAndroid Build Coastguard Worker }, 204*6dbdd20aSAndroid Build Coastguard Worker }); 205*6dbdd20aSAndroid Build Coastguard Worker } 206*6dbdd20aSAndroid Build Coastguard Worker} 207