1 /*
<lambda>null2 * Copyright (C) 2023 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 @file:JvmName("MonitorUtils")
18 @file:OptIn(
19 androidx.benchmark.perfetto.ExperimentalPerfettoCaptureApi::class,
20 androidx.benchmark.perfetto.ExperimentalPerfettoTraceProcessorApi::class
21 )
22
23 package android.tools.traces.monitors
24
25 import android.tools.ScenarioBuilder
26 import android.tools.Tag
27 import android.tools.io.Reader
28 import android.tools.traces.SERVICE_TRACE_CONFIG
29 import android.tools.traces.io.ResultReaderWithLru
30 import android.tools.traces.io.ResultWriter
31 import android.tools.traces.monitors.wm.WindowManagerTraceMonitor
32 import android.tools.traces.parsers.perfetto.LayersTraceParser
33 import android.tools.traces.parsers.perfetto.TraceProcessorSession
34 import android.tools.traces.parsers.perfetto.TransactionsTraceParser
35 import android.tools.traces.parsers.wm.WindowManagerTraceParser
36 import android.tools.traces.surfaceflinger.LayersTrace
37 import android.tools.traces.surfaceflinger.TransactionsTrace
38 import android.tools.traces.wm.WindowManagerTrace
39 import java.io.File
40 import perfetto.protos.PerfettoConfig.SurfaceFlingerLayersConfig
41
42 /**
43 * Acquire the [WindowManagerTrace] with the device state changes that happen when executing the
44 * commands defined in the [predicate].
45 *
46 * @param predicate Commands to execute
47 * @throws UnsupportedOperationException If tracing is already activated
48 */
49 fun withWMTracing(predicate: () -> Unit): WindowManagerTrace {
50 return WindowManagerTraceParser()
51 .parse(WindowManagerTraceMonitor().withTracing(Tag.ALL, predicate))
52 }
53
54 /**
55 * Acquire the [LayersTrace] with the device state changes that happen when executing the commands
56 * defined in the [predicate].
57 *
58 * @param flags Flags to indicate tracing level
59 * @param predicate Commands to execute
60 * @throws UnsupportedOperationException If tracing is already activated
61 */
62 @JvmOverloads
withSFTracingnull63 fun withSFTracing(
64 flags: List<SurfaceFlingerLayersConfig.TraceFlag>? = null,
65 predicate: () -> Unit
66 ): LayersTrace {
67 val trace =
68 PerfettoTraceMonitor.newBuilder()
69 .enableLayersTrace(flags)
70 .build()
71 .withTracing(Tag.ALL, predicate)
72 return TraceProcessorSession.loadPerfettoTrace(trace) { session ->
73 LayersTraceParser().parse(session)
74 }
75 }
76
77 /**
78 * Acquire the [TransactionsTrace] with the device state changes that happen when executing the
79 * commands defined in the [predicate].
80 *
81 * @param predicate Commands to execute
82 * @throws UnsupportedOperationException If tracing is already activated
83 */
84 @JvmOverloads
withTransactionsTracingnull85 fun withTransactionsTracing(predicate: () -> Unit): TransactionsTrace {
86 val trace =
87 PerfettoTraceMonitor.newBuilder()
88 .enableTransactionsTrace()
89 .build()
90 .withTracing(Tag.ALL, predicate)
91 return TraceProcessorSession.loadPerfettoTrace(trace) { session ->
92 TransactionsTraceParser().parse(session)
93 }
94 }
95
96 /**
97 * Acquire the [WindowManagerTrace] and [LayersTrace] with the device state changes that happen when
98 * executing the commands defined in the [predicate].
99 *
100 * @param predicate Commands to execute
101 * @throws UnsupportedOperationException If tracing is already activated
102 */
withTracingnull103 fun withTracing(
104 traceMonitors: List<TraceMonitor> =
105 listOf(
106 WindowManagerTraceMonitor(),
107 PerfettoTraceMonitor.newBuilder().enableLayersTrace().enableTransactionsTrace().build(),
108 ),
109 predicate: () -> Unit
110 ): Reader {
111 val tmpFile = File.createTempFile("recordTraces", "")
112 val writer =
113 ResultWriter()
114 .forScenario(ScenarioBuilder().forClass(tmpFile.name).build())
115 .withOutputDir(tmpFile.parentFile)
116
117 try {
118 traceMonitors.forEach { it.start() }
119 predicate()
120 } finally {
121 traceMonitors.forEach { it.stop(writer) }
122 }
123 return ResultReaderWithLru(writer.write(), SERVICE_TRACE_CONFIG)
124 }
125
126 /**
127 * Acquire the [WindowManagerTrace] and [LayersTrace] with the device state changes that happen when
128 * executing the commands defined in the [predicate].
129 *
130 * @param predicate Commands to execute
131 * @return a pair containing the WM and SF traces
132 * @throws UnsupportedOperationException If tracing is already activated
133 */
recordTracesnull134 fun recordTraces(predicate: () -> Unit): Pair<ByteArray, ByteArray> {
135 var wmTraceData = ByteArray(0)
136 val layersTraceData =
137 PerfettoTraceMonitor.newBuilder().enableLayersTrace().build().withTracing {
138 wmTraceData = WindowManagerTraceMonitor().withTracing(Tag.ALL, predicate)
139 }
140
141 return Pair(wmTraceData, layersTraceData)
142 }
143