Skip to content

Commit

Permalink
Add a plugin for Desktop Windowing statsd atoms.
Browse files Browse the repository at this point in the history
Parse desktop window events into a stdlib table, and
create a plugin that registers a command that will
create a timeline track and pin it.

Bug: 370730027
Test: tools/diff_test_trace_processor.py out/linux/trace_processor_shell --name-filter '.*desktop_mode.*'

Change-Id: Ic8e20529b802c3a25fb0c6858800048f75beb2fc
  • Loading branch information
Ben Murdoch committed Oct 21, 2024
1 parent 67dacc7 commit d5ba33f
Show file tree
Hide file tree
Showing 14 changed files with 262 additions and 0 deletions.
1 change: 1 addition & 0 deletions Android.bp
Original file line number Diff line number Diff line change
Expand Up @@ -13532,6 +13532,7 @@ genrule {
"src/trace_processor/perfetto_sql/stdlib/android/broadcasts.sql",
"src/trace_processor/perfetto_sql/stdlib/android/cpu/cluster_type.sql",
"src/trace_processor/perfetto_sql/stdlib/android/critical_blocking_calls.sql",
"src/trace_processor/perfetto_sql/stdlib/android/desktop_mode.sql",
"src/trace_processor/perfetto_sql/stdlib/android/device.sql",
"src/trace_processor/perfetto_sql/stdlib/android/dvfs.sql",
"src/trace_processor/perfetto_sql/stdlib/android/frames/jank_type.sql",
Expand Down
1 change: 1 addition & 0 deletions BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -2814,6 +2814,7 @@ perfetto_filegroup(
"src/trace_processor/perfetto_sql/stdlib/android/binder_breakdown.sql",
"src/trace_processor/perfetto_sql/stdlib/android/broadcasts.sql",
"src/trace_processor/perfetto_sql/stdlib/android/critical_blocking_calls.sql",
"src/trace_processor/perfetto_sql/stdlib/android/desktop_mode.sql",
"src/trace_processor/perfetto_sql/stdlib/android/device.sql",
"src/trace_processor/perfetto_sql/stdlib/android/dvfs.sql",
"src/trace_processor/perfetto_sql/stdlib/android/freezer.sql",
Expand Down
1 change: 1 addition & 0 deletions src/trace_processor/perfetto_sql/stdlib/android/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ perfetto_sql_source_set("android") {
"binder_breakdown.sql",
"broadcasts.sql",
"critical_blocking_calls.sql",
"desktop_mode.sql",
"device.sql",
"dvfs.sql",
"freezer.sql",
Expand Down
72 changes: 72 additions & 0 deletions src/trace_processor/perfetto_sql/stdlib/android/desktop_mode.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
--
-- Copyright 2024 The Android Open Source Project
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- https://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
--

include perfetto module android.statsd;

-- Desktop Windows with durations they were open.
CREATE PERFETTO TABLE android_desktop_mode_windows (
-- Window add timestamp; NULL if no add event in the trace.
raw_add_ts INT,
-- Window remove timestamp; NULL if no remove event in the trace.
raw_remove_ts INT,
-- timestamp that the window was added; or trace_start() if no add event in the trace.
ts INT,
-- duration the window was open; or until trace_end() if no remove event in the trace.
dur INT,
-- Desktop Window instance ID - unique per window.
instance_id INT,
-- UID of the app running in the window.
uid INT
) AS
WITH
atoms AS (
SELECT
ts,
extract_arg(arg_set_id, 'field_1') AS type,
extract_arg(arg_set_id, 'field_2') AS instance_id,
extract_arg(arg_set_id, 'field_3') AS uid
FROM android_statsd_atoms
WHERE name = 'atom_819'),
dw_statsd_events_add AS (
SELECT *
FROM atoms
WHERE type = 1),
dw_statsd_events_remove AS (
SELECT * FROM atoms
WHERE type = 2),
dw_statsd_events_update_by_instance AS (
SELECT instance_id, min(uid) AS uid FROM atoms
WHERE type = 3 GROUP BY instance_id),
dw_windows AS (
SELECT
a.ts AS raw_add_ts,
r.ts AS raw_remove_ts,
ifnull(a.ts, trace_start()) AS ts, -- Assume trace_start() if no add event found.
ifnull(r.ts, trace_end()) - ifnull(a.ts, trace_start()) AS dur, -- Assume trace_end() if no remove event found.
ifnull(a.instance_id, r.instance_id) AS instance_id,
ifnull(a.uid, r.uid) AS uid
FROM dw_statsd_events_add a
FULL JOIN dw_statsd_events_remove r ON a.instance_id = r.instance_id),
-- Assume window was open for the entire trace if we only see change events for the instance ID.
dw_windows_with_update_events AS (
SELECT * FROM dw_windows
UNION
SELECT NULL, NULL, trace_start(), trace_end() - trace_start(), instance_id, uid
FROM dw_statsd_events_update_by_instance
WHERE
instance_id NOT IN (SELECT instance_id FROM dw_windows))
SELECT * FROM dw_windows_with_update_events;

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
de2c99d57ebec6ab843bc56047eb12dbedc3d08a8a1d989d9b3302ed30057286
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0967fdf494167fe47e5ddf4c540fcc7cc0b22e36ddafa4b4c1172fe3c171b3d6
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0bb09b4c68a125a09b6856879af92cd47dd980c2dcaa1513c370b9b6a7b575d1
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
bab0c50523ac903872cd11f3fdd4a9ecda98e937573d17011eb877636e82c3c3
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
7f63f17b65a0fca4bc5ccd75c9a7eb854779585b20cb91fcf371e7892642327e
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ee1172b8ad0eaf856e2776575b861f44663bb98f1d40d7d4e66ee0f532220568
2 changes: 2 additions & 0 deletions test/trace_processor/diff_tests/include_index.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@
from diff_tests.parser.ufs.tests import Ufs
from diff_tests.parser.zip.tests import Zip
from diff_tests.stdlib.android.cpu_cluster_tests import CpuClusters
from diff_tests.stdlib.android.desktop_mode_tests import DesktopMode
from diff_tests.stdlib.android.frames_tests import Frames
from diff_tests.stdlib.android.gpu import AndroidGpu
from diff_tests.stdlib.android.heap_graph_tests import HeapGraph
Expand Down Expand Up @@ -295,6 +296,7 @@ def fetch_all_diff_tests(index_path: str) -> List['testing.TestCase']:
*AndroidGpu(index_path, 'stdlib/android', 'AndroidGpu').fetch(),
*AndroidStdlib(index_path, 'stdlib/android', 'AndroidStdlib').fetch(),
*CpuClusters(index_path, 'stdlib/android', 'CpuClusters').fetch(),
*DesktopMode(index_path, 'stdlib/android', 'DesktopMode').fetch(),
*LinuxCpu(index_path, 'stdlib/linux/cpu', 'LinuxCpu').fetch(),
*LinuxTests(index_path, 'stdlib/linux', 'LinuxTests').fetch(),
*DominatorTree(index_path, 'stdlib/graphs', 'DominatorTree').fetch(),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#!/usr/bin/env python3
# Copyright (C) 2024 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License a
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from python.generators.diff_tests.testing import DataPath
from python.generators.diff_tests.testing import Csv
from python.generators.diff_tests.testing import DiffTestBlueprint
from python.generators.diff_tests.testing import TestSuite

class DesktopMode(TestSuite):

def test_android_desktop_mode_windows_statsd_events(self):
return DiffTestBlueprint(
trace=DataPath('android_desktop_mode/single_window_add_update_remove.pb'),
query="""
INCLUDE PERFETTO MODULE android.desktop_mode;
SELECT * FROM android_desktop_mode_windows;
""",
out=Csv("""
"raw_add_ts","raw_remove_ts","ts","dur","instance_id","uid"
1112172132337,1115098491388,1112172132337,2926359051,22,10211
"""))

def test_android_desktop_mode_windows_statsd_events_multiple_windows(self):
return DiffTestBlueprint(
trace=DataPath('android_desktop_mode/multiple_windows_add_update_remove.pb'),
query="""
INCLUDE PERFETTO MODULE android.desktop_mode;
SELECT * FROM android_desktop_mode_windows;
""",
out=Csv("""
"raw_add_ts","raw_remove_ts","ts","dur","instance_id","uid"
1340951146935,1347096280320,1340951146935,6145133385,24,10211
1342507511641,1345461733688,1342507511641,2954222047,26,10183
"""))

def test_android_desktop_mode_windows_statsd_events_add_no_remove(self):
return DiffTestBlueprint(
trace=DataPath('android_desktop_mode/single_window_add_update_no_remove.pb'),
query="""
INCLUDE PERFETTO MODULE android.desktop_mode;
SELECT * FROM android_desktop_mode_windows;
""",
out=Csv("""
"raw_add_ts","raw_remove_ts","ts","dur","instance_id","uid"
1552558346094,"[NULL]",1552558346094,1620521485,27,10211
"""))

def test_android_desktop_mode_windows_statsd_events_no_add_update_remove(self):
return DiffTestBlueprint(
trace=DataPath('android_desktop_mode/single_window_no_add_update_remove.pb'),
query="""
INCLUDE PERFETTO MODULE android.desktop_mode;
SELECT * FROM android_desktop_mode_windows;
""",
out=Csv("""
"raw_add_ts","raw_remove_ts","ts","dur","instance_id","uid"
"[NULL]",1696520389866,1695387563286,1132826580,29,10211
"""))

def test_android_desktop_mode_windows_statsd_events_only_update(self):
return DiffTestBlueprint(
trace=DataPath('android_desktop_mode/single_window_only_update.pb'),
query="""
INCLUDE PERFETTO MODULE android.desktop_mode;
SELECT * FROM android_desktop_mode_windows;
""",
out=Csv("""
"raw_add_ts","raw_remove_ts","ts","dur","instance_id","uid"
"[NULL]","[NULL]",1852548597746,3663403770,31,10211
"""))

def test_android_desktop_mode_windows_statsd_events_multiple_windows_update_only(self):
return DiffTestBlueprint(
trace=DataPath('android_desktop_mode/multiple_window_only_update.pb'),
query="""
INCLUDE PERFETTO MODULE android.desktop_mode;
SELECT * FROM android_desktop_mode_windows;
""",
out=Csv("""
"raw_add_ts","raw_remove_ts","ts","dur","instance_id","uid"
"[NULL]","[NULL]",2137135290268,4737314089,33,10211
"[NULL]","[NULL]",2137135290268,4737314089,35,10183
"""))

2 changes: 2 additions & 0 deletions ui/src/plugins/dev.perfetto.AndroidDesktopMode/OWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[email protected]

81 changes: 81 additions & 0 deletions ui/src/plugins/dev.perfetto.AndroidDesktopMode/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// Copyright (C) 2024 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import {
SimpleSliceTrack,
SimpleSliceTrackConfig,
} from '../../frontend/simple_slice_track';
import {PerfettoPlugin, PluginDescriptor} from '../../public/plugin';
import {Trace} from '../../public/trace';
import {TrackNode} from '../../public/workspace';

const INCLUDE_DESKTOP_MODULE_QUERY = `INCLUDE PERFETTO MODULE android.desktop_mode`;

const QUERY = `
SELECT
ROW_NUMBER() OVER (ORDER BY ts) AS id,
ts,
dur,
ifnull(p.package_name, 'uid=' || dw.uid) AS name
FROM android_desktop_mode_windows dw
LEFT JOIN package_list p ON CAST (dw.uid AS INT) % 100000 = p.uid AND p.uid != 1000
`;

const COLUMNS = ['id', 'ts', 'dur', 'name'];
const TRACK_NAME = 'Desktop Mode Windows';
const TRACK_URI = '/desktop_windows';

class AndroidDesktopMode implements PerfettoPlugin {
async onTraceReady(_ctx: Trace): Promise<void> {
await _ctx.engine.query(INCLUDE_DESKTOP_MODULE_QUERY);
this.registerTrack(
_ctx,
QUERY,
);
_ctx.commands.registerCommand({
id: 'dev.perfetto.DesktopMode#AddTrackDesktopWindowss',
name: 'Add Track: ' + TRACK_NAME,
callback: () => this.addSimpleTrack(_ctx),
});
}

registerTrack(_ctx: Trace, sql: string) {
const config: SimpleSliceTrackConfig = {
data: {
sqlSource: sql,
columns: COLUMNS,
},
columns: {ts: 'ts', dur: 'dur', name: 'name'},
argColumns: [],
};
const track = new SimpleSliceTrack(_ctx, {trackUri: TRACK_URI}, config);
_ctx.tracks.registerTrack({
uri: TRACK_URI,
title: TRACK_NAME,
track,
});
}

addSimpleTrack(_ctx: Trace) {
const trackNode = new TrackNode({uri: TRACK_URI, title: TRACK_NAME});
_ctx.workspace.addChildInOrder(trackNode);
trackNode.pin();
}
}

export const plugin: PluginDescriptor = {
pluginId: 'dev.perfetto.AndroidDesktopMode',
plugin: AndroidDesktopMode,
};

0 comments on commit d5ba33f

Please sign in to comment.