1// Copyright (C) 2023 The Android Open Source Project 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15import {Trace} from '../../public/trace'; 16import {PerfettoPlugin} from '../../public/plugin'; 17import {addDebugSliceTrack} from '../../components/tracks/debug_tracks'; 18 19export default class implements PerfettoPlugin { 20 static readonly id = 'dev.perfetto.AndroidNetwork'; 21 // Adds a debug track using the provided query and given columns. The columns 22 // must be start with ts, dur, and a name column. The name column and all 23 // following columns are shown as arguments in slice details. 24 async addSimpleTrack( 25 ctx: Trace, 26 trackName: string, 27 tableOrQuery: string, 28 columns: string[], 29 ): Promise<void> { 30 await addDebugSliceTrack({ 31 trace: ctx, 32 data: { 33 sqlSource: `SELECT ${columns.join(',')} FROM ${tableOrQuery}`, 34 columns: columns, 35 }, 36 title: trackName, 37 columns: {ts: columns[0], dur: columns[1], name: columns[2]}, 38 argColumns: columns.slice(2), 39 }); 40 } 41 42 async onTraceLoad(ctx: Trace): Promise<void> { 43 ctx.commands.registerCommand({ 44 id: 'dev.perfetto.AndroidNetwork#batteryEvents', 45 name: 'Add track: battery events', 46 callback: async (track) => { 47 if (track === undefined) { 48 track = prompt('Battery Track', ''); 49 if (track === null) return; 50 } 51 52 await ctx.engine.query(`SELECT IMPORT('android.battery_stats');`); 53 await this.addSimpleTrack( 54 ctx, 55 track, 56 `(SELECT * 57 FROM android_battery_stats_event_slices 58 WHERE track_name = "${track}")`, 59 ['ts', 'dur', 'str_value', 'int_value'], 60 ); 61 }, 62 }); 63 64 ctx.commands.registerCommand({ 65 id: 'dev.perfetto.AndroidNetwork#activityTrack', 66 name: 'Add track: network activity', 67 callback: async (groupby, filter, trackName) => { 68 if (groupby === undefined) { 69 groupby = prompt('Group by', 'package_name'); 70 if (groupby === null) return; 71 } 72 73 if (filter === undefined) { 74 filter = prompt('Filter', 'TRUE'); 75 if (filter === null) return; 76 } 77 78 const suffix = new Date().getTime(); 79 await ctx.engine.query(` 80 SELECT RUN_METRIC( 81 'android/network_activity_template.sql', 82 'view_name', 'android_network_activity_${suffix}', 83 'group_by', '${groupby}', 84 'filter', '${filter}', 85 'idle_ns', '10e9', 86 'quant_ns', '3e9' 87 ); 88 `); 89 90 // The first group column is used for the slice name. 91 const groupCols = groupby.replaceAll(' ', '').split(','); 92 await this.addSimpleTrack( 93 ctx, 94 trackName ?? 'Network Activity', 95 `android_network_activity_${suffix}`, 96 ['ts', 'dur', ...groupCols, 'packet_length', 'packet_count'], 97 ); 98 }, 99 }); 100 } 101} 102