• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.device.traces.parsers.wm
18 
19 import android.tools.common.Timestamp
20 import android.tools.common.Timestamps
21 import android.tools.common.parsers.AbstractTraceParser
22 import android.tools.common.traces.wm.Transition
23 import android.tools.common.traces.wm.TransitionChange
24 import android.tools.common.traces.wm.TransitionType
25 import android.tools.common.traces.wm.TransitionsTrace
26 import android.tools.common.traces.wm.WmTransitionData
27 import com.android.server.wm.shell.nano.TransitionTraceProto
28 
29 /** Parser for [TransitionsTrace] objects */
30 class WmTransitionTraceParser :
31     AbstractTraceParser<
32         TransitionTraceProto,
33         com.android.server.wm.shell.nano.Transition,
34         Transition,
35         TransitionsTrace
36     >() {
37     override val traceName: String = "Transition trace (WM)"
38 
createTracenull39     override fun createTrace(entries: List<Transition>): TransitionsTrace {
40         return TransitionsTrace(entries.toTypedArray())
41     }
42 
doDecodeByteArraynull43     override fun doDecodeByteArray(bytes: ByteArray): TransitionTraceProto =
44         TransitionTraceProto.parseFrom(bytes)
45 
46     override fun shouldParseEntry(entry: com.android.server.wm.shell.nano.Transition): Boolean {
47         return true
48     }
49 
getEntriesnull50     override fun getEntries(
51         input: TransitionTraceProto
52     ): List<com.android.server.wm.shell.nano.Transition> = input.transitions.toList()
53 
54     override fun getTimestamp(entry: com.android.server.wm.shell.nano.Transition): Timestamp {
55         requireValidTimestamp(entry)
56 
57         if (entry.createTimeNs != 0L) {
58             return Timestamps.from(elapsedNanos = entry.createTimeNs)
59         }
60         if (entry.sendTimeNs != 0L) {
61             return Timestamps.from(elapsedNanos = entry.sendTimeNs)
62         }
63         if (entry.abortTimeNs != 0L) {
64             return Timestamps.from(elapsedNanos = entry.abortTimeNs)
65         }
66         if (entry.finishTimeNs != 0L) {
67             return Timestamps.from(elapsedNanos = entry.finishTimeNs)
68         }
69         if (entry.startingWindowRemoveTimeNs != 0L) {
70             return Timestamps.from(elapsedNanos = entry.startingWindowRemoveTimeNs)
71         }
72 
73         error("No valid timestamp available in entry")
74     }
75 
onBeforeParsenull76     override fun onBeforeParse(input: TransitionTraceProto) {}
77 
doParsenull78     override fun doParse(
79         input: TransitionTraceProto,
80         from: Timestamp,
81         to: Timestamp,
82         addInitialEntry: Boolean
83     ): TransitionsTrace {
84         val uncompressedTransitionsTrace = super.doParse(input, from, to, addInitialEntry)
85         return uncompressedTransitionsTrace.asCompressed()
86     }
87 
doParseEntrynull88     override fun doParseEntry(entry: com.android.server.wm.shell.nano.Transition): Transition {
89         require(entry.id != 0) { "Entry needs a non null id" }
90         requireValidTimestamp(entry)
91 
92         val changes =
93             if (entry.targets.isEmpty()) null
94             else
95                 entry.targets
96                     .map {
97                         TransitionChange(
98                             TransitionType.fromInt(it.mode),
99                             it.layerId,
100                             it.windowId,
101                         )
102                     }
103                     .toTypedArray()
104 
105         return Transition(
106             entry.id,
107             wmData =
108                 WmTransitionData(
109                     createTime =
110                         if (entry.createTimeNs == 0L) null
111                         else Timestamps.from(elapsedNanos = entry.createTimeNs),
112                     sendTime =
113                         if (entry.sendTimeNs == 0L) null
114                         else Timestamps.from(elapsedNanos = entry.sendTimeNs),
115                     abortTime =
116                         if (entry.abortTimeNs == 0L) null
117                         else Timestamps.from(elapsedNanos = entry.abortTimeNs),
118                     finishTime =
119                         if (entry.finishTimeNs == 0L) null
120                         else Timestamps.from(elapsedNanos = entry.finishTimeNs),
121                     startingWindowRemoveTime =
122                         if (entry.startingWindowRemoveTimeNs == 0L) null
123                         else Timestamps.from(elapsedNanos = entry.startingWindowRemoveTimeNs),
124                     startTransactionId =
125                         if (entry.startTransactionId == 0L) null
126                         else entry.startTransactionId.toString(),
127                     finishTransactionId =
128                         if (entry.finishTransactionId == 0L) null
129                         else entry.finishTransactionId.toString(),
130                     type = if (entry.type == 0) null else TransitionType.fromInt(entry.type),
131                     changes = changes,
132                 ),
133         )
134     }
135     companion object {
requireValidTimestampnull136         private fun requireValidTimestamp(entry: com.android.server.wm.shell.nano.Transition) {
137             require(
138                 entry.createTimeNs != 0L ||
139                     entry.sendTimeNs != 0L ||
140                     entry.abortTimeNs != 0L ||
141                     entry.finishTimeNs != 0L ||
142                     entry.startingWindowRemoveTimeNs != 0L
143             ) {
144                 "Requires at least one non-null timestamp"
145             }
146         }
147     }
148 }
149