1 /* <lambda>null2 * Copyright (C) 2021 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 com.android.server.wm.flicker.service.assertors 18 19 import android.util.Log 20 import com.android.server.wm.flicker.FLICKER_TAG 21 import com.android.server.wm.flicker.traces.FlickerSubjectException 22 import com.android.server.wm.flicker.traces.layers.LayersTraceSubject 23 import com.android.server.wm.flicker.traces.windowmanager.WindowManagerTraceSubject 24 import com.android.server.wm.traces.common.errors.Error 25 import com.android.server.wm.traces.common.errors.ErrorState 26 import com.android.server.wm.traces.common.errors.ErrorTrace 27 import com.android.server.wm.traces.common.layers.LayersTrace 28 import com.android.server.wm.traces.common.service.ITransitionAssertor 29 import com.android.server.wm.traces.common.tags.Tag 30 import com.android.server.wm.traces.common.windowmanager.WindowManagerTrace 31 32 /** 33 * Class that runs FASS assertions. 34 */ 35 class TransitionAssertor( 36 private val assertions: List<AssertionData>, 37 private val logger: (String) -> Unit 38 ) : ITransitionAssertor { 39 /** {@inheritDoc} */ 40 override fun analyze( 41 tag: Tag, 42 wmTrace: WindowManagerTrace, 43 layersTrace: LayersTrace 44 ): ErrorTrace { 45 val errorStates = mutableMapOf<Long, MutableList<Error>>() 46 47 errorStates.putAll( 48 runCategoryAssertions(tag, wmTrace, layersTrace, AssertionConfigParser.PRESUBMIT_KEY)) 49 errorStates.putAll( 50 runCategoryAssertions(tag, wmTrace, layersTrace, AssertionConfigParser.POSTSUBMIT_KEY)) 51 errorStates.putAll( 52 runCategoryAssertions(tag, wmTrace, layersTrace, AssertionConfigParser.FLAKY_KEY)) 53 54 return buildErrorTrace(errorStates) 55 } 56 57 private fun runCategoryAssertions( 58 tag: Tag, 59 wmTrace: WindowManagerTrace, 60 layersTrace: LayersTrace, 61 categoryKey: String 62 ): Map<Long, MutableList<Error>> { 63 logger.invoke("Running assertions for $tag $categoryKey") 64 val assertions = assertions.filter { it.category == categoryKey } 65 return runAssertionsOnSubjects(tag, wmTrace, layersTrace, assertions) 66 } 67 68 private fun runAssertionsOnSubjects( 69 tag: Tag, 70 wmTrace: WindowManagerTrace, 71 layersTrace: LayersTrace, 72 assertions: List<AssertionData> 73 ): Map<Long, MutableList<Error>> { 74 val errors = mutableMapOf<Long, MutableList<Error>>() 75 76 try { 77 assertions.forEach { 78 val assertion = it.assertion 79 logger.invoke("Running assertion $assertion") 80 val wmSubject = WindowManagerTraceSubject.assertThat(wmTrace) 81 val layersSubject = LayersTraceSubject.assertThat(layersTrace) 82 val result = assertion.runCatching { evaluate(tag, wmSubject, layersSubject) } 83 if (result.isFailure) { 84 val layer = assertion.getFailureLayer(tag, wmSubject, layersSubject) 85 val window = assertion.getFailureWindow(tag, wmSubject, layersSubject) 86 val exception = result.exceptionOrNull() ?: error("Exception not found") 87 // if it's not a flicker exception, we don't know what 88 // happened, raise the exception back to the test 89 if (exception !is FlickerSubjectException) { 90 throw exception 91 } 92 errors.putIfAbsent(exception.timestamp, mutableListOf()) 93 val errorEntry = Error( 94 stacktrace = exception.stackTraceToString(), 95 message = exception.message, 96 layerId = layer?.id ?: 0, 97 windowToken = window?.token ?: "", 98 assertionName = assertion.name 99 ) 100 errors.getValue(exception.timestamp).add(errorEntry) 101 } 102 } 103 } catch (e: NoSuchMethodException) { 104 Log.e("$FLICKER_TAG-ASSERT", "Assertion method not found", e) 105 } catch (e: SecurityException) { 106 Log.e("$FLICKER_TAG-ASSERT", "Unable to get assertion method", e) 107 } 108 109 return errors 110 } 111 112 private fun buildErrorTrace(errors: MutableMap<Long, MutableList<Error>>): ErrorTrace { 113 val errorStates = errors.map { entry -> 114 val timestamp = entry.key 115 val stateTags = entry.value 116 ErrorState(stateTags.toTypedArray(), timestamp.toString()) 117 } 118 return ErrorTrace(errorStates.toTypedArray()) 119 } 120 }