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 wmSubject = WindowManagerTraceSubject.assertThat(wmTrace)
65         val layersSubject = LayersTraceSubject.assertThat(layersTrace)
66         val assertions = assertions.filter { it.category == categoryKey }
67         return runAssertionsOnSubjects(tag, wmSubject, layersSubject, assertions)
68     }
69 
70     private fun runAssertionsOnSubjects(
71         tag: Tag,
72         wmSubject: WindowManagerTraceSubject,
73         layerSubject: LayersTraceSubject,
74         assertions: List<AssertionData>
75     ): Map<Long, MutableList<Error>> {
76         val errors = mutableMapOf<Long, MutableList<Error>>()
77 
78         try {
79             assertions.forEach {
80                 val assertion = it.assertion
81                 logger.invoke("Running assertion $assertion")
82                 val result = assertion.runCatching { evaluate(tag, wmSubject, layerSubject) }
83                 if (result.isFailure) {
84                     val layer = assertion.getFailureLayer(tag, wmSubject, layerSubject)
85                     val window = assertion.getFailureWindow(tag, wmSubject, layerSubject)
86                     val exception = result.exceptionOrNull() as FlickerSubjectException
87 
88                     errors.putIfAbsent(exception.timestamp, mutableListOf())
89                     val errorEntry = Error(
90                         stacktrace = exception.stackTraceToString(),
91                         message = exception.message,
92                         layerId = layer?.id ?: 0,
93                         windowToken = window?.token ?: "",
94                         assertionName = assertion.name
95                     )
96                     errors.getValue(exception.timestamp).add(errorEntry)
97                 }
98             }
99         } catch (e: NoSuchMethodException) {
100             Log.e("$FLICKER_TAG-ASSERT", "Assertion method not found", e)
101         } catch (e: SecurityException) {
102             Log.e("$FLICKER_TAG-ASSERT", "Unable to get assertion method", e)
103         }
104 
105         return errors
106     }
107 
108     private fun buildErrorTrace(errors: MutableMap<Long, MutableList<Error>>): ErrorTrace {
109         val errorStates = errors.map { entry ->
110             val timestamp = entry.key
111             val stateTags = entry.value
112             ErrorState(stateTags.toTypedArray(), timestamp.toString())
113         }
114         return ErrorTrace(errorStates.toTypedArray(), source = "")
115     }
116 }