• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }