blob: 87863aa3caf5cd3afc45d4444aac09e84c74c438 [file] [log] [blame]
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.tools.device.traces.parsers.wm
import android.tools.common.Timestamp
import android.tools.common.Timestamps
import android.tools.common.parsers.AbstractTraceParser
import android.tools.common.traces.wm.ShellTransitionData
import android.tools.common.traces.wm.Transition
import android.tools.common.traces.wm.TransitionsTrace
import com.android.wm.shell.nano.WmShellTransitionTraceProto
/** Parser for [TransitionsTrace] objects */
class ShellTransitionTraceParser :
AbstractTraceParser<
WmShellTransitionTraceProto,
com.android.wm.shell.nano.Transition,
Transition,
TransitionsTrace
>() {
override val traceName: String = "Transition trace (shell)"
override fun createTrace(entries: List<Transition>): TransitionsTrace {
return TransitionsTrace(entries.toTypedArray())
}
override fun doDecodeByteArray(bytes: ByteArray): WmShellTransitionTraceProto =
WmShellTransitionTraceProto.parseFrom(bytes)
override fun shouldParseEntry(entry: com.android.wm.shell.nano.Transition): Boolean {
return true
}
override fun getEntries(
input: WmShellTransitionTraceProto
): List<com.android.wm.shell.nano.Transition> = input.transitions.toList()
override fun getTimestamp(entry: com.android.wm.shell.nano.Transition): Timestamp {
requireValidTimestamp(entry)
if (entry.dispatchTimeNs != 0L) {
return Timestamps.from(elapsedNanos = entry.dispatchTimeNs)
}
if (entry.mergeRequestTimeNs != 0L) {
return Timestamps.from(elapsedNanos = entry.mergeRequestTimeNs)
}
if (entry.mergeTimeNs != 0L) {
return Timestamps.from(elapsedNanos = entry.mergeTimeNs)
}
if (entry.abortTimeNs != 0L) {
return Timestamps.from(elapsedNanos = entry.abortTimeNs)
}
error("No valid timestamp for entry")
}
private val handlerMapping = mutableMapOf<Int, String>()
override fun onBeforeParse(input: WmShellTransitionTraceProto) {
handlerMapping.clear()
for (mapping in input.handlerMappings) {
handlerMapping[mapping.id] = mapping.name
}
}
override fun doParse(
input: WmShellTransitionTraceProto,
from: Timestamp,
to: Timestamp,
addInitialEntry: Boolean
): TransitionsTrace {
val uncompressedTransitionsTrace = super.doParse(input, from, to, addInitialEntry)
return uncompressedTransitionsTrace.asCompressed()
}
override fun doParseEntry(entry: com.android.wm.shell.nano.Transition): Transition {
require(entry.id != 0) { "Entry needs a non null id" }
requireValidTimestamp(entry)
return Transition(
entry.id,
shellData =
ShellTransitionData(
dispatchTime =
if (entry.dispatchTimeNs == 0L) {
null
} else {
Timestamps.from(elapsedNanos = entry.dispatchTimeNs)
},
mergeRequestTime =
if (entry.mergeRequestTimeNs == 0L) {
null
} else {
Timestamps.from(elapsedNanos = entry.mergeRequestTimeNs)
},
mergeTime =
if (entry.mergeTimeNs == 0L) {
null
} else {
Timestamps.from(elapsedNanos = entry.mergeTimeNs)
},
abortTime =
if (entry.abortTimeNs == 0L) {
null
} else {
Timestamps.from(elapsedNanos = entry.abortTimeNs)
},
handler = handlerMapping[entry.handler],
mergeTarget = if (entry.mergeTarget == 0) null else entry.mergeTarget
)
)
}
companion object {
private fun requireValidTimestamp(entry: com.android.wm.shell.nano.Transition) {
require(
entry.dispatchTimeNs != 0L ||
entry.mergeRequestTimeNs != 0L ||
entry.mergeTimeNs != 0L ||
entry.abortTimeNs != 0L
) {
"Requires at least one non-null timestamp"
}
}
}
}