• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 package android.tools.monitors
18 
19 import android.tools.device.apphelpers.BrowserAppHelper
20 import android.tools.io.TraceType
21 import android.tools.testutils.CleanFlickerEnvironmentRule
22 import android.tools.traces.SERVICE_TRACE_CONFIG
23 import android.tools.traces.io.IResultData
24 import android.tools.traces.io.ResultReader
25 import android.tools.traces.monitors.PerfettoTraceMonitor
26 import android.tools.traces.monitors.withSFTracing
27 import android.tools.traces.monitors.withTransactionsTracing
28 import android.tools.traces.parsers.WindowManagerStateHelper
29 import android.tools.traces.parsers.perfetto.LayersTraceParser
30 import android.tools.traces.parsers.perfetto.TraceProcessorSession
31 import android.tools.traces.parsers.perfetto.TransitionsTraceParser
32 import androidx.test.platform.app.InstrumentationRegistry
33 import com.android.server.wm.flicker.helpers.ImeAppHelper
34 import com.google.common.truth.Truth
35 import java.io.File
36 import org.junit.Assume.assumeTrue
37 import org.junit.ClassRule
38 import org.junit.FixMethodOrder
39 import org.junit.Test
40 import org.junit.runners.MethodSorters
41 
42 /**
43  * Contains [PerfettoTraceMonitor] tests. To run this test: `atest
44  * FlickerLibTest:PerfettoTraceMonitorTest`
45  */
46 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
47 class PerfettoTraceMonitorTest : TraceMonitorTest<PerfettoTraceMonitor>() {
48     override val traceType = TraceType.PERFETTO
49 
50     override fun getMonitor() =
51         PerfettoTraceMonitor.newBuilder().enableLayersTrace().enableTransactionsTrace().build()
52 
53     override fun assertTrace(traceData: ByteArray) {
54         Truth.assertThat(traceData.size).isGreaterThan(0)
55     }
56 
57     @Test
58     fun withSFTracingTest() {
59         val debugFile = getDebugFile("uiTrace-PerfettoTraceMonitorTest-withSFTracingTest")
60         val trace =
61             withSFTracing(debugFile = debugFile) {
62                 device.pressHome()
63                 device.pressRecentApps()
64             }
65 
66         Truth.assertWithMessage("Could not obtain layers trace").that(trace.entries).isNotEmpty()
67     }
68 
69     @Test
70     fun withTransactionsTracingTest() {
71         val debugFile = getDebugFile("uiTrace-PerfettoTraceMonitorTest-withTransactionsTracingTest")
72         val trace =
73             withTransactionsTracing(debugFile) {
74                 device.pressHome()
75                 device.pressRecentApps()
76             }
77 
78         Truth.assertWithMessage("Could not obtain transactions trace")
79             .that(trace.entries)
80             .isNotEmpty()
81     }
82 
83     @Test
84     fun layersDump() {
85         val reader =
86             PerfettoTraceMonitor.newBuilder().enableLayersDump().build().withTracing(
87                 resultReaderProvider = { buildResultReader(it) }
88             ) {}
89         val debugFile = getDebugFile("uiTrace-PerfettoTraceMonitorTest-layersDump")
90         debugFile.writeBytes(reader.artifact.readBytes())
91         val traceData = reader.readBytes(TraceType.PERFETTO) ?: ByteArray(0)
92         assertTrace(traceData)
93 
94         val trace =
95             TraceProcessorSession.loadPerfettoTrace(traceData) { session ->
96                 LayersTraceParser().parse(session)
97             }
98         Truth.assertWithMessage("Could not obtain layers dump")
99             .that(trace.entries.size)
100             .isEqualTo(1)
101     }
102 
103     @Test
104     fun withTransitionTracingTest() {
105         assumeTrue(
106             "PerfettoTransitionTracing flag should be enabled",
107             android.tracing.Flags.perfettoTransitionTracing(),
108         )
109 
110         val traceMonitor = PerfettoTraceMonitor.newBuilder().enableTransitionsTrace().build()
111         val reader =
112             traceMonitor.withTracing(resultReaderProvider = { buildResultReader(it) }) {
113                 BrowserAppHelper().launchViaIntent()
114                 device.pressHome()
115                 device.pressRecentApps()
116             }
117         val debugFile = getDebugFile("uiTrace-PerfettoTraceMonitorTest-withTransitionTracingTest")
118         debugFile.writeBytes(reader.artifact.readBytes())
119         val traceData = reader.readBytes(TraceType.PERFETTO) ?: ByteArray(0)
120         assertTrace(traceData)
121 
122         val trace =
123             TraceProcessorSession.loadPerfettoTrace(traceData) { session ->
124                 TransitionsTraceParser().parse(session)
125             }
126         Truth.assertWithMessage("Could not obtain transition trace")
127             .that(trace.entries)
128             .isNotEmpty()
129     }
130 
131     @Test
132     fun imeTracingTest() {
133         assumeTrue("PerfettoIme flag should be enabled", android.tracing.Flags.perfettoIme())
134 
135         val traceMonitor = PerfettoTraceMonitor.newBuilder().enableImeTrace().build()
136         val reader =
137             traceMonitor.withTracing(resultReaderProvider = { buildResultReader(it) }) {
138                 val wmHelper = WindowManagerStateHelper()
139                 val imeApp = ImeAppHelper(instrumentation)
140                 imeApp.launchViaIntent(wmHelper)
141                 imeApp.openIME(wmHelper)
142             }
143         val debugFile = getDebugFile("uiTrace-PerfettoTraceMonitorTest-imeTracingTest")
144         debugFile.writeBytes(reader.artifact.readBytes())
145         val traceData = reader.readBytes(TraceType.PERFETTO) ?: ByteArray(0)
146         assertTrace(traceData)
147 
148         val queryRowsCount = { session: TraceProcessorSession, tableName: String ->
149             val sql =
150                 "INCLUDE PERFETTO MODULE android.winscope.inputmethod;" +
151                     "SELECT COUNT(*) FROM $tableName;"
152             session.query(sql) { rows ->
153                 require(rows.size == 1)
154                 rows[0]["COUNT(*)"] as Long
155             }
156         }
157 
158         val (countRowsClients, countRowsManagerService, countRowsService) =
159             TraceProcessorSession.loadPerfettoTrace(traceData) { session ->
160                 Triple(
161                     queryRowsCount(session, "android_inputmethod_clients"),
162                     queryRowsCount(session, "android_inputmethod_manager_service"),
163                     queryRowsCount(session, "android_inputmethod_service"),
164                 )
165             }
166 
167         Truth.assertWithMessage("TP doesn't contain IME client rows")
168             .that(countRowsClients)
169             .isGreaterThan(0L)
170         Truth.assertWithMessage("TP doesn't contain IME manager service rows")
171             .that(countRowsManagerService)
172             .isGreaterThan(0L)
173         Truth.assertWithMessage("TP doesn't contain IME service rows")
174             .that(countRowsService)
175             .isGreaterThan(0L)
176     }
177 
178     @Test
179     fun viewCaptureTracingTest() {
180         assumeTrue(
181             "PerfettoViewCaptureTracing flag should be enabled",
182             android.tracing.Flags.perfettoViewCaptureTracing(),
183         )
184 
185         val traceMonitor = PerfettoTraceMonitor.newBuilder().enableViewCaptureTrace().build()
186         val reader =
187             traceMonitor.withTracing(resultReaderProvider = { buildResultReader(it) }) {
188                 BrowserAppHelper().launchViaIntent()
189                 device.pressHome()
190                 device.pressRecentApps()
191             }
192         val debugFile = getDebugFile("uiTrace-PerfettoTraceMonitorTest-viewCaptureTracingTest")
193         debugFile.writeBytes(reader.artifact.readBytes())
194         val traceData = reader.readBytes(TraceType.PERFETTO) ?: ByteArray(0)
195         assertTrace(traceData)
196 
197         val countRows =
198             TraceProcessorSession.loadPerfettoTrace(traceData) { session ->
199                 val sql =
200                     "INCLUDE PERFETTO MODULE android.winscope.viewcapture;" +
201                         "SELECT COUNT(*) FROM android_viewcapture;"
202                 session.query(sql) { rows ->
203                     require(rows.size == 1)
204                     rows[0]["COUNT(*)"] as Long
205                 }
206             }
207 
208         Truth.assertWithMessage("TP doesn't contain ViewCapture rows")
209             .that(countRows)
210             .isGreaterThan(0L)
211     }
212 
213     @Test
214     fun windowManagerTracingTest() {
215         assumeTrue(
216             "PerfettoWmTracing flag should be enabled",
217             android.tracing.Flags.perfettoWmTracing(),
218         )
219 
220         val traceMonitor = PerfettoTraceMonitor.newBuilder().enableWindowManagerTrace().build()
221         val reader =
222             traceMonitor.withTracing(resultReaderProvider = { buildResultReader(it) }) {
223                 BrowserAppHelper().launchViaIntent()
224                 device.pressHome()
225                 device.pressRecentApps()
226             }
227         val debugFile = getDebugFile("uiTrace-PerfettoTraceMonitorTest-windowManagerTracingTest")
228         debugFile.writeBytes(reader.artifact.readBytes())
229         val traceData = reader.readBytes(TraceType.PERFETTO) ?: ByteArray(0)
230         assertTrace(traceData)
231 
232         val countRows =
233             TraceProcessorSession.loadPerfettoTrace(traceData) { session ->
234                 val sql =
235                     "INCLUDE PERFETTO MODULE android.winscope.windowmanager;" +
236                         "SELECT COUNT(*) FROM android_windowmanager;"
237                 session.query(sql) { rows ->
238                     require(rows.size == 1)
239                     rows[0]["COUNT(*)"] as Long
240                 }
241             }
242 
243         Truth.assertWithMessage("TP doesn't contain WindowManager rows")
244             .that(countRows)
245             .isGreaterThan(0L)
246     }
247 
248     @Test
249     fun windowManagerDumpTest() {
250         assumeTrue(
251             "PerfettoWmTracing flag should be enabled",
252             android.tracing.Flags.perfettoWmTracing(),
253         )
254 
255         val reader =
256             PerfettoTraceMonitor.newBuilder().enableWindowManagerDump().build().withTracing(
257                 resultReaderProvider = { buildResultReader(it) }
258             ) {}
259         val debugFile = getDebugFile("uiTrace-PerfettoTraceMonitorTest-windowManagerDumpTest")
260         debugFile.writeBytes(reader.artifact.readBytes())
261         val traceData = reader.readBytes(TraceType.PERFETTO) ?: ByteArray(0)
262         assertTrace(traceData)
263 
264         val countRows =
265             TraceProcessorSession.loadPerfettoTrace(traceData) { session ->
266                 val sql =
267                     "INCLUDE PERFETTO MODULE android.winscope.windowmanager;" +
268                         "SELECT COUNT(*) FROM android_windowmanager;"
269                 session.query(sql) { rows ->
270                     require(rows.size == 1)
271                     rows[0]["COUNT(*)"] as Long
272                 }
273             }
274 
275         Truth.assertWithMessage("TP doesn't contain WindowManager dump rows")
276             .that(countRows)
277             .isEqualTo(1L)
278     }
279 
280     private fun getDebugFile(testName: String): File =
281         InstrumentationRegistry.getInstrumentation()
282             .targetContext
283             .filesDir
284             .resolve("$testName.winscope")
285 
286     private fun buildResultReader(resultData: IResultData): ResultReader =
287         ResultReader(resultData, SERVICE_TRACE_CONFIG)
288 
289     companion object {
290         @ClassRule @JvmField val ENV_CLEANUP = CleanFlickerEnvironmentRule()
291     }
292 }
293