1 /* 2 * 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.events 18 19 import android.tools.io.TraceType 20 import android.tools.monitors.TraceMonitorTest 21 import android.tools.testutils.CleanFlickerEnvironmentRule 22 import android.tools.testutils.newTestResultWriter 23 import android.tools.traces.TRACE_CONFIG_REQUIRE_CHANGES 24 import android.tools.traces.events.CujEvent 25 import android.tools.traces.events.CujType 26 import android.tools.traces.events.EventLog.Companion.MAGIC_NUMBER 27 import android.tools.traces.events.FocusEvent 28 import android.tools.traces.events.UnknownCuj 29 import android.tools.traces.io.ResultReader 30 import android.tools.traces.monitors.events.EventLogMonitor 31 import android.tools.traces.now 32 import android.util.EventLog 33 import com.android.internal.jank.EventLogTags 34 import com.google.common.truth.Truth 35 import org.junit.Assert.assertEquals 36 import org.junit.Assert.assertTrue 37 import org.junit.ClassRule 38 import org.junit.Test 39 40 /** 41 * Contains [EventLogMonitor] tests. To run this test: {@code atest 42 * FlickerLibTest:EventLogMonitorTest} 43 */ 44 class EventLogMonitorTest : TraceMonitorTest<EventLogMonitor>() { 45 override val traceType = TraceType.EVENT_LOG 46 getMonitornull47 override fun getMonitor(): EventLogMonitor = EventLogMonitor() 48 49 override fun assertTrace(traceData: ByteArray) { 50 Truth.assertThat(traceData.size).isAtLeast(MAGIC_NUMBER.toByteArray().size) 51 Truth.assertThat(traceData.slice(0 until MAGIC_NUMBER.toByteArray().size)) 52 .isEqualTo(MAGIC_NUMBER.toByteArray().asList()) 53 } 54 55 @Test canCaptureFocusEventLogsnull56 fun canCaptureFocusEventLogs() { 57 val monitor = EventLogMonitor() 58 EventLog.writeEvent( 59 INPUT_FOCUS_TAG, 60 "Focus entering 111 com.android.phone/" + 61 "com.android.phone.settings.fdn.FdnSetting (server)", 62 "reason=test", 63 ) 64 EventLog.writeEvent( 65 INPUT_FOCUS_TAG, 66 "Focus leaving 222 com.google.android.apps.nexuslauncher/" + 67 "com.google.android.apps.nexuslauncher.NexusLauncherActivity (server)", 68 "reason=test", 69 ) 70 EventLog.writeEvent( 71 INPUT_FOCUS_TAG, 72 "Focus entering 333 com.android.phone/" + 73 "com.android.phone.settings.fdn.FdnSetting (server)", 74 "reason=test", 75 ) 76 monitor.start() 77 EventLog.writeEvent( 78 INPUT_FOCUS_TAG, 79 "Focus leaving 4749f88 com.android.phone/" + 80 "com.android.phone.settings.fdn.FdnSetting (server)", 81 "reason=test", 82 ) 83 EventLog.writeEvent( 84 INPUT_FOCUS_TAG, 85 "Focus entering 7c01447 com.android.phone/" + 86 "com.android.phone.settings.fdn.FdnSetting (server)", 87 "reason=test", 88 ) 89 val writer = newTestResultWriter() 90 monitor.stop(writer) 91 EventLog.writeEvent( 92 INPUT_FOCUS_TAG, 93 "Focus entering 2aa30cd com.android.phone/" + 94 "com.android.phone.settings.fdn.FdnSetting (server)", 95 "reason=test", 96 ) 97 val result = writer.write() 98 99 val reader = ResultReader(result, TRACE_CONFIG_REQUIRE_CHANGES) 100 val eventLog = reader.readEventLogTrace() 101 requireNotNull(eventLog) { "EventLog was null" } 102 103 assertEquals(2, eventLog.focusEvents.size) 104 assertEquals( 105 "4749f88 com.android.phone/com.android.phone.settings.fdn.FdnSetting (server)", 106 eventLog.focusEvents.first().window, 107 ) 108 assertEquals(FocusEvent.Type.LOST, eventLog.focusEvents.first().type) 109 assertEquals( 110 "7c01447 com.android.phone/com.android.phone.settings.fdn.FdnSetting (server)", 111 eventLog.focusEvents.drop(1).first().window, 112 ) 113 assertEquals(FocusEvent.Type.GAINED, eventLog.focusEvents.drop(1).first().type) 114 assertTrue( 115 eventLog.focusEvents.first().timestamp <= eventLog.focusEvents.drop(1).first().timestamp 116 ) 117 assertEquals(eventLog.focusEvents.first().reason, "test") 118 } 119 120 @Test onlyCapturesLastTransitionnull121 fun onlyCapturesLastTransition() { 122 val monitor = EventLogMonitor() 123 monitor.start() 124 EventLog.writeEvent( 125 INPUT_FOCUS_TAG, 126 "Focus leaving 11111 com.android.phone/" + 127 "com.android.phone.settings.fdn.FdnSetting (server)", 128 "reason=test", 129 ) 130 EventLog.writeEvent( 131 INPUT_FOCUS_TAG, 132 "Focus entering 22222 com.android.phone/" + 133 "com.android.phone.settings.fdn.FdnSetting (server)", 134 "reason=test", 135 ) 136 monitor.stop(newTestResultWriter()) 137 138 monitor.start() 139 EventLog.writeEvent( 140 INPUT_FOCUS_TAG, 141 "Focus leaving 479f88 com.android.phone/" + 142 "com.android.phone.settings.fdn.FdnSetting (server)", 143 "reason=test", 144 ) 145 EventLog.writeEvent( 146 INPUT_FOCUS_TAG, 147 "Focus entering 7c01447 com.android.phone/" + 148 "com.android.phone.settings.fdn.FdnSetting (server)", 149 "reason=test", 150 ) 151 val writer = newTestResultWriter() 152 monitor.stop(writer) 153 val result = writer.write() 154 155 val reader = ResultReader(result, TRACE_CONFIG_REQUIRE_CHANGES) 156 val eventLog = reader.readEventLogTrace() 157 requireNotNull(eventLog) { "EventLog was null" } 158 159 assertEquals(2, eventLog.focusEvents.size) 160 assertEquals( 161 "479f88 com.android.phone/com.android.phone.settings.fdn.FdnSetting (server)", 162 eventLog.focusEvents.first().window, 163 ) 164 assertEquals(FocusEvent.Type.LOST, eventLog.focusEvents.first().type) 165 assertEquals( 166 "7c01447 com.android.phone/com.android.phone.settings.fdn.FdnSetting (server)", 167 eventLog.focusEvents.drop(1).first().window, 168 ) 169 assertEquals(FocusEvent.Type.GAINED, eventLog.focusEvents.drop(1).first().type) 170 assertTrue( 171 eventLog.focusEvents.first().timestamp <= eventLog.focusEvents.drop(1).first().timestamp 172 ) 173 } 174 175 @Test ignoreFocusRequestLogsnull176 fun ignoreFocusRequestLogs() { 177 val monitor = EventLogMonitor() 178 monitor.start() 179 EventLog.writeEvent( 180 INPUT_FOCUS_TAG, 181 "Focus leaving 4749f88 com.android.phone/" + 182 "com.android.phone.settings.fdn.FdnSetting (server)", 183 "reason=test", 184 ) 185 EventLog.writeEvent( 186 INPUT_FOCUS_TAG, 187 "Focus request 111 com.android.phone/" + 188 "com.android.phone.settings.fdn.FdnSetting (server)", 189 "reason=test", 190 ) 191 EventLog.writeEvent( 192 INPUT_FOCUS_TAG, 193 "Focus entering 7c01447 com.android.phone/" + 194 "com.android.phone.settings.fdn.FdnSetting (server)", 195 "reason=test", 196 ) 197 val writer = newTestResultWriter() 198 monitor.stop(writer) 199 val result = writer.write() 200 201 val reader = ResultReader(result, TRACE_CONFIG_REQUIRE_CHANGES) 202 val eventLog = reader.readEventLogTrace() 203 requireNotNull(eventLog) { "EventLog was null" } 204 205 assertEquals(2, eventLog.focusEvents.size) 206 assertEquals( 207 "4749f88 com.android.phone/com.android.phone.settings.fdn.FdnSetting (server)", 208 eventLog.focusEvents.first().window, 209 ) 210 assertEquals(FocusEvent.Type.LOST, eventLog.focusEvents.first().type) 211 assertEquals( 212 "7c01447 com.android.phone/com.android.phone.settings.fdn.FdnSetting (server)", 213 eventLog.focusEvents.drop(1).first().window, 214 ) 215 assertEquals(FocusEvent.Type.GAINED, eventLog.focusEvents.drop(1).first().type) 216 assertTrue( 217 eventLog.focusEvents.first().timestamp <= eventLog.focusEvents.drop(1).first().timestamp 218 ) 219 assertEquals(eventLog.focusEvents.first().reason, "test") 220 } 221 222 @Test savesEventLogsToFilenull223 fun savesEventLogsToFile() { 224 val monitor = EventLogMonitor() 225 monitor.start() 226 EventLog.writeEvent( 227 INPUT_FOCUS_TAG, 228 "Focus leaving 4749f88 com.android.phone/" + 229 "com.android.phone.settings.fdn.FdnSetting (server)", 230 "reason=test", 231 ) 232 EventLog.writeEvent( 233 INPUT_FOCUS_TAG, 234 "Focus request 111 com.android.phone/" + 235 "com.android.phone.settings.fdn.FdnSetting (server)", 236 "reason=test", 237 ) 238 EventLog.writeEvent( 239 INPUT_FOCUS_TAG, 240 "Focus entering 7c01447 com.android.phone/" + 241 "com.android.phone.settings.fdn.FdnSetting (server)", 242 "reason=test", 243 ) 244 val writer = newTestResultWriter() 245 monitor.stop(writer) 246 val result = writer.write() 247 val reader = ResultReader(result, TRACE_CONFIG_REQUIRE_CHANGES) 248 249 Truth.assertWithMessage("Trace not found") 250 .that(reader.hasTraceFile(TraceType.EVENT_LOG)) 251 .isTrue() 252 } 253 254 @Test cropsEventsFromBeforeMonitorStartnull255 fun cropsEventsFromBeforeMonitorStart() { 256 val monitor = EventLogMonitor() 257 258 EventLog.writeEvent( 259 INPUT_FOCUS_TAG, 260 "Focus leaving 4749f88 com.android.phone/" + 261 "com.android.phone.settings.fdn.FdnSetting (server)", 262 "reason=test", 263 ) 264 265 monitor.start() 266 267 EventLog.writeEvent( 268 INPUT_FOCUS_TAG, 269 "Focus entering 7c01447 com.android.phone/" + 270 "com.android.phone.settings.fdn.FdnSetting (server)", 271 "reason=test", 272 ) 273 274 val writer = newTestResultWriter() 275 monitor.stop(writer) 276 val result = writer.write() 277 278 val reader = ResultReader(result, TRACE_CONFIG_REQUIRE_CHANGES) 279 val eventLog = reader.readEventLogTrace() ?: error("EventLog should have been created") 280 281 Truth.assertThat(eventLog.focusEvents).hasSize(1) 282 Truth.assertThat(eventLog.focusEvents.first().type).isEqualTo(FocusEvent.Type.GAINED) 283 } 284 285 @Test cropsEventsOutsideOfTransitionTimesnull286 fun cropsEventsOutsideOfTransitionTimes() { 287 val monitor = EventLogMonitor() 288 val writer = newTestResultWriter() 289 monitor.start() 290 291 EventLog.writeEvent( 292 INPUT_FOCUS_TAG, 293 "Focus leaving 4749f88 com.android.phone/" + 294 "com.android.phone.settings.fdn.FdnSetting (server)", 295 "reason=test", 296 ) 297 298 writer.setTransitionStartTime(now()) 299 300 EventLog.writeEvent( 301 INPUT_FOCUS_TAG, 302 "Focus entering 7c01447 com.android.phone/" + 303 "com.android.phone.settings.fdn.FdnSetting (server)", 304 "reason=test", 305 ) 306 307 writer.setTransitionEndTime(now()) 308 309 EventLog.writeEvent( 310 INPUT_FOCUS_TAG, 311 "Focus entering 7c01447 com.android.phone/" + 312 "com.android.phone.settings.fdn.FdnSetting (server)", 313 "reason=test", 314 ) 315 316 monitor.stop(writer) 317 val result = writer.write() 318 319 val reader = ResultReader(result, TRACE_CONFIG_REQUIRE_CHANGES) 320 val eventLog = reader.readEventLogTrace() ?: error("EventLog should have been created") 321 322 Truth.assertThat(eventLog.focusEvents).hasSize(1) 323 Truth.assertThat(eventLog.focusEvents.first().hasFocus()).isTrue() 324 } 325 326 @Test canCaptureCujEventsnull327 fun canCaptureCujEvents() { 328 val monitor = EventLogMonitor() 329 val writer = newTestResultWriter() 330 monitor.start() 331 var now = now() 332 EventLogTags.writeJankCujEventsBeginRequest( 333 CujType.CUJ_NOTIFICATION_APP_START.ordinal, 334 now.unixNanos, 335 now.elapsedNanos, 336 now.systemUptimeNanos, 337 "", 338 ) 339 now = now() 340 EventLogTags.writeJankCujEventsEndRequest( 341 CujType.CUJ_NOTIFICATION_APP_START.ordinal, 342 now.unixNanos, 343 now.elapsedNanos, 344 now.systemUptimeNanos, 345 ) 346 monitor.stop(writer) 347 val result = writer.write() 348 349 val reader = ResultReader(result, TRACE_CONFIG_REQUIRE_CHANGES) 350 val eventLog = reader.readEventLogTrace() ?: error("EventLog should have been created") 351 352 assertEquals(2, eventLog.cujEvents.size) 353 } 354 355 @Test collectsCujEventDatanull356 fun collectsCujEventData() { 357 val monitor = EventLogMonitor() 358 val writer = newTestResultWriter() 359 monitor.start() 360 val now = now() 361 EventLogTags.writeJankCujEventsBeginRequest( 362 CujType.CUJ_LAUNCHER_QUICK_SWITCH.id, 363 now.unixNanos, 364 now.elapsedNanos, 365 now.systemUptimeNanos, 366 "", 367 ) 368 EventLogTags.writeJankCujEventsEndRequest( 369 CujType.CUJ_LAUNCHER_ALL_APPS_SCROLL.id, 370 now.unixNanos + 1, 371 now.elapsedNanos + 1, 372 now.systemUptimeNanos + 1, 373 ) 374 EventLogTags.writeJankCujEventsCancelRequest( 375 CujType.CUJ_LOCKSCREEN_LAUNCH_CAMERA.id, 376 now.unixNanos + 2, 377 now.elapsedNanos + 2, 378 now.systemUptimeNanos + 2, 379 ) 380 monitor.stop(writer) 381 val result = writer.write() 382 383 val reader = ResultReader(result, TRACE_CONFIG_REQUIRE_CHANGES) 384 val eventLog = reader.readEventLogTrace() ?: error("EventLog should have been created") 385 386 // There maybe be some random CUJ events triggered in the background 387 val cujEvents = 388 eventLog.cujEvents.filter { 389 now.unixNanos <= it.timestamp.unixNanos && 390 it.timestamp.unixNanos <= (now.unixNanos + 2) 391 } 392 393 Truth.assertThat(cujEvents).hasSize(3) 394 395 Truth.assertThat(cujEvents.first().type).isEqualTo(CujEvent.Companion.Type.START) 396 Truth.assertThat(cujEvents.first().cuj).isEqualTo(CujType.CUJ_LAUNCHER_QUICK_SWITCH) 397 398 Truth.assertThat(cujEvents.drop(1).first().type).isEqualTo(CujEvent.Companion.Type.END) 399 Truth.assertThat(cujEvents.drop(1).first().cuj) 400 .isEqualTo(CujType.CUJ_LAUNCHER_ALL_APPS_SCROLL) 401 402 Truth.assertThat(cujEvents.drop(2).first().type).isEqualTo(CujEvent.Companion.Type.CANCEL) 403 Truth.assertThat(cujEvents.drop(2).first().cuj) 404 .isEqualTo(CujType.CUJ_LOCKSCREEN_LAUNCH_CAMERA) 405 } 406 407 @Test canParseHandleUnknownCujTypesnull408 fun canParseHandleUnknownCujTypes() { 409 val unknownCujId = Int.MAX_VALUE 410 val monitor = EventLogMonitor() 411 val writer = newTestResultWriter() 412 monitor.start() 413 var now = now() 414 EventLogTags.writeJankCujEventsBeginRequest( 415 unknownCujId, 416 now.unixNanos, 417 now.elapsedNanos, 418 now.systemUptimeNanos, 419 "", 420 ) 421 now = now() 422 EventLogTags.writeJankCujEventsEndRequest( 423 unknownCujId, 424 now.unixNanos, 425 now.elapsedNanos, 426 now.systemUptimeNanos, 427 ) 428 now = now() 429 EventLogTags.writeJankCujEventsCancelRequest( 430 unknownCujId, 431 now.unixNanos, 432 now.elapsedNanos, 433 now.systemUptimeNanos, 434 ) 435 monitor.stop(writer) 436 val result = writer.write() 437 438 val reader = ResultReader(result, TRACE_CONFIG_REQUIRE_CHANGES) 439 val eventLog = reader.readEventLogTrace() 440 requireNotNull(eventLog) { "EventLog should have been created" } 441 442 assertEquals(3, eventLog.cujEvents.size) 443 Truth.assertThat(eventLog.cujEvents.first().cuj).isEqualTo(UnknownCuj(unknownCujId)) 444 Truth.assertThat(eventLog.cujEvents.drop(1).first().cuj).isEqualTo(UnknownCuj(unknownCujId)) 445 Truth.assertThat(eventLog.cujEvents.drop(2).first().cuj).isEqualTo(UnknownCuj(unknownCujId)) 446 } 447 448 private companion object { 449 const val INPUT_FOCUS_TAG = 62001 450 451 @ClassRule @JvmField val ENV_CLEANUP = CleanFlickerEnvironmentRule() 452 } 453 } 454