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