• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.common.flicker.extractors
18 
19 import android.tools.common.Timestamp
20 import android.tools.common.Timestamps
21 import android.tools.common.io.Reader
22 import android.tools.common.traces.events.Cuj
23 import android.tools.common.traces.events.CujType
24 import android.tools.common.traces.wm.Transition
25 import kotlin.math.max
26 import kotlin.math.min
27 
28 class TaggedScenarioExtractor(
29     private val targetTag: CujType,
30     private val transitionMatcher: TransitionMatcher,
31     private val adjustCuj: CujAdjust
32 ) : ScenarioExtractor {
33     override fun extract(reader: Reader): List<TraceSlice> {
34         val cujTrace = reader.readCujTrace() ?: error("Missing CUJ trace")
35 
36         val targetCujEntries =
37             cujTrace.entries
38                 .filter { it.cuj === targetTag }
39                 .filter { !it.canceled }
40                 .map { adjustCuj.adjustCuj(it, reader) }
41 
42         if (targetCujEntries.isEmpty()) {
43             // No scenarios to extract here
44             return emptyList()
45         }
46 
47         return targetCujEntries.map { cujEntry ->
48             val associatedTransition =
49                 transitionMatcher.getMatches(reader, cujEntry).firstOrNull()
50                     ?: error("Missing associated transition")
51 
52             require(
53                 cujEntry.startTimestamp.hasAllTimestamps && cujEntry.endTimestamp.hasAllTimestamps
54             )
55 
56             val startTimestamp =
57                 estimateScenarioStartTimestamp(cujEntry, associatedTransition, reader)
58             val endTimestamp = estimateScenarioEndTimestamp(cujEntry, associatedTransition, reader)
59 
60             TraceSlice(
61                 startTimestamp,
62                 endTimestamp,
63                 associatedCuj = cujEntry.cuj,
64                 associatedTransition = associatedTransition
65             )
66         }
67     }
68 
69     private fun estimateScenarioStartTimestamp(
70         cujEntry: Cuj,
71         associatedTransition: Transition?,
72         reader: Reader
73     ): Timestamp {
74         val interpolatedStartTimestamp =
75             if (associatedTransition != null) {
76                 Utils.interpolateStartTimestampFromTransition(associatedTransition, reader)
77             } else {
78                 null
79             }
80 
81         return Timestamps.from(
82             elapsedNanos =
83                 min(
84                     cujEntry.startTimestamp.elapsedNanos,
85                     interpolatedStartTimestamp?.elapsedNanos ?: cujEntry.startTimestamp.elapsedNanos
86                 ),
87             systemUptimeNanos =
88                 min(
89                     cujEntry.startTimestamp.systemUptimeNanos,
90                     interpolatedStartTimestamp?.systemUptimeNanos
91                         ?: cujEntry.startTimestamp.systemUptimeNanos
92                 ),
93             unixNanos =
94                 min(
95                     cujEntry.startTimestamp.unixNanos,
96                     interpolatedStartTimestamp?.unixNanos ?: cujEntry.startTimestamp.unixNanos
97                 )
98         )
99     }
100 
101     private fun estimateScenarioEndTimestamp(
102         cujEntry: Cuj,
103         associatedTransition: Transition?,
104         reader: Reader
105     ): Timestamp {
106         val interpolatedEndTimestamp =
107             if (associatedTransition != null) {
108                 Utils.interpolateFinishTimestampFromTransition(associatedTransition, reader)
109             } else {
110                 null
111             }
112 
113         return Timestamps.from(
114             elapsedNanos =
115                 max(
116                     cujEntry.endTimestamp.elapsedNanos,
117                     interpolatedEndTimestamp?.elapsedNanos ?: -1L
118                 ),
119             systemUptimeNanos =
120                 max(
121                     cujEntry.endTimestamp.systemUptimeNanos,
122                     interpolatedEndTimestamp?.systemUptimeNanos ?: -1L
123                 ),
124             unixNanos =
125                 max(cujEntry.endTimestamp.unixNanos, interpolatedEndTimestamp?.unixNanos ?: -1L)
126         )
127     }
128 }
129