blob: cd890790a5a88591a1dcd4a9abb0e07eded8b23d [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.common.traces.events
import android.tools.common.CrossPlatform
import android.tools.common.ITrace
import android.tools.common.Timestamp
class CujTrace(override val entries: Array<Cuj>) : ITrace<Cuj> {
override fun slice(startTimestamp: Timestamp, endTimestamp: Timestamp): CujTrace {
return CujTrace(
entries
.dropWhile { it.endTimestamp < startTimestamp }
.dropLastWhile { it.startTimestamp > endTimestamp }
.toTypedArray()
)
}
companion object {
fun from(cujEvents: Array<CujEvent>): CujTrace {
val cujs = mutableListOf<Cuj>()
val sortedCujEvents = cujEvents.sortedBy { it.timestamp.unixNanos }
val startEvents = sortedCujEvents.filter { it.type == CujEvent.Companion.Type.START }
val endEvents = sortedCujEvents.filter { it.type == CujEvent.Companion.Type.END }
val canceledEvents =
sortedCujEvents.filter { it.type == CujEvent.Companion.Type.CANCEL }
for (startEvent in startEvents) {
val matchingEndEvent =
endEvents.firstOrNull {
it.cuj == startEvent.cuj && it.timestamp >= startEvent.timestamp
}
val matchingCancelEvent =
canceledEvents.firstOrNull {
it.cuj == startEvent.cuj && it.timestamp >= startEvent.timestamp
}
if (matchingCancelEvent == null && matchingEndEvent == null) {
// CUJ started but not ended within the trace
continue
}
val closingEvent =
listOf(matchingCancelEvent, matchingEndEvent).minBy {
it?.timestamp ?: CrossPlatform.timestamp.max()
}
?: error("Should have found one matching closing event")
val canceled = closingEvent.type == CujEvent.Companion.Type.CANCEL
cujs.add(
Cuj(startEvent.cuj, startEvent.timestamp, closingEvent.timestamp, canceled)
)
}
return CujTrace(cujs.toTypedArray())
}
}
}