• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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