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 {Plugin, PluginContextTrace, PluginDescriptor} from '../../public'; 16import {addDebugSliceTrack} from '../../public'; 17 18class AndroidNetwork implements Plugin { 19 // Adds a debug track using the provided query and given columns. The columns 20 // must be start with ts, dur, and a name column. The name column and all 21 // following columns are shown as arguments in slice details. 22 async addSimpleTrack( 23 ctx: PluginContextTrace, 24 trackName: string, 25 tableOrQuery: string, 26 columns: string[], 27 ): Promise<void> { 28 await addDebugSliceTrack( 29 ctx, 30 { 31 sqlSource: `SELECT ${columns.join(',')} FROM ${tableOrQuery}`, 32 columns: columns, 33 }, 34 trackName, 35 {ts: columns[0], dur: columns[1], name: columns[2]}, 36 columns.slice(2), 37 ); 38 } 39 40 async onTraceLoad(ctx: PluginContextTrace): Promise<void> { 41 ctx.registerCommand({ 42 id: 'dev.perfetto.AndroidNetwork#batteryEvents', 43 name: 'Add track: battery events', 44 callback: async (track) => { 45 if (track === undefined) { 46 track = prompt('Battery Track', ''); 47 if (track === null) return; 48 } 49 50 await ctx.engine.query(`SELECT IMPORT('android.battery_stats');`); 51 await this.addSimpleTrack( 52 ctx, 53 track, 54 `(SELECT * 55 FROM android_battery_stats_event_slices 56 WHERE track_name = "${track}")`, 57 ['ts', 'dur', 'str_value', 'int_value'], 58 ); 59 }, 60 }); 61 62 ctx.registerCommand({ 63 id: 'dev.perfetto.AndroidNetwork#activityTrack', 64 name: 'Add track: network activity', 65 callback: async (groupby, filter, trackName) => { 66 if (groupby === undefined) { 67 groupby = prompt('Group by', 'package_name'); 68 if (groupby === null) return; 69 } 70 71 if (filter === undefined) { 72 filter = prompt('Filter', 'TRUE'); 73 if (filter === null) return; 74 } 75 76 const suffix = new Date().getTime(); 77 await ctx.engine.query(` 78 SELECT RUN_METRIC( 79 'android/network_activity_template.sql', 80 'view_name', 'android_network_activity_${suffix}', 81 'group_by', '${groupby}', 82 'filter', '${filter}', 83 'idle_ns', '10e9', 84 'quant_ns', '3e9' 85 ); 86 `); 87 88 // The first group column is used for the slice name. 89 const groupCols = groupby.replaceAll(' ', '').split(','); 90 await this.addSimpleTrack( 91 ctx, 92 trackName || 'Network Activity', 93 `android_network_activity_${suffix}`, 94 ['ts', 'dur', ...groupCols, 'packet_length', 'packet_count'], 95 ); 96 }, 97 }); 98 } 99} 100 101export const plugin: PluginDescriptor = { 102 pluginId: 'dev.perfetto.AndroidNetwork', 103 plugin: AndroidNetwork, 104}; 105